【ALB学习笔记】基于多线程方式的串行通信接口数据接收案例
基于多线程方式的串行通信接口数据接收案例
广东职业技术技术学院 欧浩源
1、案例背景
在本博客的《【CC2530入门教程-06】CC2530的ADC工作原理与应用》中实现了电压数据采集的程序设计,传感器模块以每1秒发送一帧数据的形式通过串口向上位机发送电压数据。其数据帧由4个字节组成:一个帧头和一个帧尾,中间两个字节为电压数据,其格式如下:
帧头(0xAF) 电压数据高8位 电压数据低8位 帧尾(0xFA)
在篇博文中,将讲述如何通过多线程的方式,从串口接收传感器发送过来的数据帧,并将数据帧和换算后的实际电压值显示出来。
2、界面设计

3、引入命令空间
使用多线程的方式,需要引入命名空间:System.Threading;
使用串行通信接口,需要引入命名空间:System.IO.Ports;
4、初始化工作
首先,定义一个串行接口的对象和一个线程的字段,
然后,给主窗体添加窗体装载事件(即Load事件),在该事件中对各个控件的属性进行初始化工作。
SerialPort com = new SerialPort(); //实例化一个串口对象
Thread t; //定义一个线程字段
private void Form1_Load(object sender, EventArgs e)
{
textBox1.ReadOnly = true; //文本框只读
textBox1.ScrollBars = ScrollBars.Vertical; //文本框支持垂直滚动条
comboBox1.Items.Add("COM1");
comboBox1.Items.Add("COM2");
comboBox1.Items.Add("COM3");
comboBox1.Items.Add("COM4");
comboBox1.Items.Add("COM5");
comboBox1.SelectedIndex = ; comboBox2.Items.Add("");
comboBox2.Items.Add("");
comboBox2.Items.Add("");
comboBox2.Items.Add("");
comboBox2.Items.Add("");
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 = ;
}
5、设置串行接口
在进行串口通信的时候,一般的流程是:先设置通信的端口号、波特率、数据位、停止位和校验位,然后打开串口,接着发送数据和接收数据,最后要关闭串口。
在本案例中,对串口的各个参数配置完成后,打开串口,然后启动串口数据接收的线程,开始以轮询的方式接收数据。
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();
}
t = new Thread(com_DataReceived); //创建并启用数据接收线程
t.Start();
}
catch(Exception ex)
{
MessageBox.ReferenceEquals("错误:" + ex.Message, "串口通信");
}
button1.Text = "关闭串口";
}
else if (button1.Text == "关闭串口")
{
com.Close(); //关闭串口
t.Abort(); //终止线程
button1.Text = "打开串口";
}
}
6、串口数据接收线程方法
在该方法中,只有在串口打开并连接成功的情况下在去读取串口缓冲区中的数据。
首先通过读取BytesToRead属性,获取串口接收缓冲区中的数据字节数,然后根据这个属性实例化一个byte类型的数据,在通过Read方法将数据从缓冲区中读取到数组中。
将数据帧以十六进制的形式显示到窗体的文本框中。
通过计算获得实际的电压值,显示到对应的Lable标签中。
private void com_DataReceived()
{
while (com.IsOpen) //在串口已打开情况下读取数据
{
string strRcv = "";
int count = com.BytesToRead; //获取串口缓冲器的字节数
byte[] readBuffer = new byte[count]; //实例化接收串口数据的数组
if (count != ) //如果串口接收到数据
{
strRcv = count.ToString() + " ";
com.Read(readBuffer, , count); //从串口缓冲区读出数据到数组
for (int i = ; i < readBuffer.Length; i++)
{
strRcv += readBuffer[i].ToString("X2") + " "; //16进制显示
}
textBox1.Text += strRcv + "\r\n"; if (readBuffer[] == 0xAF && readBuffer[] == 0xFA) //判断数据的帧头和帧尾
{
Int32 ad = readBuffer[];
double advalue;
ad <<= ;
ad |= readBuffer[]; //从数据帧中将电压数据取出
advalue = ad;
advalue = (advalue * 3.3) / ; //将数据换算为实际的电压值
label6.Text = advalue.ToString("F2") + " V";
}
}
Thread.Sleep();
}
7、程序运行结果

8、结语
串行接口通信是物联网技术应用中常用的数据交互方式。
利用多线程的手段以轮询的方式读取串口缓冲区的数据是一种最基础的方法,然而并不是唯一的方法。采用DadaReceived事件触发的方法来接收数据也很常用,当程序设计程度稍微复杂一点,后面再慢慢讲述。
【ALB学习笔记】基于多线程方式的串行通信接口数据接收案例的更多相关文章
- 【ALB技术笔记】基于多线程方式的串行通信接口数据接收案例
基于多线程方式的串行通信接口数据接收案例 广东职业技术技术学院 欧浩源 1.案例背景 在本博客的<[CC2530入门教程-06]CC2530的ADC工作原理与应用>中实现了电压数据采集的 ...
- 【ALB学习笔记】基于事件触发方式的串行通信接口数据接收案例
基于事件触发方式的串行通信接口数据接收案例 广东职业技术学院 欧浩源 一.案例背景 之前写过一篇<基于多线程方式的串行通信接口数据接收案例>的博文,讨论了采用轮询方式接收串口数据的情况. ...
- Mybatis进阶学习笔记——动态代理方式开发Dao接口、Dao层(推荐第二种)
1.原始方法开发Dao Dao接口 package cn.sm1234.dao; import java.util.List; import cn.sm1234.domain.Customer; pu ...
- 孙鑫VC学习笔记:多线程编程
孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010 HQU Email:zgzhaobo@gmail.com QQ:452728574 Latest Modified ...
- 【Spring学习笔记-MVC-3.1】SpringMVC返回Json数据-方式1-扩展
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- Linux学习笔记——基于鸟哥的Linux私房菜
Linux学习笔记--基于鸟哥的Linux私房菜 ***** ARM与嵌入式linux的入门建议 (1) 学习基本的裸机编程:ARM7或ARM9,理解硬件架构和控制原理 (这一步是绝对的根基) (2) ...
- JavaWeb和WebGIS学习笔记(三)——GeoServer 发布shp数据地图
系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...
- EF学习笔记(八):更新关联数据
学习笔记主目录链接:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考 ...
- 【EF6学习笔记】(八)更新关联数据
上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考虑对于有关联的数据进行新增.删除.更新操作:比如Course .Instructor: ...
随机推荐
- phpshell提权
实际操作中可以在webshell用udf.dll提权,用函数的上传文件功能上传文件到启动目录,再用shut函数重起系统.(目前没成功过,有 机会本地测试一下,先记录在这了).如果是英文版的系统,启动目 ...
- Python的压缩文件处理 zipfile & tarfile
本文从以下两个方面, 阐述Python的压缩文件处理方式: 一. zipfile 二. tarfile 一. zipfile 虽然叫zipfile,但是除了zip之外,rar,war,jar这些压缩( ...
- laravel5.6 后台无法退出,必须清楚浏览器缓存才能退出
方法一: 在后台,admin/logincontroleer.php 中 可行 public function logout(Request $request) { Auth::logout(); ...
- BZOJ 1854 游戏(二分图匹配或并查集)
此题的二分图匹配做法很容易想,就是把属性当做s集,武器当做t集,如果该武器拥有该武器则连一条边. 那么答案就是求该二分图的最大前i个匹配.将匈牙利算法改一改,当前找不到增广路就break. 但是过这个 ...
- Codeforces Round #510 Div. 2 Virtual Participate记
这场打的顺手到不敢相信.如果不是vp的话估计肯定打不到这个成绩. A:最大显然,最小的话每次暴力给最小的+1. #include<iostream> #include<cstdio& ...
- UVA.839 Not so Mobile ( 二叉树 DFS)
UVA.839 Not so Mobile ( 二叉树 DFS) 题意分析 给出一份天平,判断天平是否平衡. 一开始使用的是保存每个节点,节点存储着两边的质量和距离,但是一直是Runtime erro ...
- LOJ 模拟赛
1.LOJ 507 接竹竿 link dp[i]表示前i个的最大分数,所以dp[i]=max(dp[i-1],dp[j-1]+sum[i]-sum[j-1]) (color i ==color j ...
- GoLand安装配置
目录 下载 安装 破解 运行 参考网址 GoLand配置 下载 1 下载路径:https://pan.baidu.com/s/1JJ-Oxx9NkEK-PrwcvLys7Q,提取码:o0e5 2 下载 ...
- anroid 6.0.1_r77源码编译
一.源码下载(基本类似4.4.4_r1) 二.必须使用openjdk1.7 sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-get update ...
- 剑桥offer(11~20)
11.题目描述 输入一个整数,输出该数二进制表示中1的个数.其中负数用补码表示. class Solution { public: int NumberOf1(int n) { ; unsigned ...