c#串口接收字符串

时间:2022-08-02 23:43:44
我在单片机上每10s发送4个字符到上位机  波特率9600
上位机接收事件里面将接收到的字符和时间记录日志,代码如下:
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {

            string str = serialPort1.ReadExisting();
            write_log(str);  //记录日志  将接收到的数据和时间记录下来
        }
然后我接收一段时间后查看日志内容如下:
2760    2016/6/11 16:35:26
2           2016/6/11 16:35:37
760      2016/6/11 16:35:37

2           2016/6/11 16:35:48
760      2016/6/11 16:35:48

2          2016/6/11 16:35:59
76       2016/6/11 16:35:59
0         2016/6/11 16:35:59

2         2016/6/11 16:36:09
75      2016/6/11 16:36:09
9        2016/6/11 16:36:09

2        2016/6/11 16:36:20
759   2016/6/11 16:36:20

27     2016/6/11 16:36:31
59     2016/6/11 16:36:31


可以看出我一次发送的数据除了第一次能接收完整  其余时候都要分2次或者3次接收
是windows缓冲机制的原因吗?
各位大神指点指点  这个怎么解决?加快波特率可以吗?

6 个解决方案

#1


分几次接收那是不确定的。如果你电脑比较卡,那么你的 .net 组件接收缓存中的数据自然就少一些,那么自然就需要多接受一次才可能收到消息的结尾。

首先搞明白,“本来就应该写成循环接收数据的程序流程”。在这个程序写正确之后,再来考虑为什么不能快速收到信息的问题。因为效率并不会影响正确性。如果连正确你都不保证,就不要奢谈“分2次或者3次接收”。这是解决的问题的正确次序问题。

#2


对于 .net 的串口组件来说,有两种可以设置的模式。一种是你可以设置一个“消息结束符”,组件收到这个符号之后才会触发 DataReceived 事件。另外一种(默认)就是不设置这个结束符,组件只要是在轮到处理应用程序消息循环时就会触发这个 DataReceived事件,而寻找结束符的工作交给你自己来办。

#3


所谓“加快波特率”是个不靠谱的想法,因为加到“多少才保证没有这个问题,而又能保证通讯稳定”?上面已经说过了解决问题的正确次序了。

有一些比较坑爹的博客,你会看到甚至上面在DataReceived  事件处理中写了 Thread.Sleep(2000)这种代码。其实用屁股都能想清楚,数据都来了不跑去接收,干嘛还要故意延迟2秒?

其出发点,就是用不靠谱的“瞎试”的做法莱蒙自己。这个数值设置为多少合适?多少才能保证没有接收问题、同时又能保证一有完整数据就立刻收到完整数据?设置大点好还是小点好?——根本没有纠结的结果。

因为这根本就不是靠谱的思路。靠谱的思路是先保证完整接收到消息,不管是1次2次还是3次收到的,先保证流程数据正确。而不需要考虑玩什么“波特率、阻塞时间”之类的。

#4


找找单片机设计者,设置两边一样,再不行多试试理性波特率。

#5


首先先用串口调试工具测试,如果调试工具没问题,那就是你自己的代码有问题。

#6


在 datareceived 事件里用 console.writeline (e.EventType) 你会发现一次数据接收会 cw 多次,这说明事件被触发了多次。
正如 sp1234所说,通常数据到达缓存,sp 就会触发一次事件,除非事先设定了校验位。
可即便设置了校验,由于缓冲区大小的限制,也未必会按照理想情况触发事件。
所以,通常会定义一个全局变量,比如 list<char> list<byte> 或者string,
然后,在事件中判断校验位比如02、03或者回车等等。
在读取到校验位时,将全局变量整合成自己需要的数据,清空,再继续读取后续数据。


#1


分几次接收那是不确定的。如果你电脑比较卡,那么你的 .net 组件接收缓存中的数据自然就少一些,那么自然就需要多接受一次才可能收到消息的结尾。

首先搞明白,“本来就应该写成循环接收数据的程序流程”。在这个程序写正确之后,再来考虑为什么不能快速收到信息的问题。因为效率并不会影响正确性。如果连正确你都不保证,就不要奢谈“分2次或者3次接收”。这是解决的问题的正确次序问题。

#2


对于 .net 的串口组件来说,有两种可以设置的模式。一种是你可以设置一个“消息结束符”,组件收到这个符号之后才会触发 DataReceived 事件。另外一种(默认)就是不设置这个结束符,组件只要是在轮到处理应用程序消息循环时就会触发这个 DataReceived事件,而寻找结束符的工作交给你自己来办。

#3


所谓“加快波特率”是个不靠谱的想法,因为加到“多少才保证没有这个问题,而又能保证通讯稳定”?上面已经说过了解决问题的正确次序了。

有一些比较坑爹的博客,你会看到甚至上面在DataReceived  事件处理中写了 Thread.Sleep(2000)这种代码。其实用屁股都能想清楚,数据都来了不跑去接收,干嘛还要故意延迟2秒?

其出发点,就是用不靠谱的“瞎试”的做法莱蒙自己。这个数值设置为多少合适?多少才能保证没有接收问题、同时又能保证一有完整数据就立刻收到完整数据?设置大点好还是小点好?——根本没有纠结的结果。

因为这根本就不是靠谱的思路。靠谱的思路是先保证完整接收到消息,不管是1次2次还是3次收到的,先保证流程数据正确。而不需要考虑玩什么“波特率、阻塞时间”之类的。

#4


找找单片机设计者,设置两边一样,再不行多试试理性波特率。

#5


首先先用串口调试工具测试,如果调试工具没问题,那就是你自己的代码有问题。

#6


在 datareceived 事件里用 console.writeline (e.EventType) 你会发现一次数据接收会 cw 多次,这说明事件被触发了多次。
正如 sp1234所说,通常数据到达缓存,sp 就会触发一次事件,除非事先设定了校验位。
可即便设置了校验,由于缓冲区大小的限制,也未必会按照理想情况触发事件。
所以,通常会定义一个全局变量,比如 list<char> list<byte> 或者string,
然后,在事件中判断校验位比如02、03或者回车等等。
在读取到校验位时,将全局变量整合成自己需要的数据,清空,再继续读取后续数据。