最近在做的项目中涉及到串口通信编程,队友在做这一模 块的时候遇到了一个相信很多人都可能遇到的问题,那就是接受数据的冲突或者丢失。队友让我帮他调试的时候,足足花了近两个小时才把问题给解决了,现觉得有 必要总结一下以给遇到类似问题的朋友一个思路吧~

问题是这样的,从相应的硬件设备每隔2秒便发送一个大小为15的字节数据,存的是16进制数据,每条数据以7E开头以7E结尾。例如:7E 09 01 1A ... 7E。但是PC端在接受显示的时候却出现了问题,如前五个数据接受正常,接下来的都是以00填充,而剩下的10个数据却出现在下条数据显示的位置。如下所 示:

7E 09 01 1A 5C 00 00 00 00 00 00 00 00 00 00 /// 03 06 1A 2C 3D 09 6C 32 12 7E 00 00 00 00 00 00/// ........

总之感觉错位了,对了,先把PC端代码贴一下吧:


public partial class Form1 : Form
    {
        /// <summary>
        /// 接受数据的串口类 
        /// </summary>
        SerialPort spReceive;
        delegate void ReceivData(byte[] bytes);

public Form1()
        {
            Form1.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();
          
            spReceive =new SerialPort("COM5", 57600, Parity.None, 8, StopBits.One);             
            spReceive.Open();
            
            //设置触发 DataReceived事件的阀值,在调试中发现这个不起作用,不解~      
            spReceive.ReceivedBytesThreshold =15;            
            spReceive.DataReceived +=new System.IO.Ports.SerialDataReceivedEventHandler(spReceive_DataReceived);            
        }

/// <summary>
        /// 更新接受到得数据到UI 界面显示
        /// </summary>
        /// <param name="bytes"></param>
        public void UpdateReceiveToUI(byte[] bytes)
        {
            if (txtReceive.InvokeRequired)
            {
                ReceivData dl = new ReceivData(UpdateReceiveToUI);
                object arg = bytes;
                txtReceive.Invoke(dl, arg);
            }
            else
                txtReceive.Text += "/" + BitConverter.ToString(bytes);
        }

/// <summary>
        /// 接收到串口数据触发的事 件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void spReceive_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            byte[] recevied = new byte[15];
            int size = spReceive.Read(recevied, 0, recevied.Length);

if (size >0)

UpdateReceiveToUI(recevied);

}

}

在调试的过程中,当我spReceive_DataReceived函数中的byte[] recevied = new byte[15]; 后面在加上个初始化,如下:

for( int i=0; i<recevied.Lengthl;i++)

recevied[i]=11;

这个时候界面显示的时候,凡是以00显示的地方都被11替换了。这肯定了这些00是由于传送的15个字节数组未被完全填充到我们定义的字节数组中,即 Read(byte [] bytes,int offset,int size)函数未一次性将字节数组填充完,而是分了两次。但是在此过程中我使用的是SerialPort类的DataReceived事件,即没收到一条 数据便会触发,而这儿的现象仿佛是事件被触发了多次。后来自己在SerialPort类的属性里面找了下,突然发现了有个 ReceivedBytesThreshold属性,从这个属性可以看出我们可以控制接受多少个字节触发一次DataReceived事件。于是,我便将 阀值设为15个字节,满以为问题解决了,可是结果却~

囧啊,可是这个属性也给了我们一些提示,也找到了问题的症结所在。那就是,DataRecevied事件触发的阀值,即接受到多少个字节数触发一次偏小, 结果导致了我们一条大小为15个字节的数据触发了两次DataReceived事件。要解决这个问题,我们可以沿着这个思路走下去,那就是延迟 DataRecevied事件的触发直到我们一条数据接受完毕。

所以在spReceive_DataReceived事件函数中,我们做如下修改:

byte[]  receiveBuffer=new byte[15];

public void spReceive_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)

{

int bytesRead = 0;

spReceive.ReceivedBytesThreshold = 100000;     //延迟DataRecevied事件的再次触发

while (true)

{

if (bytesRead >= 15)      //这儿的15是我一条数据的大小

{

byte[] bytes = new byte[bytesRead];

Array.Copy(receiveBuffer, 0, bytes, 0, bytesRead);

Array.Clear(receiveBuffer, 0, bytesRead);

UpdateReceiveToUI(bytes);

bytesRead = 0;

break;

}

try

{

receiveBuffer[bytesRead] = (byte)spReceive.ReadByte();

++bytesRead;

}

catch (Exception ex1)

{

MessageBox.Show(ex1.Message);

break;

}

bytesRead = 0;

spReceive.ReceivedBytesThreshold = 1;            //将延迟改回正常

}

}

经过上述的改动,便可以解决读取串口数据冲突与丢失的问题了~不周之处,还望各位斧正~

