基于事件触发方式的串行通信接口数据接收案例

广东职业技术学院  欧浩源

1、案例背景

之前写过一篇《基于多线程方式的串行通信接口数据接收案例》的博文,讨论了采用轮询方式接收串口数据的情况。经过使用了多线程来处理,而然轮询的办法比较还是比较笨拙的。我们在实际的项目开发中,更加常用的是基于事件触发的方式,这个方式不但好用,而且灵活,只是使用起来需要更多的一点专业知识。在本博文中,就“传感器模块每隔1秒钟向上位机传送4字节的电压数据帧”的项目,对该方法的设计进行详细的讲述。

  数据帧的格式:帧头(0xAF)    电压数据高8位    电压数据低8位    帧尾(0xFA)

2、事件触发方式的工作原理

SerialPort类中有一个DataReceived事件,当串口接收到了ReceivedBytesThreshold属性设置的字符个数或者接收到了文件结束符并将其放入了串口接收缓冲区时,就会触发DataReceived事件。

ReceivedBytesThreshold属性决定了串口读缓存中数据达到多少字节时才触发DataReceived事件,其默认值为1。如果串口接收的是固定长度的数据,则将ReceivedBytesThreshold属性设置为接收数据的长度;如果接收数据的结尾是固定的字符或字符串,则可以采用ReadTo方法或在DataReceived事件中判断接收的字符是否满足条件。

由于DataReceived事件在辅线程中被触发,不能与主线程中的数据显示控件直接进行数据传输,必须使用间接方式来实现。当收到完整的一条数据时,返回主线程处理或在主窗体上显示时,要使用跨线程的处理方式,在C#中可以采用控件异步委托的方法BeginInvoke或者控件同步委托的方法Invoke

3、引入命令空间

使用多线程的方式,需要引入命名空间:System.Threading;

使用串行通信接口,需要引入命名空间:System.IO.Ports;

4、初始化工作

给主窗体添加窗体装载事件(即Load事件),在该事件中对各个控件的属性进行初始化工作。

重点:在这里要给DataReceived事件添加一个委托,将事件与数据接收处理方法DataReceivedHandler关联起来。

  com.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

        SerialPort com = new SerialPort();                  //实例化一个串口对象
private void Form2_Load(object sender, EventArgs e)
{
string[] ports = { "COM1", "COM2", "COM3", "COM4", "COM5" };
foreach (string str in ports)
{
comboBox1.Items.Add(str);
}
comboBox1.SelectedIndex = ; string[] baudrate = { "", "", "", "", "", "" };
foreach (string str in baudrate)
{
comboBox2.Items.Add(str);
}
comboBox2.SelectedIndex = ; comboBox3.Items.Add("");
comboBox3.Items.Add("");
comboBox3.Items.Add("");
comboBox3.SelectedIndex = ; comboBox4.Items.Add("");
comboBox4.Items.Add("1.5");
comboBox4.Items.Add("");
comboBox4.SelectedIndex = ; comboBox5.Items.Add("None");
comboBox5.SelectedIndex = ; com.ReceivedBytesThreshold = ; //设置串口接收到4个字节数据才触发DataReceived事件
//为串口DataReceived事件添加处理方法
com.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}

5、数据接收处理方法DataReceivedHandler

当串口接收到ReceivedBytesThreshold属性设置的字节数时,就会触发DataReceived事件,从而执行DataReceivedHandler方法。在该方法里进行对串口接收数据的分析处理等工作。如果需要在这个方法里面将接收到的数据或者对数据的处理结果显示到窗体的控件上,那么就需要进行跨线程的处理了。

注意:在本方法中采用了BeginInvoke方法来处理跨线程的问题,在这个过程中,涉及到Action委托Lambda表达式的知识点是很常用的,但在这里就不展开叙述了,大家可以百度查找学习。

        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
string strRcv = "";
int count = com.BytesToRead; //获取串口缓冲器的字节数
byte[] readBuffer = new byte[count]; //实例化接收串口数据的数组
com.Read(readBuffer, , count); //从串口缓冲区读出数据到数组 for (int i = ; i < readBuffer.Length; i++)
{
strRcv += readBuffer[i].ToString("X2") + " "; //16进制显示
}
this.BeginInvoke(new Action(() =>
{
textBox1.AppendText(strRcv);
})); if (readBuffer[] == 0xAF && readBuffer[] == 0xFA) //判断数据的帧头和帧尾
{
Int32 ad = readBuffer[];
double advalue;
ad <<= ;
ad |= readBuffer[]; //从数据帧中将电压数据取出
advalue = ad;
advalue = (advalue * 3.3) / ; //将数据换算为实际的电压值
this.BeginInvoke(new Action(() =>
{
label2.Text = advalue.ToString("F2") + " V";
}));
}
}

6、打开串口

在进行串口通信的时候,一般的流程是:先设置通信的端口号波特率数据位停止位校验位,然后打开串口,接着发送数据和接收数据,最后要关闭串口。

        private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "打开串口")
{
com.PortName = comboBox1.Text; //选择串口号
com.BaudRate = int.Parse(comboBox2.Text); //选择波特率
com.DataBits = int.Parse(comboBox3.Text); //选择数据位数
com.StopBits = (StopBits)int.Parse(comboBox4.Text); //选择停止位数
com.Parity = Parity.None; //选择是否奇偶校验 try
{
if (com.IsOpen) //判断该串口是否已打开
{
com.Close();
com.Open();
}
else
{
com.Open();
} }
catch (Exception ex)
{
MessageBox.ReferenceEquals("错误:" + ex.Message, "串口通信");
}
button1.Text = "关闭串口";
}
else if (button1.Text == "关闭串口")
{
com.Close(); //关闭串口 button1.Text = "打开串口";
}
}

