C# 串口显示不同步

问题描述

我现在通过以硬件发送数据波特率115200数据一秒一发。上位机接收数据用的是C#winform使用DataReceived这个自带的方法接收数据。前台用了一个RichTextBox控件显示。我设置了一个变量i只要一进DataReceived方法自加一次,值赋给RichTextBox。现在的显示就应该是RichTextBox显示的数一秒加一次1,2,3,4.....一直加下去。但是现在的显示是1,3,,6,9,12。请大神指点。voidSp_DataReceived(objectsender,SerialDataReceivedEventArgse){if(!com.Sp.IsOpen){MessageBox.Show("ComError");}intid=Thread.CurrentThread.ManagedThreadId;if(rtb_Test.InvokeRequired){i=i+1;this.Invoke(a,i);}else{rtb_Test.Text=Builder.ToString();}}privatedelegatevoidSetValues_Thead(inti);voidSetValue(intk){rtb_Test.Text=(i).ToString();}

解决方案

解决方案二:
其中a就是那个委托的对象。我断点调试了下i的数据没问题一直自加(1,2,3,4,5,6,7,8,9,1o.........)但是就是显示的不对
解决方案三:
你写如下代码:for(inti=0;i<10000000;i++){this.Invoke(a,i);}我不信你能看清每一个变化2个数据间隔时间太短,一次跳2个数,那不是太正常了
解决方案四:

解决方案五:
要么你别用rtb_Test.Text=(i).ToString();而改用rtb_Test.Text+=(i).ToString()+"";再看结果,看到底是没变,还是变的太快没看见
解决方案六:
串口是一秒一发一秒更新一次还快吗?使用+=确实能看到!
解决方案七:
引用2楼Z65443344的回复:

你写如下代码:for(inti=0;i<10000000;i++){this.Invoke(a,i);}我不信你能看清每一个变化2个数据间隔时间太短,一次跳2个数,那不是太正常了

你这个循环肯定是太快了!串口设置的才一秒一发,不应该啊?
解决方案八:
引用6楼nileige123的回复:

Quote: 引用2楼Z65443344的回复:
你写如下代码:for(inti=0;i<10000000;i++){this.Invoke(a,i);}我不信你能看清每一个变化2个数据间隔时间太短,一次跳2个数,那不是太正常了

你这个循环肯定是太快了!串口设置的才一秒一发,不应该啊?

现在改成2秒一发效果依旧!
解决方案九:
这个问题类似多线程共享变量使用冲突的问题。为证明问题。可以在i=i+i下面使用console.write(i.tostring);不要设置断点调试,输出i的值如果确实是这个问题。你可以用lock来解决。
解决方案十:
接收几次跟发送几次没有任何关系你只发送一次,但是可能事件会执行2次,因为你使用的异步接收,不能确定回调函数到底什么时候执行比如设备给你发送10个字节,有可能接收到第1个字节它就执行了一次,也有可能先接收了9个再执行,也有可能一次性接收到,这都没准串口通信本身就不是像TCP和UDP那样有"包"的概念,所以程序也不可能自动给你判断每一次的数据是否完整,数据的完整性需要你自己做好协议去验证
解决方案十一:
TCP和UDP在互联网中应用时也会发生"粘包","分包"的现象何况你是串口,如果你发送的太快,很可能一次接收到设备的2次返回值,或者设备一次返回的数据你需要多次才能接收到所以你应该先将接收到的数据放到缓冲区里,比如就是一个List<byte>,每次接收完判断一下长度,如果不足先不处理,等待下一次接收完再次判断
解决方案十二:
引用5楼nileige123的回复:

串口是一秒一发一秒更新一次还快吗?使用+=确实能看到!

串口DataReceived事件的触发不是你一秒钟发送一次就只触发一次的,还跟接收的字节数有关,你虽然是一秒一发,但是你一次发送多少字节的内容呢,从显示的内容看,一次发送的内容触发了3次DataReceived事件,就是1秒钟实际上触发了三次。
解决方案十三:
引用9楼Z65443344的回复:

接收几次跟发送几次没有任何关系你只发送一次,但是可能事件会执行2次,因为你使用的异步接收,不能确定回调函数到底什么时候执行比如设备给你发送10个字节,有可能接收到第1个字节它就执行了一次,也有可能先接收了9个再执行,也有可能一次性接收到,这都没准串口通信本身就不是像TCP和UDP那样有"包"的概念,所以程序也不可能自动给你判断每一次的数据是否完整,数据的完整性需要你自己做好协议去验证

