This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430G2553 实现spwm波 遇到一个奇怪问题

Other Parts Discussed in Thread: MSP430G2553

  • /*

    *

    */

    #include "msp430g2553.h"

    #include "delay.h"

    const unsigned int spwm[] = {

    250, 327, 396, 452, 487, 499, 487, 452, 396, 327,

    250, 172, 103, 47, 12, 0, 12, 47, 103, 172,

    };

    unsigned int n=0;

    /*

    *

    */

    void TimerA_Init()

    {

    P1DIR |= BIT2;

    P1SEL |= BIT2;                            // p1.2

    TACCR0 = 500;                              // Init TACCR0 w/ sample prd=CCR0+1

    TACCR1= spwm[n];

    TACCTL1 = OUTMOD_7;                            // Set/reset

    TACCTL0 = CCIE;

    TACTL = TACLR + MC_1 + TASSEL_2 +ID_3;                // clear TAR, up mode*/

    }

    void ini_sys(void)

    {

       WDTCTL=WDTPW+WDTHOLD;  //STOP W D T

       if (CALBC1_8MHZ ==0xFF || CALDCO_8MHZ == 0xFF)

        {

        while(1);                               // If calibration constants erased

        // do not load, trap CPU!!

        }

        //1Mhz  ~1008000

        BCSCTL1 = CALBC1_16MHZ;                    // Set range

        DCOCTL = CALDCO_16MHZ;                     // Set DCO step + modulation */

        delay_ms(10);

    }

    /*

    * main()

    */

    void main()

    {

       ini_sys();

       TimerA_Init();

       _EINT();

     //_BIS_SR(LPM0_bits + GIE);

       while(1);

    }

    /*

    * T0_A0 interrupt service

    */

    #pragma vector=TIMER0_A0_VECTOR

    __interrupt void Timer0_A0(void)

    {

    //一个周期内取180个点,点间隔2度

    n = (n+1)%20;

    TACCR1 = spwm[n];

    }

  • 程序如上,经示波器观察,spwm正弦表数组中,TACCR1 = 250, 327, 396, 452, 487, 499, 487, 452, 396, 327,

    250, 172, 103, 47,都输出正常,到TACCR1=12, 0, 12, 47的时候输出不正常了。出来效果跟TACCR1 = 500, 0, 0,5一输出相近。

    然后后面的TACCR1= 103, 172。也是正常的。

    纠结好久了。求助!

  • 在使用手册里有一句话:

    The numbers at the right margin show the necessary CPU cycles for each instruction. The software

    overhead for different interrupt sources includes interrupt latency and return-from-interrupt cycles, but not

    the task handling itself. The latencies are:

    • Capture/compare block TACCR0: 11 cycles

    • Capture/compare blocks TACCR1, TACCR2: 16 cycles

    首先你选择的是SMCLK作为timer的时钟源。一般进timer中断与出中断大概需要16个cycles,那么你选择太窄的pwm占空比本身是有问题的。

  • 一种可能性:

    1、在总程序中还有其它的“中断”,当Timer_A中的TACCR1在按预定的节奏输出预期信号期间,另外一个“中断”会间或插一杠子;

    2、因为中断服务函数使用的都是MCLK,如果此时两个中断服务函数之间形成了“碰头冲突”,那么另外那个中断就可能对这个TACCR1的运行造成干扰。

    我以前遇到过类似情况:当时我没用Timer_A而是用delay语句的方式直接输出PWM信号,结果发觉输出信号抖晃非常厉害,100思不得其解,最后发现是有其它中断服务在干扰,于是我在每次输出PWM期间就临时关闭系统所有中断(_DINT;),之后输出的PWM信号就非常稳定了!-------你也可尝试一下关闭除TACCR1之外的其它中断。

  • 1. if (CALBC1_8MHZ ==0xFF || CALDCO_8MHZ == 0xFF)改写成 if (CALBC1_16MHZ ==0xFF || CALDCO_16MHZ == 0xFF)更合适。

    2.输出的问题,把波形发给大家看看嘛

  • 看他程序里已经是16M的主频了。主要是受PWM频率限制,不能做到非常小的占空比。

  • 我也想发个波形的,不过还得拍照,就没发了。

    确实是Peter_Zheng说的那个问题。

    而且我发现

    n = (n+1)%20;

    这条语句竟然要运行150个cpu 周期。

    后来我改成

    TACCR1 = spwm[n++];

    if(n == 20){

    //n=0;

    }

    运行时间大概只有23个cpu周期了。加上Capture/compare block TACCR0: 11 cycles。大概是34个cpu周期。

    我是smclk 8分频后给TA做时钟源。

    我把spwm数组里面的 0 改成了大点的 3 。

    现在输出基本可以了。

  • 一般是不会在中断程序里做运算的。中断应该要及时响应及时退出。

  • 1.”n = (n+1)%20;

    这条语句竟然要运行150个cpu 周期。“

    这个应该才是问题的关键,因为楼主用的8分频,进中断的时间是足够的,按照楼主的程序,中断执行时间小于96个cycle都可以接受

    2.正如Peter_Zheng 所说,MSP430支持SPWM效果不会太好,特别是PWM频率要求较高的时候。

    3.楼主把主频再调高一些到24MHz,效果会好一些。

  • 嗯,n = (n+1)%20;那条语句执行时间较长,好像msp430g2553里面的DCO 最高只能16M

    有什么办法可以调到25M么

  • n = (n+1)%20;

    这条语句改为:

    n++;

    if(n>=20){

    n-=20;

    }

  • G2553最高只支持16MHz,不能调到25MHz,我想主要还是在实现方法上突破,一味调高主频并不可取。

  • 请问一下楼主实现的SPWM是用于什么应用?

  • 我是想用spwm滤波来得到频率和赋值都可调正弦波

  • 我是想用spwm滤波的方法得到赋值和频率都可调的正弦波。不过现在觉得LaunchPad 16M的速度实现起来效果不是很好。频率做不高

  • 是的,应用中常用C2000实现SPWM,MSP430更适合做低功耗,低成本的信号控制用