7、运行结果

8、结语

关于串口数据的接收读取无非就两种方法:一是通过轮询方式实时读取串口,而是通过事件触发实现串口读取。尽管可以使用多线程处理,但是轮询方式读取串口的效率并不十分高效,因此,本人觉得还是采用事件触发方式比较好。或许有人问,为什么只写串口读取数据,不讲串口发送数据呢?嗯.......没错,串口的数据读取和数据发送是同样重要的,但是数据读取的处理比数据发送要复杂很多,我想,如果能把串口的数据读取搞明白了,那串口数据发送还成问题吗?

【ALB学习笔记】基于事件触发方式的串行通信接口数据接收案例的更多相关文章

  1. 【ALB学习笔记】基于多线程方式的串行通信接口数据接收案例

    基于多线程方式的串行通信接口数据接收案例 广东职业技术技术学院  欧浩源 1.案例背景 在本博客的<[CC2530入门教程-06]CC2530的ADC工作原理与应用>中实现了电压数据采集的 ...

  2. 【ALB技术笔记】基于多线程方式的串行通信接口数据接收案例

    基于多线程方式的串行通信接口数据接收案例 广东职业技术技术学院  欧浩源 1.案例背景 在本博客的<[CC2530入门教程-06]CC2530的ADC工作原理与应用>中实现了电压数据采集的 ...

  3. Linux学习笔记——基于鸟哥的Linux私房菜

    Linux学习笔记--基于鸟哥的Linux私房菜 ***** ARM与嵌入式linux的入门建议 (1) 学习基本的裸机编程:ARM7或ARM9,理解硬件架构和控制原理 (这一步是绝对的根基) (2) ...

  4. 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果

    学习笔记---Javascript事件Event.IE浏览器下的拖拽效果     1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...

  5. JavaSE学习笔记(4)---抽象类和接口

    JavaSE学习笔记(4)---抽象类和接口 抽象方法和抽象类 ·抽象方法 使用abstract修饰的方法,没有方法体,只有声明.定义的是一种"规范",就是告诉子类必须要给抽象方法 ...

  6. JavaWeb和WebGIS学习笔记(三)——GeoServer 发布shp数据地图

    系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...

  7. 【Spring学习笔记-MVC-3.1】SpringMVC返回Json数据-方式1-扩展

    <Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...

  8. EF学习笔记(八):更新关联数据

    学习笔记主目录链接:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考 ...

  9. 【EF6学习笔记】(八)更新关联数据

    上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考虑对于有关联的数据进行新增.删除.更新操作:比如Course .Instructor: ...

随机推荐

  1. css reset的重置作用(可取还是不可取,取决于你)

    一.重置的理由 当今流行的浏览器中,有些都是以自己的方式去理解css规范,这就会到只有的浏览器对css的解释与设计师的css定义初衷相冲突,使得网页的样子在某些浏览器下能正确按照设计师的想法显示.,但 ...

  2. 从零开始——PowerShell应用入门(全例子入门讲解)

    学习一门技术,不止要会,还要善用,例子就是带你快速入门的最佳利器.本文就是要用例子,不,大量的例子来带你走进PowerShell应用世界. 本文主要介绍一些PowerShell入门的基础知识,对技术小 ...

  3. maven 创建后报错

    <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId& ...

  4. js扩展父类方法

    在网上找了很多一直没找到关于JS扩展父类的方法,让我很是郁闷啊~要是真的开发组遇到了该咋整,于是乎自己手写了一些测试代码,没想到通过了……(难道是人品太好了?)废话不多说了直接上代码看看~ <s ...

  5. asp.net core 教程(六)-中间件

    Asp.Net Core-中间件 在这一章,我们将了解如何设置中间件.中间件技术在 ASP.NET Core中控制我们的应用程序如何响应 HTTP 请求.它还可以控制应用程序的异常错误,这是一个在如何 ...

  6. 锁和监视器之间的区别 – Java并发

    在面试中你可能遇到过这样的问题:锁(lock)和监视器(monitor)有什么区别? 嗯,要回答这个问题,你必须深入理解Java的多线程底层是如何工作的. 简短的答案是,锁为实现监视器提供必要的支持. ...

  7. CSS3 @keyframes 规则

    今天来给大家分享一下CSS3 @keyframes 规则! 在你了解CSS3 @keyframes 规则时我先来给大家说说什么是css3中的动画 动画是使元素从一种样式逐渐变化为另一种样式的效果. 您 ...

  8. Mac机上安装nvm遇到的坑--nvm command not found

    在Mac机上,我最开始是通过homebrew来安装nvm,如下: $ brew install nvm 安装完成后,在命令行输入nvm list,发现出现如下提示: What?!!我不是才安装了nvm ...

  9. 高考志愿填报:java 软件 程序员 目前的就业现状

    大约在17年前,也就是2000年,学计算机专业的学生可以有大部分都进入本专业,并且就业非常容易.哪怕只会office套件,想找个工作也很简单.那时候学计算机就是最热门的行业. 那时候,搞Java的还是 ...

  10. 如何用JavaScript复制到剪贴板

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...