技巧1:关于串口接收
对于串口数据帧到检测,对于串口接收有判定帧头、尾 FIFO缓存等方式,推荐采用超时判断来确定一帧数据接收完成,尤其对于处理GPS,3G模块数据效,比判断帧头、尾效果好的多。参考网友模式
//检测超时函数 供定时器中断调用-1ms一次
// t为超时时间
__inline void Chk_TimeOut(u8 t)
{
if(!uartRMsg.rcOK && (uartRMsg.rcIndex>=8) && (++uartRMsg.rcS >=t) ) //超时之后,开始重新解码
uartRMsg.rcOK = true;
}
//接收函数, 供USART中断调用
__inline void Recieve_MSG(char ch)
{
uartRMsg.rcS = 0; //如果接收到数据,则清除超市检测计数,
if(!uartRMsg.rcOK)
{
uartRMsg.Buf.buf[uartRMsg.rcIndex ++] = ch; //赋值
if(uartRMsg.rcIndex>=8 && uartRMsg.Buf.msg.cmd!=16)//其他条件成立的时候也可进入解码程序<此程序为Modbus应用,可改为接收到结束符等>
uartRMsg.rcOK = true;
}
}
//供主函数调用
void MSGTransfer(void)
{
if(!uartRMsg.rcOK) return;
//......数据解析部分
}
技巧2 关于systick
系统滴答用作精确定时,网上的代码如下:
SysTick_SetReload(delay_fac_us * Nus); /* 时间加载 */
SysTick_CounterCmd(SysTick_Counter_Clear); /* 清空计数器 */
SysTick_CounterCmd(SysTick_Counter_Enable); /* 开始倒数 */
do
{
Status = SysTick_GetFlagStatus(SysTick_FLAG_COUNT);
}while (Status != SET); /* 等待时间到达 */
SysTick_CounterCmd(SysTick_Counter_Disable); /* 关闭计数器 */
SysTick_CounterCmd(SysTick_Counter_Clear); /* 清空计数器 */
该函数存在很大的局限性,即不可重入。所以在中断中不能使用。不可重入的原因主要有两个:
1 滴答计数器在重入返回时被关闭,导致计数停止。
2 即便在此函数的do{}while()中不停开启计数器,重入返回时,可能计数器已溢出到下一个周期。
对于以上不足,实际上可以直接采用systick的系统滴答来实现精确延时即可,即永不关闭系统滴答,开机后始终计数。
具体实现函数:
3 关于systick用于超时检测
在应用中经常出现要检测超时的场景,此时采用jiffies get_systick 非常方便,而应当注意的是溢出的情况,即在超时比较时,注意jiffies回绕问题,可以参考linux内核中的#define time_after(a,b) 的写法。
技巧3 关于屏幕数据刷新。
有时我们在GUI编程过程中需要多个不同频率的刷新某些数据,此时我们即可采用仅仅使用一个硬件定时器systick即可实现多个软件定时,实现多个软件定时事件,在中断处理函数中轮询这几个定时事件的定时标志,完成对相应事件处理的回调。
4 关于延时函数
void delay_1us(u32 Nus)
{
unsigned long j;
while (Nus--) {
j = 0;
while (j--);
}
}
以上函数在STM32内编译时,会偶尔出现延时时间不一致的情况。大概相差0.8倍的延时时差,因此对于延时精确的代码,不宜使用。推荐采用定时器延时。
阅读(1793) | 评论(0) | 转发(0) |