历史上的今天
今天是:2024年10月21日(星期一)
2018年10月21日 | STM32学习之:定时器程序设计探讨
2018-10-21 来源:eefocus
假设使用定时器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
}
}
上一篇:STM32学习之:事件标志组
史海拾趣
|
在多电平系统中,直流电平转换是很常见的事情,这直接关系到一个系统设计的成败,TI在直流电平转换上的方案还是不错的,如SN74LVC4245(3.3V~5V),SN74AVC8T245(1.2V~3.6V)等,附件是TI的相关器件的详细介绍。 … 查看全部问答> |
|
我用lpc1343枚举了一个USB HID键盘设备,描述符我用的USB 键盘的,以前用过没问题的。 用end1 发送键盘数据,但是空闲时段一直发送0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00.但是按键数据又是正常的,就是表象没什么影响。不知道会不会对别的有影 ...… 查看全部问答> |
|
上海汉的信息技术股份有限公司 诚招嵌入式软件工程师 任职要求: 1.本科以上学历,计算机软件或相关专业,2年以上工作经验。 2.具有2年以上C++语言,linux或unix开发经验。 3.熟悉嵌入式开发。 4.懂日语者优先。 有意者请将简历发 ...… 查看全部问答> |
|
单片机与PC机的串口通信时,刚开始的时候传的数据是正确的,工作一段时间,传的数据就出现错误,当向PC机传固定的一个数据时,还出现时而正确,时而错误的情形,不知道这是为什么。… 查看全部问答> |
|
Building configuration: gas - Release Error[e16]: Segment DATA16_Z (size: 0xb9 align: 0x1) is too long for segment definition. At least 0x38 more bytes needed. The pro××em occurred while processing the segment placement comma ...… 查看全部问答> |
|
哪位大侠写过msp430f149控制DHT11温室读传感器的串口显示程序,我调了好久总是不能显示数据 ?不知道什么原因?高手帮忙啊,不胜感激之至!! 串口程序; #include \"usart.h\"struct DHT_data{ unsigned char DH_H; ...… 查看全部问答> |
|
ucos ii 的中断处理过程是这样的(直接上代码): { OSIntEnter(); //Call ISR... OSIntExit (); return; } OSIntExit () { #if OS_CRITICAL_METHOD == 3&n ...… 查看全部问答> |




