超时使用RTC计数器辅助实现
但在实际使用中发现有时会出现死机现象
现像:
死机
代码:
// RTC频率: fRTC [kHz] = 32.768 / (PRESCALER + 1 )
#if (0 == APP_TIMER_CONFIG_RTC_FREQUENCY)
#define RTC_CNT_MS (33) // // 当分频为0 时, 1ms 对应的 RTC 计数值
#else
#error "undefine RTC_CNT_MS"
#endif
//获取当前时间
int getCurrentMs(void)
{
int scal_ms = RTC_CNT_MS;
int timeCounter = NRF_RTC1->COUNTER;
return (timeCounter/scal_ms);
}
int main(void){
int i =0;
int startTime = getCurrentMs();
int endTime=0;
// 只执行1秒
while(1){
i++;
endTime = getCurrentMs();
if((endTime - startTime) > 1000){
break;
}
}
return 0;
}
分析:
Nordic nrf52832 RTC 计数器只有24位(0x00FFFFFF), 计数满后会清零翻转
这样会出现一种情况,在快翻转时获取到startTime,翻转后获取到的endTime就会比startTime小
即会导致 startTime > endTime, 则永远不会超时,导致死机.
解决
添加计数器翻转判断
/**
* 超时检测
* 输入: startTime 起始时间, 单位ms
* thTimeOut 超时时间阈值 单位ms
* 输出: 0 -- 未超时 1 -- 已超时
*/
int TIM_TimeOut(int startTime, int thTimeOut){
int currentT = 0;
int tmp = 0;
currentT = TIM_getCurrentMs();
if(0 >= thTimeOut){
return 1;
}
if(currentT < startTime){
// 已翻转
tmp = (RTC_MAX_MS > startTime)?(RTC_MAX_MS - startTime):(startTime - RTC_MAX_MS);
if((tmp + currentT) >= thTimeOut){
return 1;
}
}else{
// 未翻转
if((currentT - startTime) >= thTimeOut){
return 1;
}
}
return 0;
}
int main(void){
int i =0;
int startTime = getCurrentMs();
int endTime=0;
// 只执行1秒
while(1){
i++;
if(1 == TIM_TimeOut(startTime, 1000)){
break;
}
}
return 0;
}

本文探讨了Nordic nRF52832平台RTC计数器在长时间运行时出现的问题,特别是在计数器翻转后的时间计算错误,可能导致程序误判超时情况而进入死循环。文中提供了一种解决方案,通过增加计数器翻转判断来避免此类问题。
712

被折叠的 条评论
为什么被折叠?



