最近在用MSP430做东西
对发热有一些要求
为了尽可能减少发热
单片机一直运行在低功耗模式
包括代码中的延时函数
自己写了一个低功耗延时函数
给定时器设置一个时间
然后让单片机进入睡眠状态
通过定时器中断唤醒并将一个标志清零
因为其它中断也有唤醒代码
醒后判断标志是否被定时器清零0
如果清零代码继续执行
如果没清零继续进入睡眠状态
代码是下边这样
- void delay_ms_lpm3(uint16_t ms)
- {
- if(ms > 5957)while(1);
- TA1CCTL0 = CCIE; // CCR0 interrupt enabled
- TA1CCR0 = 11*ms;
- TA1CTL = TASSEL_1 + MC_1; // ACLK = 11KHz, Up to CCR0
- delay_flag = 1; //设置延时标志
- while(delay_flag) //等待延时标志被中断清除
- {
- __bis_SR_register(LPM3_bits + GIE); // CPU off, interrupts enabled
- }
- }
- #pragma vector=TIMER1_A0_VECTOR
- __interrupt void Timer1_A0 (void)
- {
- delay_flag = 0;
- TA1CTL &= ~(MC_1);
- TA1CCTL0 &= ~(CCIE);
- __bic_SR_register_on_exit(LPM3_bits); // Exit LPMx
- }
复制代码
以前运行没发现问题,后来在串口中断里作了一些数据处理
现在的代码运行一会儿就会卡在while(delay_flag)
delay_flag会一直为1
经过分析发现这个延时函数存在一些隐患
比如
delay_flag = 1; 是在定时器配置好以后设置的
如果代码正好在定时器配置好,还没有将delay_flag置1
此时定时器已经工作,如果有其它中断产生,比如UART,然后在中断函数里占用了一定时间
这个时间超过定时器的定时时间
中断退出后此定时器到达指定时间会产生中断,将delay_flag置0,其实delay_flag本来就是0
接下来继续执行代码,将delay_flag置1,然后等待delay_flag被定时器中断清零
因为定时器中断函数已经执行过,所以delay_flag会一直为1,代码才会卡在这里
解决办法是将delay_flag=1放在配置定时器之前
修改后的代码运行了一段时间,还没有发现之前的问题
- void delay_ms_lpm3(uint16_t ms)
- {
- if(ms > 5957)while(1);
- delay_flag = 1; //设置延时标志
- TA1CCTL0 = CCIE; // CCR0 interrupt enabled
- TA1CCR0 = 11*ms;
- TA1CTL = TASSEL_1 + MC_1; // ACLK = 11KHz, Up to CCR0
- while(delay_flag) //等待延时标志被中断清除
- {
- __bis_SR_register(LPM3_bits + GIE); // CPU off, interrupts enabled
- }
- }
复制代码
|