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.

MSP430F5438A调节PWM波占空比为什么时钟会乱掉?

Other Parts Discussed in Thread: MSP430F5438A

我用F5438A定时器B输出50HZ的PWM波,并用P2.6和P2.7外接两个按键,在外部中断中增加/减少TBCCR2的值来调节PWM波的占空比,如果按键不按下去在示波器上观察SMCLK是正常的16M,按键按了大概前5次左右是能正常调节占空比的,但再按按键示波器上就能观察到时钟变成了26-28M左右,而且这时候外部中断也进不去了,同样PWM波的周期和正脉宽受时钟影响也变大了,并且无法调节。求大神解答!以下是程序代码:

#include<msp430f5438a.h>

unsigned int s=3000;  //s存放将要改变的TBCCR2的值,并将它赋值给TBCCR2

void main( void )

 {  

 // Stop watchdog timer to prevent time out reset

  WDTCTL = WDTPW + WDTHOLD;    

 P1DIR = BIT0+BIT1; //P1.0和P1.1设置为输出,点亮两个LED

/*-------有关端口中断的设置--------*/

P2OUT = BIT6+BIT7;   

 P2REN = BIT6+BIT7; //因为按键另一端接地了,所以P2.6 P2.7输入端口要上拉  

 P2IES = BIT6+BIT7; //中断触发边沿为下降沿  

 P2IFG &= ~(BIT6 + BIT7);    

P2IE  = BIT6+BIT7; //中断打开

/*-------有关时钟系统的设置--------*/  

P5SEL = BIT3 + BIT2;  

 P7SEL = BIT0 + BIT1;  //晶振输入端口为第二功能    

 UCSCTL6 &= ~0x8000u;  //XT2驱动能力设为8-16MHZ     

 UCSCTL6 &= ~(XT1OFF + XT2OFF ); //打开XT1和XT2    

__bis_SR_register(SCG0);  

 UCSCTL3 = SELREF__XT2CLK;  //DCO的参考时钟源为XT2CLK(8MHz)  

 UCSCTL1 = DCORSEL_5;  

 UCSCTL2 = 1;            //DCOCLKDIV=MCLK=SMCLK=2*8=16MHz  

__bic_SR_register(SCG0);     

do

  {    

 UCSCTL7 &= ~(XT2OFFG + XT1HFOFFG+ XT1LFOFFG + DCOFFG);    

SFRIFG1 &= ~OFIFG;

  }while(SFRIFG1 & OFIFG);  //等待时钟系统稳定     

 P11DIR = BIT0+BIT1+BIT2;  

 P11SEL = BIT0+BIT1+BIT2;  //设置ACLK,MCLK,SMCLK的端口输出     

 /*-------有关定时器的设置--------*/  

P4DIR = BIT2;   

P4SEL = BIT2;  //设置P4.2为第二功能,即TB0.2的输出  

TB0CCR0=40000;   //决定输出PWM波的周期  

TB0CCR2=3000;    //范围为1000-5000,决定输出PWM波的占空比  

TB0CCTL2 = OUTMOD_7;  

TB0CTL = ID_3 + TBSSEL__SMCLK + MC__UP + TBCLR;   //默认16位计数值,8分频,SMCLK,上升计数,清零

    _EINT(); //打开总中断  

LPM0;  //进入低功耗模式0   }

/*-------PORT2的中断函数--------*/

 #pragma vector=PORT2_VECTOR

 __interrupt void aaaa(void) 

  {  

       __delay_cycles(4000000); //按键消抖,貌似按键抖动的时间比较长,所以延时也比较长

       if(P2IFG & BIT6) //如果是P2.6触发中断

       {   

             s+=200;          

            if(s>5000)             

                  s=5000;          

             else            

                   TBCCR2=s;  //改变TBCCR2的值                    

             P1OUT |=BIT1;         

             __delay_cycles(4000000);        

              P1OUT &=~BIT1;  //点亮LED示意               

             P2IFG &= ~BIT6; //清除中断标志位  

        }          

       if(P2IFG & BIT7)  //如果是P2.7触发中断  

       {        

              s-=200;      

              if(s<1000)       

                       s=1000;        

              else          

                       TBCCR2=s; //改变TBCCR2的值           

              P1OUT |=BIT0;       

              __delay_cycles(4000000);   

              P1OUT &=~BIT0;  //点亮LED示意       

             P2IFG &= ~BIT7;  //清除中断标志位    

        }

}

 

  • 你GPIO中断服务函数中存在两个问题:

    1.TRCCR2赋值逻辑错误

    2. 延时有问题

    maqk ma 说:

    我用F5438A定时器B输出50HZ的PWM波,并用P2.6和P2.7外接两个按键,在外部中断中增加/减少TBCCR2的值来调节PWM波的占空比,如果按键不按下去在示波器上观察SMCLK是正常的16M,按键按了大概前5次左右是能正常调节占空比的,但再按按键示波器上就能观察到时钟变成了26-28M左右,而且这时候外部中断也进不去了,同样PWM波的周期和正脉宽受时钟影响也变大了,并且无法调节。求大神解答!以下是程序代码:

    #include<msp430f5438a.h>

    unsigned int s=3000;  //s存放将要改变的TBCCR2的值,并将它赋值给TBCCR2

    void main( void )

     {  

     // Stop watchdog timer to prevent time out reset

      WDTCTL = WDTPW + WDTHOLD;    

     P1DIR = BIT0+BIT1; //P1.0和P1.1设置为输出,点亮两个LED

    /*-------有关端口中断的设置--------*/

    P2OUT = BIT6+BIT7;   

     P2REN = BIT6+BIT7; //因为按键另一端接地了,所以P2.6 P2.7输入端口要上拉  

     P2IES = BIT6+BIT7; //中断触发边沿为下降沿  

     P2IFG &= ~(BIT6 + BIT7);    

    P2IE  = BIT6+BIT7; //中断打开

    /*-------有关时钟系统的设置--------*/  

    P5SEL = BIT3 + BIT2;  

     P7SEL = BIT0 + BIT1;  //晶振输入端口为第二功能    

     UCSCTL6 &= ~0x8000u;  //XT2驱动能力设为8-16MHZ     

     UCSCTL6 &= ~(XT1OFF + XT2OFF ); //打开XT1和XT2    

    __bis_SR_register(SCG0);  

     UCSCTL3 = SELREF__XT2CLK;  //DCO的参考时钟源为XT2CLK(8MHz)  

     UCSCTL1 = DCORSEL_5;  

     UCSCTL2 = 1;            //DCOCLKDIV=MCLK=SMCLK=2*8=16MHz  

    __bic_SR_register(SCG0);     

    do

      {    

     UCSCTL7 &= ~(XT2OFFG + XT1HFOFFG+ XT1LFOFFG + DCOFFG);    

    SFRIFG1 &= ~OFIFG;

      }while(SFRIFG1 & OFIFG);  //等待时钟系统稳定     

     P11DIR = BIT0+BIT1+BIT2;  

     P11SEL = BIT0+BIT1+BIT2;  //设置ACLK,MCLK,SMCLK的端口输出     

     /*-------有关定时器的设置--------*/  

    P4DIR = BIT2;   

    P4SEL = BIT2;  //设置P4.2为第二功能,即TB0.2的输出  

    TB0CCR0=40000;   //决定输出PWM波的周期  

    TB0CCR2=3000;    //范围为1000-5000,决定输出PWM波的占空比  

    TB0CCTL2 = OUTMOD_7;  

    TB0CTL = ID_3 + TBSSEL__SMCLK + MC__UP + TBCLR;   //默认16位计数值,8分频,SMCLK,上升计数,清零

        _EINT(); //打开总中断  

    LPM0;  //进入低功耗模式0   }

    /*-------PORT2的中断函数--------*/

     #pragma vector=PORT2_VECTOR

     __interrupt void aaaa(void) 

      {  

           __delay_cycles(4000000); //按键消抖,貌似按键抖动的时间比较长,所以延时也比较长

           if(P2IFG & BIT6) //如果是P2.6触发中断

           {   

                 s+=200;          

                if(s>5000)             

                      s=5000;          

                 else            

                       TBCCR2=s;  //改变TBCCR2的值

    这个逻辑有问题 应该改为

         s+=200;          

                if(s>5000)             

                s=5000;                      

                TBCCR2=s;  //改变TBCCR2的值


                       

                 P1OUT |=BIT1;         

                 __delay_cycles(4000000);        // 4000000超过限制了,取消这个长延时 改为_delay_cecles(10);

                  P1OUT &=~BIT1;  //点亮LED示意               

                 P2IFG &= ~BIT6; //清除中断标志位  

            }          

           if(P2IFG & BIT7)  //如果是P2.7触发中断  

           {        

                  s-=200;      

                  if(s<1000)       

                           s=1000;        

                  else          

                           TBCCR2=s; //改变TBCCR2的值           

                  P1OUT |=BIT0;       

                  __delay_cycles(4000000);   

                  P1OUT &=~BIT0;  //点亮LED示意       

                 P2IFG &= ~BIT7;  //清除中断标志位    

            }

    }

     

  • 按照你说的修改后试了一下,时钟还是会乱掉,而且是程序烧进去以后刚执行还没有按下按键进入外部中断,在示波器上就看到SMCLK是26-28MHz

    ,不是程序里设置的16MHz。另外当时钟乱掉的时候,MCLK也变成了26-28MHz,外部中断也进不去了。以上种种现象有没有可能是硬件的问题造成的?

  • 那说明你时钟就不对了,我无法猜测什么原因。