搜索
bottom↓
回复: 11

C# SerialPort类 事件触发接收数据的问题请教。

[复制链接]

出0入4汤圆

发表于 2020-1-8 09:20:06 | 显示全部楼层 |阅读模式
最近用C# SerialPort类做单片机上位机程序,发现一个问题:
     单片机一次发送一批数据(400字节左右)到上位机,上位机利用事件触发方式接收数据。
     刚开始数据接收非常不稳定,上位机经常数据接收不完整。
     后来我在事件处理函数最开始处加入了500ms延时,则每次数据接收就完全OK了。
     不知道这是什么原因。感觉这样虽一时可以解决问题,但是感觉这样会影响接收的实时性。
    是否还有更好的解决方法,让事件触发接收既实时,又能保证数据接收完整?
    下面是我的事件处理程序演示代码:
void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
        Thread.Sleep(500);//这个延时非常重要
       
        int n = sp.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
        byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
        sp.Read(buf, 0, n);//读取缓冲数据
       
        //因为要访问ui资源,所以需要使用invoke方式同步ui。
        this.Invoke((EventHandler)(delegate
        {
                for(int i;i<n;i++)
                {
                        textBox1.text += buf[i].ToString();
                }               
        }));
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2020-1-8 09:34:42 | 显示全部楼层
数据接收事件,跟单片机的串口接收中断是一个意思,搞个缓冲区,再搞个超时信号量,就可以了

出100入18汤圆

发表于 2020-1-8 09:39:44 | 显示全部楼层
数据接收本来就不是一次性收完的,可以分很多次,每次大小不一。你总想一次接收完,所以只能加延迟,早来的不理会,存在缓存里。
你这个接收函数只管接收,把数据存到一个数组里,每次收到都继续保存,直到接收长度符合你的需要,再去处理,不用加延时,就实时了。

出0入16汤圆

发表于 2020-1-8 12:26:02 | 显示全部楼层
就是楼上说的,你可以每次触发事件的数据都输出 一下看看,正常应该就是可能分成几次收到的,然后你处理一下缓存一起再处理就行了。(如果你数据发送间隔很短的话也有极端情况是两次数据包合在一起)

出0入8汤圆

发表于 2020-1-8 12:35:26 来自手机 | 显示全部楼层
这属于串口和tcp数据处理的基本常识:粘包与分包处理
粘包,多个数据包合在一起同时收到
分包,一个数据包被分成多个分时送到

出0入0汤圆

发表于 2020-1-8 12:37:15 来自手机 | 显示全部楼层
这么做想不卡死都难

出0入0汤圆

发表于 2020-1-8 12:39:07 来自手机 | 显示全部楼层
用tickcount对比两次接收时间,差别不大的当一包

出0入4汤圆

 楼主| 发表于 2020-1-8 12:44:10 | 显示全部楼层
canspider 发表于 2020-1-8 12:35
这属于串口和tcp数据处理的基本常识:粘包与分包处理
粘包,多个数据包合在一起同时收到
分包,一个数据包 ...

多谢指教,看来要再更深入学习一下了。

出20入186汤圆

发表于 2020-1-8 13:19:13 | 显示全部楼层
根本不是这样用的,一个中断接收数据,收到的数据全部串在一起,然后根据协议头,尾再从数据中间提取出来

出0入4汤圆

 楼主| 发表于 2020-1-8 13:32:29 | 显示全部楼层
yuyu87 发表于 2020-1-8 13:19
根本不是这样用的,一个中断接收数据,收到的数据全部串在一起,然后根据协议头,尾再从数据中间提取出来 ...

你好,能否给个简单的示例程序,谢谢!

出0入0汤圆

发表于 2020-1-8 13:43:56 | 显示全部楼层
弄个list去接收数据,每次接收都产生委托,委托用互斥委托。

出0入4汤圆

 楼主| 发表于 2020-1-8 13:57:38 | 显示全部楼层
本帖最后由 BS_good200xy 于 2020-1-8 14:05 编辑

yuyu87 发表于 2020-1-8 13:19
根本不是这样用的,一个中断接收数据,收到的数据全部串在一起,然后根据协议头,尾再从数据中间提取出来 ...


按下面这样可以吗?

void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
        //Thread.Sleep(500);//这个延时非常重要
       
        int n = sp.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
        byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
        sp.Read(buf, 0, n);//读取缓冲数据
       
        for(int i=0; i < n; i++) FrameBuff[LastLocal + i] += buf[ i ] ;  //当前数据存入帧缓存
        if((FrameBuff[0]==0xaa)&&(FrameBuff[LastLocal + n -1]==0xa5)) //收到完整的一帧数据则立即处理并清零
        {
                 .......//一帧数据处理程序
                for(int i=0; i < LastLocal + n; i++)  //帧缓存清零。
               {
                     FrameBuff[ i ] = 0 ;
               }
               LastLocal = 0 ;
        }
       
        //因为要访问ui资源,所以需要使用invoke方式同步ui。
        this.Invoke((EventHandler)(delegate
        {
                for(int i;i<n;i++)
                {
                        textBox1.text += buf.ToString();
                }               
        }));
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 12:08

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表