dear TI‘s fellows:
我正学习430TimerA,我现在想通过timerA 产生两路pwm波形。
1.当我没使用中断时,通过示波器观察到预期的波形,这没问题;
2.问题在于我想使用中断,我的思路是:通过中断服务程序分别改变CCR1,CCR2的值,这样就能很灵活的改变pwm的占空比等参数,但为何我在示波器上什么也看不到,连基本波形都没有;求解答
#include <msp430g2452.h>
unsigned char test1=0;
unsigned char test2=0;
unsigned char test=0;
int main()
{
//wdt
WDTCTL = WDTPW +WDTHOLD;//SHUTDOWN WDT
//basic clock system
DCOCTL = CALDCO_8MHZ;// calibration DCO ,8MHZ,(10FC)
BCSCTL1 = CALBC1_8MHZ;// calibration bcs, 8MHZ,(10FD)
//DISABLE INT
_DINT();
//P1.2,P1.4 FUNCTION
P1DIR |= BIT2 + BIT4;//P1.2,P1.4output
P1SEL |= BIT2 + BIT4;//TA1, TA2 function options
P1SEL2 |= BIT4;//DATASHEET :TA1(1,0),TA2(1,1)
//TIMER A
TA0CTL = TASSEL_2 + ID_3 + MC_1; // SMCLK,8DIV->1MHZ, UP MODE
CCR0 = 50000;//50ms;
TA0CCTL1 = OUTMOD_4 ;// mode 4: TOGGLE
CCR1 = 1000;//1000us
TA0CCTL2 =OUTMOD_4; // MODE 4: TOGGLE
CCR2 = 10000;//10ms
TA0CCTL1 &= ~CCIFG;
TA0CCTL2 &= ~CCIFG;
TA0CCTL1 |= CCIE;
TA0CCTL2 |= CCIE;
//ENABLE INT
_EINT();
while(1)
{
;
}
}
#pragma vector =TIMER0_A1_VECTOR // 0xFFF0__interrupt void TMR0_A1_INT(void)
{
switch(TAIV)
{
case 02 : //CCR1 INT TA0CCTL1 &= ~CCIFG;
CCR1 += 1000; /1000us 此处为P1.2的半周期
break;
case 04 : //CCR2 INT
TA0CCTL2 &= ~CCIFG;
CCR2 += 10000; //10ms 此处为P1.4的半周期
break;
}
Leon Yan:
你好:
楼主先参考一下下面的代码,是关于G2xx2的PWM的。
//******************************************************************************// MSP430G2xx2 Demo – Timer_A, PWM TA1-2, Up Mode, DCO SMCLK//// Description: This program generates one PWM output on P1.2 using// Timer_A configured for up mode. The value in CCR0, 512-1, defines the PWM// period and the value in CCR1 the PWM duty cycles.// A 75% duty cycle on P1.2.// ACLK = na, SMCLK = MCLK = TACLK = default DCO//// MSP430G2xx2// —————–// /|\| XIN|-// | | |// –|RST XOUT|-// | |// | P1.2/TA1|–> CCR1 – 75% PWM//// D. Dang// Texas Instruments, Inc// December 2010// Built with CCS Version 4.2.0 and IAR Embedded Workbench Version: 5.10//******************************************************************************
#include <msp430.h>
int main(void){ WDTCTL = WDTPW + WDTHOLD; // Stop WDT P1DIR |= 0x0C; // P1.2 and P1.3 output P1SEL |= 0x0C; // P1.2 and P1.3 TA1/2 options CCR0 = 512-1; // PWM Period CCTL1 = OUTMOD_7; // CCR1 reset/set CCR1 = 384; // CCR1 PWM duty cycle TACTL = TASSEL_2 + MC_1; // SMCLK, up mode
_BIS_SR(CPUOFF); // Enter LPM0}
yingjun zhu:
回复 Leon Yan:
dear Leon Yan :
你贴的代码我可以明白,TI 其它的示例代码我也看懂了。现在的问题是加入中断为何产生不了波形,求解答。
Xutong Han2:
注意到你的程序中使能中断 _EINT();的这条语句应该在G2的编译环境下找不到对于的原型 你可以用仿真器 go to the define ,,, 试一下,我之前也遇到过这个问题(IAR 5.4),
//ENABLE INT_EINT();
你尝试打开中断利用
_BIS_SR(GIE); //使能总中断
看看这样能不能解决问题
yingjun zhu:
回复 Xutong Han2:
dear Xutong Han2:
你好,我把中断程序改了如下就可以得到相应的波形。
#pragma vector =TIMER0_A1_VECTOR // 0xFFF0 __interrupt void TMR0_A1_INT(void){ switch(TAIV) { case 02 : //CCR1 INT TA0CCTL1 &= ~CCIFG; CCR1 += 1000;//1000us if(CCR1 > 50000) CCR1 = 1000; //CCR0=50000,CCR1不断自加,大于50000时重设为1000;如此反复。
test1++;
break; case 04 : //CCR2 INT TA0CCTL2 &= ~CCIFG; CCR2 += 10000; //10ms if(CCR2 > 50000) CCR2 = 10000; test2++; break; }}
//但是按照我开始的想法:在up 模式下,CCR1不断自加 并产生中断;当CCR1>50000时,不会发生捕获;当CCR1的值大于65535时,16位寄存器溢出得到一个新值,并可产生捕获中断。如此反复。 可是程序结果却不是这样。
Xutong Han2:
回复 yingjun zhu:
if(CCR1 > 50000)CCR1 = 1000; //CCR0=50000,CCR1不断自加,大于50000时重设为1000;如此反复。
通过测试当CCR1=51000时 重新置为CCR1=1000 相应的PWM波形的也会发生变化,你说当CCR1的值大于65535时,16位寄存器溢出得到一个新值,并可产生捕获中断,CCR1的值在等于51000时已经置位为1000不会大于65535,
yingjun zhu:
回复 Xutong Han2:
/**************** Timer A ——>PWM ******************UP MODE : CCR0 -> PWM period CCR1 -> TA0.1 OUTPUT (P1.2) CCR2 -> TA0.2 OUTPUT (P1.4) **********************************************************/#include <msp430g2452.h>
unsigned char test1=0; // these three vars for testunsigned char test2=0;unsigned char test=0;
int main(){ //wdt WDTCTL = WDTPW +WDTHOLD; //SHUTDOWN WDT //basic clock system DCOCTL = CALDCO_8MHZ; // calibration DCO ,8MHZ,(10FC) BCSCTL1 = CALBC1_8MHZ; // calibration bcs, 8MHZ,(10FD) //DISABLE INT _DINT(); //P1.2,P1.4 FUNCTION P1DIR |= BIT2 + BIT4; //P1.2,P1.4output P1SEL |= BIT2 + BIT4; //TA1, TA2 function options P1SEL2 |= BIT4; //DATASHEET :TA1(1,0),TA2(1,1) //TIMER A TA0CTL = TASSEL_2 + ID_3 + MC_1; // SMCLK,8DIV->1MHZ, UP MODE //TA0CTL = TASSEL_2 + ID_3 + MC_3; // SMCLK,8DIV->1MHZ, UP and DOWN MODE
//CCR0 = 50000; //50ms; //CCR0 = 65535; //65ms; 只有改值可以产生正常波形 CCR0 = 60000; //60ms;
TA0CCTL1 = OUTMOD_4 ; // mode 4: TOGGLE CCR1 = 1000; //1000us TA0CCTL2 =OUTMOD_4; // MODE 4: TOGGLE CCR2 = 10000; //10ms //TA INTERRUPT SETUP TA0CCTL1 &= ~CCIFG; TA0CCTL2 &= ~CCIFG; TA0CCTL1 |= CCIE; TA0CCTL2 |= CCIE; //ENABLE INT _EINT(); while(1) { test = test1; } }
#pragma vector =TIMER0_A1_VECTOR // 0xFFF0 __interrupt void TMR0_A1_INT(void){ switch(TAIV) { case 02 : //CCR1 INT TA0CCTL1 &= ~CCIFG; CCR1 += 1000; //1000us // if(CCR1 > 50000) // CCR1 = 1000; test1++; break; case 04 : //CCR2 INT TA0CCTL2 &= ~CCIFG; CCR2 += 10000; //10ms // if(CCR2 > 50000) // CCR2 = 10000; test2++; break; }
}
dear Xutong Han2:
是我没有表述清楚。请看以上代码,我测试该代码时。红色标注的三条语句,只有当CCR0为65535时,可以产生正常的波形;为其他两个值都不可以,为什么会这样啊。
Xutong Han2:
回复 yingjun zhu:
TA0CCTL1 = OUTMOD_4 ; // mode 4: TOGGLE
TA0CCTL2 =OUTMOD_4; // MODE 4: TOGGLE
你用的都是TOGGLE模式, 也就是The output is toggled when the timer counts to the TACCRx value. The output period is double the timer period. 这个和CCR0的值没有关系,如果你想用CCR0做PWM的周期尝试Reset/Set OUTMOD_7模式,