转 C# 串口编程遇到的问题以及解决方法相关推荐

  1. Qt 串口通信 高速发送出错的解决方法总结

    使用网上的qextserialport-1.2类,自行开发多线程串口通信.开发的过程中,出现两个问题: 问题1:我用信号槽跨线程调用串口类MyCom 发送和接收数据,中间运行的时候,会内存错误,Qt ...

  2. java并发编程之 并发问题及解决方法

    一.并发问题的根源 首先,我们要知道并发要解决的是什么问题?并发要解决的是单进程情况下硬件资源无法充分利用的问题.而造成这一问题的主要原因是CPU-内存-磁盘三者之间速度差异实在太大.如果将CPU的速 ...

  3. win7 64位VC串口控件打不开解决方法

    写了个MSComm的串口通信程序,在没有安装Vc的机器上没有办法运行.需要手动注册控件. 不过手动注册可以写成bat文件来完成.首先是建一个文件夹,64位系统将Windows/SysWOW64(32位 ...

  4. gtk/Glade编程 编译命令不成功 解决方法

    摘自:http://blog.chinaunix.net/uid-26746982-id-3433656.html 当我们编写gtk/glade程序,gcc编译时,用如下命令: #gcc -o ser ...

  5. ESP8266-Arduino网络编程实例-WiFi连接丢失解决方法

    WiFi连接丢失解决方法 在实际应用中,WiFi连接上的,有可能存在连接断开的情况.比如, ESP8266 暂时失去 Wi-Fi 信号: ESP8266 暂时不在路由器的 Wi-Fi 范围内: 路由器 ...

  6. 【linux】串口编程(三)——错误处理

    一个程序的优劣,可以从多个角度来判断,错误处理就是其中之一.从代码中的错误处理部分,可以体现出一个程序员的水平和修养. 下面还是以libmodbus为例,总结下串口编程中的错误处理. [1]基础 [1 ...

  7. 【linux】串口编程(一)——配置串口

    目前遇到的串口编程都是用于通信,很少作为终端显示.以前没有对串口编程做深入研究,本次以libmodbus源码中对串口的设置为例,详解总结串口编程时配置的属性(struct termios) 以libm ...

  8. QT开发(五十)——QT串口编程基础

    QT开发(五十)--QT串口编程基础 一.QtSerialPort简介 1.串口通信基础 目前使用最广泛的串口为DB9接口,适用于较近距离的通信.一般小于10米.DB9接口有9个针脚. 串口通信的主要 ...

  9. 【C#串口编程计划】C#通讯类库构建

    这篇图文是关于[串口编程计划]的最后一篇"C#通讯类库的构建",也就是把这次所做的关于串口系统的代码集成到团队的类库中,做到代码的可复用(以后写串口的系统,只需要写数据的定义,协议 ...

最新文章

  1. 综述|工业金属平面材料表面缺陷自动视觉检测的研究进展
  2. 程序员和产品经理的恩怨情仇 | 每日趣闻
  3. 吴恩达机器学习笔记21-正则化线性回归(Regularized Linear Regression)
  4. 跨浏览器设置标签样式
  5. Gogland IDE Run/Debug Configurations 配置说明
  6. 社会保险省内转移需要什么手续或过程?
  7. 文献记录(part12)--Biclustering of human cancer microarray data using co-similarity based co-clustering
  8. 离线安装Eclipse的Color theme plugin
  9. MVC与三层架构的联系及三层架构实现学生注册功能
  10. python列表删除会出现一个错误 list index out of range
  11. VB 2010 (32)泛型方法
  12. 天线波束形成matlab,数字多波束形成的MATLAB仿真
  13. 【MQTT编程】Last will and Testament(LWT Payload设置)
  14. 硬石-专题04 步进电机控制(第1节)_步进电机基本知识介绍1
  15. 概念模型向逻辑模型的转换
  16. java调用python库pyd_Java怎么调用pyd文件
  17. 下面哪个linux内核是稳定版本,哪个 Linux 内核版本是 “稳定的”?
  18. numpy.outer()函数
  19. 电路板阻抗原理知识及应用
  20. Prometheus监控系列一 | 安装部署及配置

热门文章

  1. 用python 10min手写一个简易的实时内存监控系统
  2. PowerDesigner连接SqlServer数据库
  3. 使用原生JavaScript
  4. vb编程的好帮手--资源文件
  5. 快头条月增迅猛超微视 三四线城市“流量炼金”的上限在哪?
  6. 为什么停车类APP看似缺口巨大却没有成长起来?
  7. MySQL数据库同步小工具(Java实现)
  8. Horizon View 6-安装View Composer组件⑵
  9. Java实现二叉树的创建、递归/非递归遍历
  10. mysql tinyint和char(1)性能对比