查看: 4149|回复: 1

[资料] MSP430G2231 正弦波发生器(网友作品)

[复制链接]
  • TA的每日心情
    奋斗
    2020-9-28 10:10
  • 签到天数: 1018 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2012-8-23 11:01:33 | 显示全部楼层 |阅读模式
    分享到:

    1.jpg
    由于使用到的DA芯片使用的是spi接口的通信,所以着重研究了一下SPI模块。G2系列的串行通信模块即可以配置成SPI的主或从方式,又可以配置成IIC模式,不需要使用软件模拟时序,大大方便了开发。
    SPI通信,SPI通信属于同步通信。即发送者和接受者使用同一个时钟,在相同时钟的驱动下工作,与常见的串口通信有所区别。考虑到DA的时序,时钟的频率需要在1Mhz一下,DA在下降沿采集数据,数据线空闲时置低。由于MSP430只需要发送数据,可不需要输入的数据线。
    顺着左下角的紫色箭头浏览SPI的时钟线。首先是选择SPI的时钟源。USISELx 寄存器用于选择SPI时钟的来源。可以选择辅助时钟、系统子时钟、定时器模块产生的时钟等。USIDIVx用于选择时钟分频的系数,用于获得需要的时钟频率。USIMST寄存器用于选择430单片机作为SPI的主设备或者从设备。在此设计中430 用作主设备,向外提供时钟。时钟一路向右,为从设备提供时钟,;另一路向左为430的SPI模块提供时钟。寄存器USICKPH 和USICKPL用于选择时钟的相位和决定在上升沿或者下降沿采样。
    USISR寄存器由两个8bit寄存器组成,用于存放SPI的收发数据。USICNTx 模块是计数模块,控制要发送的数据的位数。当USISWRST置位的时候,可以时能数据模块和计数模块,spi通信就开始工作了。


       配合DA分析一下SPI寄存器模块的设计。下面是TLV5620的时序图。


    2.jpg
    每一次模式转换需要11位数据。其中A1,A0 用于选择使用哪个通道。一共有4路DA通道,由于仅用到A通道,前两位为00。


    3.jpg
    RNG位用于选择倍数,这里最大输出选择的参考电压的一倍,此位设置为0即可。D7,D6,D5,D4,D3,D2,D1,D0为8位数据用于控制输出电压,先发送最高有效位。数据线上一次传送11位数据,因此计数器中存入11,USI16B置高后,数据存储单元最多可以存放16位数据。USILSB用于选择先发送最高有效位。 LOAD这个线需要在11个时钟过后发送一个低脉冲,通知DA更新DA输出。至此,一帧数据完成发送。



    橘黄色的线指示中断信号,USICNTx中的数在每一个时钟沿后减一,减到0后触发中断。中断信号送到分频器模块,停止寄存器的输出。当需要再次发送数据的时候,向USICNTx写入传送位数,即可清除中断信号。


    程序的流程大体是 1)配置好SPI模块的各个寄存器的数据,使得其能够工作在需要的模式。 2)使能计数器和移位器模块,使得SPI开始工作 3)进入低功耗的模式 4)传送完成后引发中断 5)先装载传送数据,再存入发送数据个数启动下一次的数据传送


    4.jpg

    作为信号源加入一级跟随器,使得DA的输出具有驱动能力,同时避免负载对输出端口的影响。跟随级后面添加有源或无源的巴特沃斯滤波器,滤除信号以外频率的信号。作为一个练手的东西,就不做了。输出数据可以用matlab生成。





    -------------------------------------------------------------    实物图片           -------------------------------------------------------------







    5.jpg


    该图为使用面包板搭建的电路,可以方便的验证电路。




    6.jpg

    该图为信号源输出的正弦波



    7.jpg

    输出波形的FFT变换,可以看到有两个峰值-------------直流成分和正弦波成分。



    ---------------------------------------------------程序部分-----------------------------------------------------------------------------------

    #include<msp430g2231.h>
               #include"source.h"
              #define DAC_UPDATE BIT4
    unsigned char i=0;
    void update_spi(unsigned char i);
    #define debug
    #ifdef  debug
    void main(void)
    {
    WDTCTL = WDTPW + WDTHOLD;                     //关闭看门狗
    BCSCTL1 = CALBC1_1MHZ;                        // Set range
    DCOCTL = CALDCO_1MHZ;                         // Set DCO step + modulation */
    P1DIR |= DAC_UPDATE;                          //设置成为输出
    P1OUT |= DAC_UPDATE;                          //输出高电平
    P1REN |= DAC_UPDATE;                          // 输出口上拉电阻
    USICKCTL =USISSEL_2;                          // 16 SMCLK   选择时钟源为SMLK
    USICKCTL &=   ~USICKPL;
    USICTL0  &=   ~USILSB;                         //清零从高位开始发送
    //BCSCTL3 |= LFXT1S_2;                        // ACLK = VLO
    USICTL1 &=~(USII2C+USICKPH);                  //关闭I2C模式,下降沿发送数据
    USICNT  |= USI16B;                            //允许使用高八位
    USICTL1 |= USIIE;                             // Counter interrupt, flag remains set
    USICTL0 |= USIPE5 + USIPE6 + USIMST + USIOE;  // USIPE6 SDO打开,输出    USIPE7 SDI打开,输入    USIPE8 SCLK 时钟输出   设置为主模式
    USICTL0 &= ~USISWRST;                         // USI released for operation
      _BIS_SR(LPM0_bits + GIE);                   // Enter LPM0 w/ interrupt

    while(1)
    {
    }
    }
    #pragma vector=USI_VECTOR
    __interrupt void universal_serial_interface(void)
    {
    //USICNT |=USIIFGCC;
      //P1OUT ^= 0x01;                        // Toggle P1.0 using exclusive-OR
      P1DIR |=0x10;//DAC_UPDATE;                    //设置成为输出
      P1OUT   &= ~DAC_UPDATE;
      if(i>=199)i=0;
      else i++;
      update_spi(i);
      //USISRH  =  0x07;
      //USISRL  =  0x54;

      //P1OUT =  0x10;                         // P1.4 set, else reset
      //P1REN |= 0x10;                         // P1.4 pullup
    }
    void update_spi(unsigned char i)
    {
      
       USISRH  =  digital_signal >>3;
       USISRL   = (digital_signal & 0x07)<<5;
       P1OUT   |= DAC_UPDATE;
       USICNT  |= 0x0B;                         // re-load counter
    }
    #endif
    #ifndef  debug
    void main()
    {
    WDTCTL = WDTPW + WDTHOLD;                     //关闭看门狗
    P1DIR |=0x10;//DAC_UPDATE;                    //设置成为输出
    P1OUT |=0x10;//DAC_UPDATE;                    //输出高电平
    while(1);
    }
    #endif


    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2016-8-25 12:42
  • 签到天数: 692 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2012-8-29 19:21:58 | 显示全部楼层
    好资料,顶一下!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-19 10:40 , Processed in 0.114820 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.