标题:
请教单片机如何避免串口接收数据丢失?
[打印本页]
作者:
happy2058
时间:
2021-10-13 00:17
标题:
请教单片机如何避免串口接收数据丢失?
单片机与触控屏通信 按下屏幕下发 AA 79 ** ** 33 cc c3 3c 抬起屏幕下发 AA 78 ** ** 33 cc c3 3c 中间两个字节用户定义相同指令
以下部分代码
uchar buf[16]; //接收缓存区 这里因为上电握手最大长度,所以给了16 下面程序只用到8个字节
uchar rp = 0; //缓存区地址
void interrupt_uart() interrupt 4 //using 3 //串口接收,定时器2 115200
{
if (RI)
{
RI = 0 ;
buf[ rp++ ] = SBUF;
if(SBUF==0X3C) //接收到尾 地址复位
rp=0;
}
}
void key_service() //放在大循环 while(1) 里一直调用
{
switch(buf[1]) //对应该按下 指令 79后进行比较
{
case 0X79:
if( buf[3]==0x01 && buf[7]==0x3c) //buf[3]==0x01 是用户指令01 只判定buf[3]
{
memset(buf, 0, 16)
**********此处省略**********
}
if( buf[3]==0x02 && buf[7]==0x3c)
{
memset(buf, 0, 16)
**********此处省略**********
}
if( buf[3]==0x03 && buf[7]==0x3c)
{
memset(buf, 0, 16)
**********此处省略**********
}
if( buf[3]==0x04 && buf[7]==0x3c)
{
memset(buf, 0, 16)
**********此处省略**********
}
......................
总共15个IF判断
break;
case 0X78: //对应该抬起 指令 78后进行比较
if(buf[0]==0xAA && buf[7]==0x3c) // 接收完成
{
for(i=0;i<16;i++) //清空缓存区
{
buf[ i]=0;
}
//memset(buf, 0, 16) //清空缓存区 感觉这个函数比较费时,所以没用 ,求指教
}
break;
default:break;
}
}
目前程序运行正常。
请问,如果数据接收慢,当case 0X79: 跑完了,用户指令才来,或者我要比较指令01 。但可能跑到03去比较了。这时候 01 才到。那么这一次不执行。退出 case 0X79: 这时候缓存区未被清空,(此处为单次点击)
当抬起屏幕的时候指令78来了,会覆盖缓存区 ,然后 switch(buf[1]) 在while(1) 里一直调用。直到清空
(正常操作点击屏幕按下抬起不作停留 。屏幕下发数据是 AA 79********** AA 78 ********** 中间有很短的间隔)
这次点击那就无效了。
如果在case 0X79后面加上while (buf[7]!=0x3c) 防止没接收完就判断,会有多大影响。谢谢大家
作者:
ucmic
时间:
2021-10-13 07:45
参考宋老师的串口接收部份。百度金沙滩工作室
作者:
ly1972001
时间:
2021-10-13 08:00
再加缓存,就不怕buf[]的变化了。当一帧数据接收完毕,置标志位,放入缓存,再进行数据处理。
作者:
npn
时间:
2021-10-13 08:09
请提供下波特率和晶振频率确定是否为误码率高。
作者:
18701931930
时间:
2021-10-13 08:21
如果你的单片机处理速度比较慢,那就降低波特率。或者采用闭环控制的方式。
作者:
xuyaqi
时间:
2021-10-13 08:35
应该是一帧数据接收完设置标志,再进行判断,不应该收一个判断一个。
作者:
happy2058
时间:
2021-10-13 09:51
npn 发表于 2021-10-13 08:09
请提供下波特率和晶振频率确定是否为误码率高。
24M 1T 115200
作者:
xstong
时间:
2021-10-13 10:16
总体思路:中断仅缓存接收数据,接收完毕唤醒任务处理数据。
使用一个定时器,每次串口中断接收到一个字节,缓存数据后更新定时器延后一段时间产生定时器超时中断,只要串口连续接收到数据,超时中断不会产生,反之只要定时器发生超时中断,则判定为一帧连续数据接收完毕。
整个串口数据接收过程,全部由串口和定时器中断完成,无需任务参与,任务只需要在接收完毕后由定时器中断唤醒后做数据帧解析处理。
如果其它功能应用对中断占用时间不敏感,可以直接在定时器超时中断里面处理数据帧。全程任务完全无需参与了。
作者:
npn
时间:
2021-10-13 11:00
happy2058 发表于 2021-10-13 09:51
24M 1T 115200
串口需要用 22.1184Mhz 或 33.1776Mhz 才可以的。
作者:
lengrudie
时间:
2021-10-13 11:50
增加数据缓存是比较好的方法,可以的话最好做个环形队列,先进先出。
作者:
笨笨兔
时间:
2021-10-13 14:12
建议改变整个程序结构,那样更简单,更有效。
作者:
yzwzfyz
时间:
2021-10-13 17:10
所有的中断程序处理时间,不大于1个字节的串行拼装时间,你能做到就可以。
作者:
xiao_yyp
时间:
2021-10-13 17:17
加缓存, 数据接收完毕,设置标志位,放入缓存后再进行数据处理
作者:
188610329
时间:
2021-10-13 20:46
做缓冲池,比如你一个指令8个字节,你做一个128字节的缓冲池,最多保存16个指令,那么,应该就没啥问题了。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1