在线情况
楼主
  • 头像
  • 级别
    • 积分9
    • 经验613
    • 文章19
    • 注册2008-12-14
    MSP430F16x产生正弦信号[转载分享]
    注:此贴是转别人的,希望对大家有帮助

    msp430产生正弦信号(一)
    利用msp430f1611中的DAC12产生频率在200-2000hz可调的正弦波
      单片机处理的是数字信号,而正弦波是一个连续变化的模拟量, 所以就必须对一个周期内的正弦波形进行有限点数的采样。一个周期内选择的点数越多,得到的波形就越接近真实的波形,但另一方面。 由于单片机处理的速度有限, 点数如果选取过多, 单片机就无法处理其它程序,而且正弦破频率也无法降低。

      单片机计算正弦函数需要大量的时间(偶的2274根本就没有算出来,郁闷),所以我选择了使用正弦函数表的方式,正弦函数表是我用电子表格中的计算功能按照自己设定的计算公式算出来的,我使用的计算公式:=(SIN(3.6*3.14/180*A0)+1)/2。我在正弦函数表中存了100个数据,故360/100=3.6。A0-A100中存了数字0-99。加1除2是为了将函数值从-1~1调整到0~1。程序表格中再将各函数值乘以DAC的精度的倒数即4095。

            由于要用到DAC,所以我放弃了2274,使用了内部有DAC模块的1611(从TI上申请的样片,哈哈)。制作好函数表,然后就可以使用定时器按正弦规律周期性的改变DAC12_DAT的值,在主程序中设置好定时器,DAC和系统主频,就可以进入低功耗模式了。 定时器的设置值要注意计算准确,为了达到足够的精度,我在CCR0的计算时减去了DAC的转换时间15us,测试表明确实提高了实际正弦波的精度。

            另外加入了一个按键,功能是以200hz步进调整正弦波的频率。

    源程序:
    [CODE]
    #include <msp430x16x.h>
    #define fs_val 4095
    //******************************************************************************
    static int sinc[100]={
    0.5*fs_val+0.5,
    0.53139523328*fs_val+0.5,
    0.56266656413*fs_val+0.5,
    0.5936905791*fs_val+0.5,
    0.62434484077*fs_val+0.5,
    0.654508371*fs_val+0.5,
    0.68406212831*fs_val+0.5,
    0.71288947771*fs_val+0.5,
    0.74087665102*fs_val+0.5,
    0.76791319584*fs_val+0.5,
    0.79389241147*fs_val+0.5,
    0.81871176997*fs_val+0.5,
    0.84227332084*fs_val+0.5,
    0.86448407756*fs_val+0.5,
    0.88525638458*fs_val+0.5,
    0.90450826323*fs_val+0.5,
    0.92216373525*fs_val+0.5,
    0.9381531227*fs_val+0.5,
    0.95241332286*fs_val+0.5,
    0.96488805734*fs_val+0.5,
    0.97552809415*fs_val+0.5,
    0.98429144198*fs_val+0.5,
    0.99114351597*fs_val+0.5,
    0.99605727416*fs_val+0.5,
    0.99901332422*fs_val+0.5,
    1*fs_val+0.5,
    0.99901340753*fs_val+0.5,
    0.99605744045*fs_val+0.5,
    0.99114376459*fs_val+0.5,
    0.98429177194*fs_val+0.5,
    0.97552850415*fs_val+0.5,
    0.96488854577*fs_val+0.5,
    0.95241388778*fs_val+0.5,
    0.93815376189*fs_val+0.5,
    0.92216444618*fs_val+0.5,
    0.9045090431*fs_val+0.5,
    0.88525723031*fs_val+0.5,
    0.86448498582*fs_val+0.5,
    0.84227428803*fs_val+0.5,
    0.81871279228*fs_val+0.5,
    0.79389348487*fs_val+0.5,
    0.76791431609*fs_val+0.5,
    0.7408778137*fs_val+0.5,
    0.71289067823*fs_val+0.5,
    0.68406336193*fs_val+0.5,
    0.65450963286*fs_val+0.5,
    0.62434612588*fs_val+0.5,
    0.59369188239*fs_val+0.5,
    0.56266788046*fs_val+0.5,
    0.53139655746*fs_val+0.5,
    0.50000132679*fs_val+0.5,
    0.4686060909*fs_val+0.5,
    0.4373347522*fs_val+0.5,
    0.4063107242*fs_val+0.5,
    0.37565644434*fs_val+0.5,
    0.34549289086*fs_val+0.5,
    0.31593910532*fs_val+0.5,
    0.28711172281*fs_val+0.5,
    0.25912451166*fs_val+0.5,
    0.23208792441*fs_val+0.5,
    0.20610866193*fs_val+0.5,
    0.18128925235*fs_val+0.5,
    0.15772764636*fs_val+0.5,
    0.13551683069*fs_val+0.5,
    0.11474446115*fs_val+0.5,
    0.095492516647*fs_val+0.5,
    0.077836975682*fs_val+0.5,
    0.061847516493*fs_val+0.5,
    0.047587242064*fs_val+0.5,
    0.035112431087*fs_val+0.5,
    0.024472315859*fs_val+0.5,
    0.015708887983*fs_val+0.5,
    0.0088567326471*fs_val+0.5,
    0.0039428921321*fs_val+0.5,
    0.00098675908872*fs_val+0.5,
    0*fs_val+0.5,
    0.00098650915851*fs_val+0.5,
    0.003942393258*fs_val+0.5,
    0.008855986798*fs_val+0.5,
    0.015707898102*fs_val+0.5,
    0.024471085853*fs_val+0.5,
    0.03511096581*fs_val+0.5,
    0.0475855473*fs_val+0.5,
    0.06184559893*fs_val+0.5,
    0.077834842887*fs_val+0.5,
    0.095490177037*fs_val+0.5,
    0.11474192396*fs_val+0.5,
    0.13551410593*fs_val+0.5,
    0.15772474478*fs_val+0.5,
    0.18128618541*fs_val+0.5,
    0.20610544174*fs_val+0.5,
    0.23208456366*fs_val+0.5,
    0.25912102362*fs_val+0.5,
    0.28710812125*fs_val+0.5,
    0.31593540445*fs_val+0.5,
    0.34548910529*fs_val+0.5,
    0.37565258901*fs_val+0.5,
    0.40630681432*fs_val+0.5,
    0.43733080321*fs_val+0.5,
    0.46860211837*fs_val+0.5
    };
    unsigned char sam_point=0;//sam_point为采样点,phase_value为相位值
    int frequence=200;

    //******************************************************************************
    void InitSys()
    {
     P1DIR=0x00;
     P1IES=0x01;
     P1IE=0x01;
     }

    //******************************************************************************
    void InitClock()
    {
     unsigned int iq0;
     BCSCTL1&=~XT2OFF; //打开XT2振荡器
     do
      {
        IFG1&=~OFIFG; // 清除振荡器失效标志
        for(iq0=0xff;iq0>0;iq0--);//延时,等待XT2起振
     }
     while((IFG1&OFIFG)!=0); // 判断XT2是否起振
     BCSCTL2=SELM_2+SELS; //选择MCLK、SMCLK为XT2
    }

    //******************************************************************************
    void InitTA()
    {
     TACTL=TASSEL1+TACLR;//定时器A时钟源为SMCLK,并清TAR
     CCTL0|=CCIE;//CCR0中断使能
     CCR0=399; //(485*8/100=39) 485us+15us=500us=0.5ms=1/2000hz(晶振为8mhz)
     TACTL|=MC0;//(4985*8/100=399)4985us+15us=5000us=5ms=1/200hz(15us为DAC转换时间)
     }

    //******************************************************************************
    void main(void)
    {
     WDTCTL = WDTPW + WDTHOLD;
     InitClock();
     InitSys();
     InitTA();
     ADC12CTL0 = REF2_5V + REFON;//打开内部2.5v参考电压
     DAC12_0CTL = DAC12IR + DAC12AMP_5 + DAC12ENC;
     while(1)
      {
       _BIS_SR(CPUOFF+GIE);//开中断,关cpu
       DAC12_0DAT=sinc[sam_point];
     }
    }

    //******************************************************************************
    #pragma vector=TIMERA0_VECTOR
    __interrupt void TA0(void)
    {
     sam_point++;
     if(sam_point==100)
        sam_point=0;
     _BIC_SR_IRQ(CPUOFF);
    }

    //******************************************************************************
    #pragma vector=PORT1_VECTOR
    __interrupt void P1key(void)
    {
    frequence+=200;
    if(frequence>2000)
        frequence=200;
    CCR0=(unsigned short)((float)(1000000/frequence-15)*0.08+0.5);//(0.08=8/100)
    P1IFG=0x00;
    }

    [/CODE]
    msp430产生正弦信号(二)
    基于MSP430定时器的DA转换
    原理很简单,PWM波形在占空比一定时,经过低通滤波得到恒定的电压,若占空比按照正弦规律变化则经过低通滤波后得到的就是一个按照正弦规律变化的电压。 此方案需配合比较精确的晶振方可实现准确的频率。

    程序:
    [CODE]
    #include <msp430x22x4.h>
    unsigned char SampleTimes=0;
    int SinTable[]={255,254,246,234,219,199,177,153,128,103,79,57,37,22,10,2,1,2,10,22,37,57,79,103,128,153,177,199,219,234,246,255};

    //******************************************************************************
    void main(void)
    {
     WDTCTL=WDTPW+WDTHOLD;                   //关看门狗
     BCSCTL1 =CALBC1_1MHZ;                   //设定DCO为1MHZ
     DCOCTL =CALBC1_1MHZ;          
     TACTL=TASSEL1+TAR;                      //SMCLK为时钟源,清TAR
     CCTL0=CCIE;
     CCR0=256;                               //设定PWM周期
     CCTL1 |=OUTMOD_7;                       //CCR1输出为reset/set模式
     CCR1=SinTable[SampleTimes];             //CCR1的PWM占空比设定
     CCTL2 |=OUTMOD_7;                       //CCR2输出为reset/set模式
     CCR2=128;                               //CCR2的PWM占空比设定
     P1SEL |=BIT2+BIT3;                      //TA1,TA2输出功能
     P1DIR |=BIT2+BIT3;                      
     TACTL |=MC0;                            //启动定时器A增计数模式
     _BIS_SR(CPUOFF+GIE);
    }

    //******************************************************************************
    //定时器A 中断服务程序区
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A (void)
    {
     SampleTimes=(SampleTimes+1)%32;
     CCR1=SinTable[SampleTimes];
    }
    [/CODE]
    [ 此贴最后由DC在2009-3-4 19:37:10编辑过 ]
    微控网感谢您的参与
    在线情况
    2
    • 头像
    • 级别
    • 门派
    • 职务总版主
    • 声望+9
    • 财富5
    • 积分3065
    • 经验390701
    • 文章6744
    • 注册2006-03-07
    hhb217你好,麻烦你注明一下原作者的名称和源出处。
    采用编辑贴子功能进行编辑,谢谢!
    [COLOR=#0000ff]欢迎发贴分享设计心得、开源DIY...[/COLOR]
    在线情况
    3
    • 头像
    • 级别
      • 积分13
      • 经验1417
      • 文章37
      • 注册2006-09-20
      关于第一种方法
      写好正弦函数表,然后用16x内部的DMA送到DAC就行了
      微控网感谢您的参与
      Powered by LeadBBS 9.2 .
      Page created in 0.2500 seconds with 5 queries.