看了大家的解答问题找了!果然是一秒发一次数据,但是可能是分2或者3次接收。eg:我现在测试是2秒发16字节,接收到的是字节大部分是分开的如:16;106;655;313;412;412;313;313;412;313;511;412;313;5115。很少有一次能接16个字节的。怎么能同步接收呢?就是一次数据发完了再接收!在硬件上的中断就是一次收一个字节有个计时器超过一定时间没数据就算一包。那我怎么处理啊因为数据长度不定不能按长度处理。我的思路是开个定时器或者线程500ms处理一次数据。处理完把数组清了。因为是1秒1发500ms足够接收完数据。但是我感觉这种方法不好有没有什么更好的方法。
解决方案十四:
引用12楼nileige123的回复:

Quote: 引用9楼Z65443344的回复:
接收几次跟发送几次没有任何关系你只发送一次,但是可能事件会执行2次,因为你使用的异步接收,不能确定回调函数到底什么时候执行比如设备给你发送10个字节,有可能接收到第1个字节它就执行了一次,也有可能先接收了9个再执行,也有可能一次性接收到,这都没准串口通信本身就不是像TCP和UDP那样有"包"的概念,所以程序也不可能自动给你判断每一次的数据是否完整,数据的完整性需要你自己做好协议去验证

看了大家的解答问题找了!果然是一秒发一次数据,但是可能是分2或者3次接收。eg:我现在测试是2秒发16字节,接收到的是字节大部分是分开的如:16;106;655;313;412;412;313;313;412;313;511;412;313;5115。很少有一次能接16个字节的。怎么能同步接收呢?就是一次数据发完了再接收!在硬件上的中断就是一次收一个字节有个计时器超过一定时间没数据就算一包。那我怎么处理啊因为数据长度不定不能按长度处理。我的思路是开个定时器或者线程500ms处理一次数据。处理完把数组清了。因为是1秒1发500ms足够接收完数据。但是我感觉这种方法不好有没有什么更好的方法。

首先你要确定下位机(硬件)与上位机记性收发数据时,并不严格按照逻辑意义的“包”进行即:1.一个包可能分多个帧发出或接收。2.一个帧里面有可能含有多个包的数据比如,逻辑的包的数据是第一个包3A000c03053F第二包3A000f0406cc那么接收到的帧有可能是3A00;0c03053f3A;000f0406cc针对上述情况,需要定义通讯协议,按照具体的场景可以定义不同复杂度的协议简单的情况,直接协商一个包结束字节(该字节不会在数据中出现)一般的情况下,建议使用类似状态机协议,比如定义一包的数据包头是啥,第二个字节是数据长度,后面跟上数据,最后加上校验码更复杂的不建议重复造轮子,可以借鉴RFID、TCP等等的数据协议
解决方案十五:
引用12楼nileige123的回复:

Quote: 引用9楼Z65443344的回复:
接收几次跟发送几次没有任何关系你只发送一次,但是可能事件会执行2次,因为你使用的异步接收,不能确定回调函数到底什么时候执行比如设备给你发送10个字节,有可能接收到第1个字节它就执行了一次,也有可能先接收了9个再执行,也有可能一次性接收到,这都没准串口通信本身就不是像TCP和UDP那样有"包"的概念,所以程序也不可能自动给你判断每一次的数据是否完整,数据的完整性需要你自己做好协议去验证

看了大家的解答问题找了!果然是一秒发一次数据,但是可能是分2或者3次接收。eg:我现在测试是2秒发16字节,接收到的是字节大部分是分开的如:16;106;655;313;412;412;313;313;412;313;511;412;313;5115。很少有一次能接16个字节的。怎么能同步接收呢?就是一次数据发完了再接收!在硬件上的中断就是一次收一个字节有个计时器超过一定时间没数据就算一包。那我怎么处理啊因为数据长度不定不能按长度处理。我的思路是开个定时器或者线程500ms处理一次数据。处理完把数组清了。因为是1秒1发500ms足够接收完数据。但是我感觉这种方法不好有没有什么更好的方法。

如果你非要这样,就给每个串口开个线程,用while(true)同步接收,否则你现在是异步接收,系统接收到数据就会自动调用回调函数
解决方案:
根据不同的数据协议可以选择不同的处理方式;比如:1一个基础方法一直监听串口接收到的数据,并写入到临时存储数组中2存入临时数组中出发一个检查现有数据的方法,该方法分析现有数据,按照协议,把符合完整“包”定义的从临时存储数组中取出,然后交给后续的方法处理;如果没有符合完整“包”定义的,继续等待,等待下次收到数据继续处理一次
解决方案:
其中API方式就是同步接收的当然你也可以用SerialPort同步接收
解决方案:
引用15楼yanbuodiao的回复:

