STM32F030K6T6 学习之:定时器程序设计探讨 STM32F030K6T6使用注意事项
发布时间:2018/11/6
假设使用定时器3每1毫秒定时;保存至SD卡的函数是StartSave();
第一种情况:定时器快,主循环慢
1、代码设计1(错误的设计)
[cpp] view plain copy
int cnt = 0; //计数
//TIM3中断处理函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
cnt ++;
}
}
void main(void)
{
代码段1
while(1)
{
代码段2
if(cnt %100 == 0)
{
StartSave();
}
代码段3
}
}
分析:第一种设计经测试发现并没有按照预期的100毫秒间隔保存;原因何在呢?
很明显后台程序运行较快,当cnt 变为100的倍数时,主循环可能到达“代码段3”,当主循环再次到达
“代码段2”时,定时器中断已经改变了cnt的值。
2、代码设计2(在这种情况下正确)
[cpp] view plain copy
int cnt = 0; //计数
unsigned char isOK = 0;
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
if(cnt++ % 100 == 0)
isOK = 1;
}
}
void main(void)
{
代码段1
while(1)
{
代码段2
if(isOK == 1)
{
isOK = 0;
StartSave();
}
代码段3
}
}
设计2避免了1中所出现的问题。
第二种情况:定时器慢,主循环快
在这种情况下上面的代码设计2就出现问题了。出现保存多了的情况。
原因很明显,isOK这个变量的变化相对于主循环来说变化太慢了。会出现isOK一直为1 的情况。
假设定时器定时1ms,主循环0.5ms周期
1、代码设计1(错误的设计)
[cpp] view plain copy
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
cnt++;//该值理论保持时间仅1ms
}
}
void main(void)
{
unsigned char saveFin = 0;
代码段1
while(1)
{
代码段2
if(cnt%100 )
{
StartSave();//明显出现100ms内多次保存的情况,因为主循环快
}
代码段3
}
}
2、代码设计2(正确的设计)
[cpp] view plain copy
unsigned char saveFin = 0;
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
cnt++;//该值理论保持时间仅1ms
}
}
void main(void)
{
unsigned char saveFin = 0;
代码段1
while(1)
{
代码段2
if(cnt%100 == 0 && saveFin == 0 )
{
saveFin = 1;
StartSave();
}
else
{
saveFin = 0;
}
代码段3
}
}
第三种情况:不能确定定时器和main循环周期哪个快的设计
当然主循环的周期不能大于保存周期100ms
[cpp] view plain copy
unsigned char isOK = 0;
unsigned int clkCnt = 0;
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
if(clkCnt++ % 10 == 0)
cnt++;//该值理论保持时间10ms,需要在主循环中清零
}
}
void main(void)
{
unsigned char saveFin = 1;//注意这里的初始值为1,与前面设计不同
代码段1
while(1) //循环周期不能大于10ms,否则丢失对cnt的判断
{
代码段2
if(cnt%10 == 0) //例如在100ms--110ms之间时将“保存标志”清零
{
saveFin = 0;
}
else //例如在110ms--200ms之间时完成保存
{
if(saveFin == 0)//在110ms--200ms之间只能保存一次的代码设计
{
startSave();
saveFin = 1;
}
}
代码段3