注:请大家帮了看一下以下程序,我运行了后,LED一直亮着(闪烁快,人眼分不清)
问大家的目的是帮我确认定时器确实是500us中断一次,我看到TI例程里的中断里有写
TA0CCR0 += 500; ,不明白为什么要加这一个语句?
还有要不在在中断里加 :关闭CPU,开启总中断语句?
__bis_SR_register(LPM4_bits+GIE); // 关闭CPU,开启总中断
例:
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
P1OUT ^= 0x01; // 用于测试P1.0口的LED来判断定时器起作用,定时器周期为500us/次
// TA0CCR0 += 500; //好像不能要,不知道为什么?
__bis_SR_register(LPM4_bits+GIE); // 关闭CPU,开启总中断
}
完整的例程如下:
//******************************************************************************************************//
// 说明:基于MSP430F2132单片机的定时器TimerA0周期为500us/次的例程 //
// 程序编写:xxx 2013年23时52分 //
// 本程序在IAR Assembler for MSP430 5.30.1 (5.30.1.50284)上编译 //
//******************************************************************************************************//
#include"msp430X21X2.h"
//声明初始化函数
void Init_CLK(void); //初始化时钟Init_CLK()函数
void Init_TimerA0(void); //初始化定时器TimerA0()函数
//*****************************************************//
// 初始化函数 Init_CLK() (OK) //
// MCLK = SMCLK = LFXT1 = HF XTAL(8Mhz) //
//*****************************************************//
void Init_CLK(void)
{
unsigned int i;
BCSCTL1 = 0X00; // 将寄存器的内容清零
BCSCTL1 |= XTS; // (ACLK = 8Mhz), ACLK = LFXT1 = HF XTAL(外部晶振8Mhz)
BCSCTL3 |= LFXT1S1; // LFXT1S1 = 3-16Mhz(外部晶振8Mhz)
do
{
IFG1 &= ~OFIFG; // 清除OSCFault标志
i = 0xFF; // i = 延时
while (i–); // 延时等待起振
}
while (OFIFG & IFG1); // 如果OSCFault = 1?
BCSCTL2 = 0X00; // 将寄存器的内容清零
BCSCTL2 |= SELM_3; // (MCLK = 8Mhz), MCLK = LFXT1 = HF XTAL, 分频因子默认为1
BCSCTL2 |= SELS; // (SMCLK = 8Mhz), SMCLK = LFXT1 = HF XTAL, 分频因子默认为1
return;
}
//结束初始化函数 Init_CLK()
//*****************************************//
// 初始化函数 Init_TimerA0() (OK) //
//*****************************************//
void Init_TimerA0(void)
{
TA0CCTL0 = CCIE; //TA0CCR0中断使能
TA0CTL = TASSEL_2 + MC_1 + ID_3 + TACLR; //TASSEL_2:选择SMCLK(8Mhz); MC_1:增至CCR0记数模式; ID_3:1/8分频后为1MHz;TACLR清除TAR
TA0CCR0 = 500; //时间间隔 (即500us),对于MSP430单片机而言,SMCLK分频为1MHz时,正好1Hz等于1us(us为微秒)
//定时器TA0CCR0设为500,即为500us/次
return;
}
//结束初始化函数 Init_TimerA0()
void main(void){
WDTCTL=WDTPW+WDTHOLD; // 关闭看门狗
_DINT(); // 关闭中断
P1DIR |= (BIT0); // 设置P1.0(接上-Res500-LED)
P1OUT &= ~(BIT0); // 初始化P1.0为低电平,关闭LED灯
Init_CLK(); //初始化时钟
Init_TimerA0(); //初始化定时器TimerA0
_EINT(); // 打开中断 //循环处理
while(1);
}//结束main()
// Timer_A0中断处理程序:每500us亮或灭一次LED
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
P1OUT ^= 0x01; // 用于测试P1.0口的LED来判断定时器起作用,定时器周期为500us/次
__bis_SR_register(LPM4_bits+GIE); // 关闭CPU,开启总中断
}
Bruce Wei:
楼主你好!
1、楼主可以借助示波器判断中断周期是否确实是500us;
2、TA0CCR0 += 500; 即是将目前 TA0CCR0 值读出来,然后再增加 500作为下次中断的计数值;
3、定时器的用法很灵活,具体请参考user guide;
Triton Zhang:
回复 Bruce Wei:
你的代码中有明显的问题,
__bis_SR_register(LPM4_bits+GIE); // 关闭CPU,开启总中断
在定时器中断中你使用了上面这条语句,使得CPU进入LPM4的工作模式,在该工作模式下所有的clock都是关闭的,TIMER不能中断唤醒CPU。所以你看到的LED长亮并非是因为闪烁时间过短造成的。你可以利用示波器或者逻辑分析仪看到LED口线的变化.
其他地方未见明显错误.TIMER中断后建议软件清除中断标志。
Shi JianHua:
回复 Triton Zhang:
定时器没理解怎么用,还要好好看看定时器部分,定时器的工作方式有多种,我估计楼主是想用定时器唤醒单片机定时的中断来完成一些工作。所以才那样做。低功耗的应用这块还要多看看。