根据不同的数据协议可以选择不同的处理方式;比如:1一个基础方法一直监听串口接收到的数据,并写入到临时存储数组中2存入临时数组中出发一个检查现有数据的方法,该方法分析现有数据,按照协议,把符合完整“包”定义的从临时存储数组中取出,然后交给后续的方法处理;如果没有符合完整“包”定义的,继续等待,等待下次收到数据继续处理一次

有协议,协议格式大概是:包头+数据长度+数据+校验都有。如果我按从包头数长度解析的话,如果是中间的有一帧丢数据了,那么解析的时候这“包”原有的数据就不够了,我只能从下一“包”数据里面取。结果校验不通过,我只能把这包数据和下一包数据都丢掉。会多丢一包数据。
解决方案:
是不是大家接收的时候都这样啊,今天用监视软件测试了一下别人的程序,为什么别人的是偶尔出现呢我这个总是这样测试的java写的!
解决方案:
引用17楼nileige123的回复:

Quote: 引用15楼yanbuodiao的回复:
根据不同的数据协议可以选择不同的处理方式;比如:1一个基础方法一直监听串口接收到的数据,并写入到临时存储数组中2存入临时数组中出发一个检查现有数据的方法,该方法分析现有数据,按照协议,把符合完整“包”定义的从临时存储数组中取出,然后交给后续的方法处理;如果没有符合完整“包”定义的,继续等待,等待下次收到数据继续处理一次

有协议,协议格式大概是:包头+数据长度+数据+校验都有。如果我按从包头数长度解析的话,如果是中间的有一帧丢数据了,那么解析的时候这“包”原有的数据就不够了,我只能从下一“包”数据里面取。结果校验不通过,我只能把这包数据和下一包数据都丢掉。会多丢一包数据。

首先:你需要跟下位机的同事协商,为什么会丢数据;这是关键,关于上下位机的通讯,需要大家配合,必须有一个可靠度的问题其次:你提到的某个包的数据有问题的时候,直接丢弃这个包,最好有日志,也是为你跟下位机配合的时候拿出证据你直接丢弃有问题的包,不影响后面包的处理
解决方案:
多线程中不能胡乱共享外部变量。大致来说,流程应该这样if(rtb_Test.InvokeRequired){intj;lock(lockFlagObject){i=i+1;j=i;}this.Invoke(a,j);}else{rtb_Test.Text=Builder.ToString();}

其中最关键的,是要传送互不共享的j变量,而不是i。
解决方案:
当然你说的“winform使用DataReceived”设置为仅仅在主线程触发的,那么不用考虑它是在子线程中运行问题。但是这样,就不可能出现“1,3,,6,9,12”的问题,而且你为什么要写this.Invoke而不直接调用a方法呢?到底,你得DataReceived是在主线程触发的,还是在不同的子线程触发的,这需要你自己回答这个问题。
解决方案:
引用21楼sp1234的回复:

当然你说的“winform使用DataReceived”设置为仅仅在主线程触发的,那么不用考虑它是在子线程中运行问题。但是这样,就不可能出现“1,3,,6,9,12”的问题,而且你为什么要写this.Invoke而不直接调用a方法呢?到底,你得DataReceived是在主线程触发的,还是在不同的子线程触发的,这需要你自己回答这个问题。

仔细看回复,问题解决了。跨线程调用需要invoke。
解决方案:
先MARK,我也碰到这个问题,我是serialPort.DataReceived+=newSerialDataReceivedEventHandler(ReceiveData)就是这个样子,如果接到的是'010203'那么就基本会先接到'01'然后再'0203',我觉得问题就在这个触发上面。

时间: 2024-09-20 11:23:20

C# 串口显示不同步的相关文章

酷狗歌词与歌曲显示不同步解决办法

给各位酷狗软件的使用者们来详细的解析分享一下酷狗歌词与歌曲显示不同步问题的解决办法. 方法分享: 1.如果是"桌面歌词",将鼠标移动到歌词处,会出现一个工具栏,点击形状为"铅笔"的图标,然后用鼠标右键点击歌词,就可以使用"歌词提前"."歌词延后"来调整歌词的进度. 2.如果是软件界面的"歌词",直接用鼠标右键点击歌词,然后使用"提前"."延后"调整歌词的进度.   好

《移动App测试的22条军规》——第23章,第8节测试微信App能否及时显示和同步消息

