介绍一个定时器的使用小技巧,今天写代码需要用到一个功能,实时测量程序运行时间,要求测量时间精度要高。
精度高就想到了硬件定时器,但是整个系统比较复杂,硬件定时器都被占用了,想了想只能和某项功能共用一个定时器了。系统中使用了一个systick定时器,systick定时器是一个自动装载递减定时器,即,计数器从设定值开始递减,减到零时触发systick中断,然后计数器自动装载初值开始下一个计数周期。这里配置为1ms产生一次中断,中断内有一个全局变量加1,如果直接用这个变量计算时间,精度±1ms,太差了。于是乎又写了俩函数,可以实现us级别测量,后面一一介绍。
void SysTick_Handler(void)
{
g_dwSysTickCnt++;//ms中断,精度只有±1ms
}
函数1:测量开始函数:
//测量开始函数
void drvMeasureUsStart(void)
{
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //关闭定时器
g_dwOldTime = SysTick->VAL; //记录当前计数值
g_dwStartTimeMs = g_dwSysTickCnt; //获取当前ms数
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //使能定时器
g_dwReload = SysTick->LOAD; //获取重载值
}
函数2:测量结束函数:
DWORD drvMeasureUsStop(void)
{
DWORD dwNowTime,dwpRunTimeUs;
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //关闭定时器
dwNowTime = SysTick->VAL;
g_dwStartTimeMs = g_dwSysTickCnt - g_dwStartTimeMs; //获取ms数差值
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //使能定时器
if(g_dwStartTimeMs > 0u)
{
g_dwStartTimeMs--;
dwpRunTimeUs = g_dwReload - dwNowTime + g_dwOldTime;
}
else
{
dwpRunTimeUs = g_dwOldTime - dwNowTime;
}
g_dwStartTimeMs *= 1000u; //换算为us
dwpRunTimeUs = dwpRunTimeUs/(g_dwSysTickClockMhz); //换算为us
dwpRunTimeUs += g_dwStartTimeMs;
return dwpRunTimeUs;
}
使用方法:
//测量usercode()函数运行时间
{
DWORD dwTime;
...
...
drvMeasureUsStart();
usercode();
dwTime = drvMeasureUsStop();
...
...
}
全部0条评论
快来发表一下你的评论吧 !