如何判断串口已经写完,然后读串口

yilaozhuang 2010-03-18 08:44:57
小弟现在在开发一个读写串口的程序,在读串口的时候,是一帧数据一帧数据进行读的,在读之前需要判断着一帧数据是否已经完全接收好(每帧有固定的格式,但是长度不一定)。
我在判断一帧是否接收完这个条件上是下面这么写的:
while ((com.BytesToRead != com.BytesToRead) || (com.BytesToRead == 0))//当串口缓冲区的字节数一直变化时,延时等待
{
Thread.Sleep(100);//等待100ms
}
int N = com.BytesToRead;//获得接收到帧的字节数
byte[] byte_arr = new byte[N];//定义新的数组,准备接收串口缓冲区数据
com.Read(byte_arr, 0, N_clear_max);//将串口缓冲区数据读入数据
string str_temp = Read_Frame(byte_arr);//将读到的数据按照帧格式进行提取,获得有用的数据
-------------------------------
我在单步运行的时候,用上面那个判断是否接收完一帧数据(串口缓冲区字节一直变化 并上 不等于零)还没有报错,全部自动运行之后就报错,有时候一帧没有读完就把数据给读出来了。
-----------------------------
我想请问各位高手,都是利用什么条件来判断 一帧 数据是否已经写完的?
谢谢!
...全文
509 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
mmhh1208 2010-08-26
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 yilaozhuang 的回复:]
引用 7 楼 wuyazhe 的回复:
其实我说的是你要的答案,只是你没有理解。顺序操作是顺序操作。没有任何矛盾的地方啊?
1.打开串口->注册事件DataReceived
2.按钮点击->触发事件->发送命令,一切结束了。
3.编写DataReceived方法:
List<byte> buffer = new List<byte>(2048);
...DataReceived(...……
[/Quote]

你写的是645通信协议吧,建议把数据域的数据长度利用起来,最后的0x16作为辅助判断。
兔子-顾问 2010-03-19
  • 打赏
  • 举报
回复
这个么。是你协议不完整了。
只有一种通讯协议么?只有一种数据么?
如果是的,14H开头,然后判断16H,14H一起为结尾16H是最后一个字符也认为是结束
cecilia2006 2010-03-18
  • 打赏
  • 举报
回复
楼主是用的 System.IO.Ports.SerialPort serialPort 这个对象么 如果是的话 我用的是while 配合 serialPort.ReadExisting()这个方法做的 应该可以满足楼主的要求
wuzhicheng5 2010-03-18
  • 打赏
  • 举报
回复
最近也是在写串口读写,很是头痛,就如楼主所说,我也是没法确定数据的完整性。
而且,每次收取的数据位数都不一样,甚至跑出一些不在协议之下的数据,很是郁闷,天天改。
协议是3年前定的,现在还不能改,又不全。
我现在主要是判断帧头和数据位数来判断一条报告是否收取完整,哈哈,其它的一律作为异常报告。
没办法啊,否则就得改协议了,但上面不同意!

呵呵,楼主,不防也可这么做!
xingyuebuyu 2010-03-18
  • 打赏
  • 举报
回复
2.我中间用的数据刚好有16(H)所以我不能把16(H)作为依据——不知道是不是设计规约的人当时考虑不全面

这就是设计规约的人当时考虑不全面,所以要改设计啊,不然是没有好办法的。
你可以考虑在收到16(H)后开始计时,在一个超时时间,比如是3S内没收到数据就判断串口已经写完。
兔子-顾问 2010-03-18
  • 打赏
  • 举报
回复
万恶的csdn。给老子辛辛苦苦敲的空格都删掉了。
兔子-顾问 2010-03-18
  • 打赏
  • 举报
回复
其实我说的是你要的答案,只是你没有理解。顺序操作是顺序操作。没有任何矛盾的地方啊?
1.打开串口->注册事件DataReceived
2.按钮点击->触发事件->发送命令,一切结束了。
3.编写DataReceived方法:
List<byte> buffer = new List<byte>(2048);
...DataReceived(...)
{
//1.接受数据并缓存
int n = serial.BytesToRead;
byte[] temp = new byte[n];
serial.Read(temp,0,n);
buffer.AddRange(temp);
//数据有效性判断
for(int i=0;i<buffer.Count;i++)
{
if(找到头尾,数据完整)
{
分析数据();
//这样来实现的,这就是收完了立刻再发
发送下一次的命令();
}
}
}
yilaozhuang 2010-03-18
  • 打赏
  • 举报
回复
多谢wuyazhe(wyz&xyl) 的回答,我前面没有说清楚我要实现的功能,我重新说下:
上位机软件需要读下面芯片里面的数据,每次上位机发一个“读数据”的指令——下位机根据指令回答——将应答数据返回串口——上位机去读应答数据;——下次发指令,读应答。
这个过程中,上位机不发指令,下位机是不会返回数据的。
电脑上的串口是有缓冲机制,但是我需要判断什么时候返回数据已经结束,然后去读,我不能等待很长时间,比如10秒,由于我这个通讯实时性较强,所以需要知道一帧已经返回完成,立刻开始下一条指令。
所以我在设计的时候想找一个判据:能够判断出串口缓冲区里面已经完全接收完了一帧数据。
我开始也按版主说的那个根据帧头和帧尾来判断结束,用的时候出现了问题才改的这个:
1.我的规约规定帧头是4个FE(H),结尾时16(H)
2.我中间用的数据刚好有16(H)所以我不能把16(H)作为依据——不知道是不是设计规约的人当时考虑不全面
兔子-顾问 2010-03-18
  • 打赏
  • 举报
回复
读写没有顺序可言的,你分开设计最好了。
兔子-顾问 2010-03-18
  • 打赏
  • 举报
回复
通讯协议一般是有 头+数据+尾+校验 组成的。不要根据时间片来处理,除非你是下位机程序,应用程序这里本来对时间的精度就是10ms级别的。用时间处理没意义,而且串口本身是有缓存机制的,数据并不是和底层那样来处理,所以应该的步骤,我已经说过很多次了。按上面的条件进行查找,使用状态机依次的找到 头,尾,然后计算校验,通过校验的数据才调用分析方法进行分析。
yilaozhuang 2010-03-18
  • 打赏
  • 举报
回复
错误时提示在我自己写的提取帧里面数据的函数里面:
string str_temp = Read_Frame(byte_arr);
是说里面从某个字节开始后面都没有了,也就是串口中的一帧数据没有接收全。
各位大牛们都是用什么条件来判断一帧数据已经接收完的?
ssny_123 2010-03-18
  • 打赏
  • 举报
回复
我也想知道答案,帮顶一下!!!!!!!!!!!!!!!!!
兔子-顾问 2010-03-18
  • 打赏
  • 举报
回复
报错提示是什么?
yilaozhuang 2010-03-18
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 cecilia2006 的回复:]
楼主是用的 System.IO.Ports.SerialPort serialPort 这个对象么 如果是的话 我用的是while 配合 serialPort.ReadExisting()这个方法做的 应该可以满足楼主的要求
[/Quote]
不能一下子readexisting(),假如一帧没有接收完,你就取走了,那样按规约去提取有用数据的话肯定有问题
yilaozhuang 2010-03-18
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wuyazhe 的回复:]
其实我说的是你要的答案,只是你没有理解。顺序操作是顺序操作。没有任何矛盾的地方啊?
1.打开串口->注册事件DataReceived
2.按钮点击->触发事件->发送命令,一切结束了。
3.编写DataReceived方法:
List<byte> buffer = new List<byte>(2048);
...DataReceived(...)
{
//1.接受数据并缓存
in……
[/Quote]
感谢老大的回帖啊。
我现在遇到的问题就是不能用帧头和帧尾来判断,我中间的有用数据有何帧头和帧尾相同的,会误判

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