芯片型号为msp430f1232,晶振为32.768,电池3.6V供电。
看门狗选择aclk, 1s (WDT_ARST_1000),用定时器A定时为500ms一次,每一次TA中断(500ms)喂狗一次。
平时一般处于lpm3模式下,每500ms中断计数器taCount++,同时喂狗(WDTCTL = WDTPW + WDTCNTCL )。当taCount大于设定值时唤醒_BIC_SR_IRQ(LPM3_bits); 进行处理。
现在的问题是 单片机总是自动重启,似乎喂狗功能没有起作用,但是单独只有定时器是,500ms计时是正常的。
Ling Zhu2:
你好,程序不长的话建议贴出来~
ChenWan Wu:
回复 Ling Zhu2:
程序有点长, 我将主要部分贴出来。
主程序main.c:
void main( void ){ STOP_WDT(); //关看门狗 halInitClock(); //时钟初始化,DCO , 1000000 halInitTimer(); //定时器初始化,TA , 500ms
halInitPort(); //初始化端口
halInitUart(B_9600); //串口初始化 halInitWDT(); //看门狗始化,1s while(1) { read_send_evt(); //处理事件,lpm1模式下,与看门狗无关 mcu_sleep(120); //休眠120,等待定时器唤醒 }
}
定时器文件hal_timer.h
#define TIMER_A_500MS_VALUE (32758/2)
uint16 time_out ;volatile uint16 sleep_count = 0;volatile uint16 timer_count = 0;
void halInitTimer(void){ TACTL |= TASSEL_1 + TACLR + ID_0 ; //选择ACLK作为定时器的时钟,1分频 TACTL |= MC_1 + TAIE ; //增加模式,并且使能中断 TACCR0 = TIMER_A_500MS_VALUE; //中断周期为500ms }
void mcu_sleep(uint16 sleep_s){ sleep_count = 0 ; timer_count = 0 ; time_out = sleep_s; _BIS_SR(LPM3_bits + GIE); //进入休眠模式 ,在定时器中比较 time_out = 120,即60s}
#pragma vector=TIMERA1_VECTOR__interrupt void TimerA1_IRQ(void)//500ms中断 { switch( TAIV ) { case 2:break; case 4:break; case 10: halClearWdt(); //500ms清一次看门狗 timer_count ++;//累计 if(timer_count >= time_out )//time_out = 120,即60s { timer_count = 0 ; _BIC_SR_IRQ(LPM3_bits); //60s唤醒一次 } break; }}
看门狗文件hal_wdt.h
#define STOP_WDT() st( WDTCTL = WDTPW + WDTHOLD; )#define START_WDT() st( WDTCTL = WDTPW; )#define CLEAR_WDT() st( WDTCTL = WDTPW + WDTCNTCL; ) void halInitWDT(void){ if( WDTIFG & IFG1 ) { IFG1 &= ~WDTIFG; //清中断标志 } WDTCTL = WDT_ARST_1000; //WDT看门狗1s一次,看门狗模式 START_WDT();}monitor void halClearWdt(void)//清看门狗记时{ WDTCTL = WDTPW + WDTCNTCL ;}
ChenWan Wu:
回复 Ling Zhu2:
程序有点长, 我将主要部分贴出来。
主程序main.c:
void main( void ){STOP_WDT(); //关看门狗halInitClock(); //时钟初始化,DCO , 1000000halInitTimer(); //定时器初始化,TA , 500ms
halInitPort(); //初始化端口
halInitUart(B_9600); //串口初始化halInitWDT(); //看门狗始化,1swhile(1){ read_send_evt(); //处理事件,lpm1模式下,与看门狗无关 mcu_sleep(120); //休眠120,等待定时器唤醒}
}
定时器文件hal_timer.h
#define TIMER_A_500MS_VALUE (32758/2)
uint16 time_out ;volatile uint16 sleep_count = 0;volatile uint16 timer_count = 0;
void halInitTimer(void){TACTL |= TASSEL_1 + TACLR + ID_0 ; //选择ACLK作为定时器的时钟,1分频TACTL |= MC_1 + TAIE ; //增加模式,并且使能中断TACCR0 = TIMER_A_500MS_VALUE; //中断周期为500ms }
void mcu_sleep(uint16 sleep_s){ sleep_count = 0 ;timer_count = 0 ;time_out = sleep_s;_BIS_SR(LPM3_bits + GIE); //进入休眠模式 ,在定时器中比较 time_out = 120,即60s}
#pragma vector=TIMERA1_VECTOR__interrupt void TimerA1_IRQ(void)//500ms中断 {switch( TAIV ){case 2:break;case 4:break;case 10:halClearWdt(); //500ms清一次看门狗timer_count ++;//累计if(timer_count >= time_out )//time_out = 120,即60s{timer_count = 0 ; _BIC_SR_IRQ(LPM3_bits); //60s唤醒一次 }break; }}
看门狗文件hal_wdt.h
#define STOP_WDT() st( WDTCTL = WDTPW + WDTHOLD; )#define START_WDT() st( WDTCTL = WDTPW; )#define CLEAR_WDT() st( WDTCTL = WDTPW + WDTCNTCL; )void halInitWDT(void){if( WDTIFG & IFG1 ) {IFG1 &= ~WDTIFG; //清中断标志 }WDTCTL = WDT_ARST_1000; //WDT看门狗1s一次,看门狗模式 START_WDT();}monitor void halClearWdt(void)//清看门狗记时{WDTCTL = WDTPW + WDTCNTCL ;}
tian liu:
回复 ChenWan Wu:
在TA定时器中断函数中执行清狗的语句处设个断点啊,看看断点能命中不,如果不能命中就reset了,那一个是TA定时的时间间隔问题,再有就是逻辑问题,把中断函数中判断TAIV的部分去掉 ,也就是去掉switch语句,只保留case10下面的代码,看看结果如何。
Ling Zhu2:
回复 ChenWan Wu:
你好,一般不建议在中断里喂狗,建议在中断里退出低功耗,然后在while(1)里面喂狗~
ChenWan Wu:
回复 Ling Zhu2:
我的设备不能随便退出低功耗的,因为是电池供电,要保证时长。在LPM3的模式下,只有定时器还能工作,所以不得不在定时器中喂狗了。为什么不推荐在定时器中喂狗呢?
ChenWan Wu:
回复 tian liu:
调试确实是可以进入定时器中断喂狗,但是现象比较奇怪。设备的低功耗模式出现问题,无法唤醒了,但是在调试确实可以到退出低功耗模式语句_BIC_SR_IRQ(LPM3_bits);
jing wu1:
回复 ChenWan Wu:
请问这个问题解决了吗,我也遇到了低功耗模式下喂狗的问题,不知道怎么弄
jing wu1:
回复 Ling Zhu2:
您好,有LPM3模式下喂狗的参考例程什么的吗?我看到网上有不少人遇到这个问题
包括http://bbs.eeworld.com.cn/thread-415367-1-1.html,期待您的回复
jing wu1:
回复 ChenWan Wu:
一进入低功耗,CPU就死了,CPU是不会执行counter++这种代码的,应该是这个原因