23.8 测试微信App能否及时显示和同步消息我们可以通过同时在多个设备上登录微信App,例如在iPad和Android手机上登录微信App进行测试:然后再验证App能否及时显示和同步消息,比如,当微信App收到消息时,检查这两部设备上的消息是否同步进行了显示(如图23.21所示).

串口显示乱码的原因有哪些?

  在通信波特率为 38400 时,通信正常,arm 板上解受到的数据(ascII码)显示正常. 但是当波特率为 115200 时,解受到的数据就出现乱码的现象! 用ARM2103 给电脑发送信息,用串口高度精灵看,一直接收的都是错误码. 波特率 换了好几档 比如9600 4800 2400 1200(我用的晶振是 11M多点的那个) 等都试过 都是乱码 区别是一个乱码来得快 一个乱码来得慢 串口线 23 脚短接能正常的自收自发 下载到单片机的程序也没啥问题. 真的不知道,原因出现在哪里! 1.

急,关于串口通信收发同步的问题

问题描述 由于某种原因,串口发送被写在了一个循环里面,表示需要多次发送,然而希望是发-收-发-收这样的步调同步工作.根据跟踪,发现目前的程序必须在所有循环执行完毕,也就是所有发送动作完成后,才会去执行串口的DATARECIEVE事件,去读缓冲.如何实现这样的同步呢?发送的代码是这样的:foreach(intiFNinSelectedFN){//**AFN,FN都有了,其他在界面上填入,开始组建通信帧textFN.Text=iFN.ToString();List<byte>frame=newLi

串口显示-串口接收到的数据如何显示在编辑框中显示出来?

问题描述 串口接收到的数据如何显示在编辑框中显示出来? 你好 在帖子中看到你回答"串口接收到的数据如何显示在编辑框中显示出来?"这类的问题.本人初学者也遇到这个问题,对于这个问题很头疼,你能抽空指点下么?最好有完整写. 十分感谢! 解决方案 先用串口读取数据,然后就是调用API操作控件显示了SetWindowText

如何在Windows 8.1的IE11中打开同步选项卡?

  浏览器可以说是每天陪伴我最久的朋友,因为工作关系,大部分时间都要在选项卡分页切来切去,如上社交网站.看新闻,或者查找参考资料等等,常常都是同时打开几十个选项卡.选项卡分页功能对我们来说非常重要,也很怕不小心浏览器崩溃,使所有选项卡都消失无踪.还好IE浏览器有重新打开关闭的选项卡功能,如果想在不同电脑的浏览器之间快速开启最后工作的选项卡网页,就可以通过Windows 8.1系统中IE11自带的同步功能,将选项卡和收藏夹等信息进行同步. 该同步功能目前仅限在Windows 8.1和Windows

电脑中如何通过iTunes使iPhone完成同步照片操作

  电脑中如何通过iTunes使iPhone完成同步照片操作         1.首先要在电脑中下载安装iTunes; 2.将手机通过数据线连接电脑的USB接口,然后点击打开iTunes; 3.点击iTunes界面左上角的手机图标; 4.点击设置里面的"照片",右侧显示出"同步照片"; 5.把"同步照片"左侧的小方框勾选上,下面选"所有文件夹"或者"包括视频". 按照以上方法在电脑中进行操作后,就可以在iT

酷我音乐盒2015桌面歌词不同步怎么调节

  歌词显示不同步,怎么调节 您可以在播放该歌曲的同时,在"正在播放"-"歌词"页面可以使用鼠标滚轮来调节歌词进度; 目前桌面歌词暂时无法直接调节歌词进度,您可以通过上述方法在"歌词"页面调节 桌面歌词是否能够拖拽,怎么样调节大小 首先如果您锁定了桌面歌词的话,需要解锁桌面歌词,可以在托盘菜单中选择"解锁桌面歌词" 然后您可以将鼠标移至桌面歌词的文字上,这将激活桌面歌词的菜单栏,然后鼠标点击菜单栏,就可以将桌面歌词拖拽到您所需

同步多线程

同步多线程(SMT)是一种在一个CPU 的时钟周期内能够执行来自多个线程的指令的硬件多线程技术.本质上,同步多线程是一种将线程级并行处理(多CPU)转化为指令级并行处理(同一CPU)的方法. 同步多线程是单个物理处理器从多个硬件线程上下文同时分派指令的能力.同步多线程用于在商用环境中及为周期/指令(CPI)计数较高的工作负载创造性能优势. 处理器采用超标量结构,最适于以并行方式读取及运行指令.同步多线程使您可在同一处理器上同时调度两个应用程序,从而利用处理器的超标量结构性质. 目 录 1概述 2