前几天做毕业设计,其中要用到串口和下位机进行通信,于是自己捣鼓了一个简单的串口通信程序。
在做通信之前要先弄一个SerialPort组件出来,当然也可以通过程序来创建。本次设计中采用的是拖的winform中提供的组件,效果是一样的。不过要使程序正确的运行起来,电脑上要安装一个pl232的驱动,安装完成后,还必须要插入一根串口线才行,或者是USB转串口的线也可以。
SerialPort有很多的属性和方法,但是在我做的这个简单的串口通信中用到的属性和方法很少,可以讲VS调出来看看有哪些属性和方法,有很多的属性已经帮我们设置好了,利用默认的设置就行
1、设置COM口
串口通信是需要利用计算机的COM接口,而很多的接口是被其它程序使用的,故首先要获得计算机当前我们程序中能够使用的COM接口,首先要添加一个引用:Microsoft.VisualBasic
<span style="font-size:18px;"> private string LoadSerial ()
{
Microsoft.VisualBasic.Devices.Computer pc;
pc = new Microsoft.VisualBasic.Devices.Computer();
//判断能够使用的COM口数量
if (pc.Ports.SerialPortNames.Count > 0)
{
//当有COM口可以使用的时候,将第一个COM口赋值给属性PortName
//也可以直接:serial.PortName = "COM2"; 指明了要使用COM2接口
serial.PortName = pc.Ports.SerialPortNames[0];
serial.BaudRate = 115200; //设置通信的波特率,默认的是9600,所以也可以不用设置
serial.StopBits = System.IO.Ports.StopBits.One; //停止位的位数,一般的串口通信都有停止位
serial.DateBit = 8; //数据位数,每一帧有效数据的位数,默认的为8,这个根据需要设置
}
else
{
return "系统没有可用串口,请检查和下位机连线是否正常";
}
return "OK";
}</span>
我设置的属性也基本上都是这些,其他的什么读缓存大小写缓存大小以及什么读取超时和写超时等等都使用默认的就OK,主要还是COM端口的设置
2、发送数据
串口通信,对方是下位机,故在通信中采用的是ASCII码,所以要先将数据转换成二进制然后进行发送,由于系统会自动的添加什么启示结束位等,我们也就不需要关系,直接将要发送的数据丢给他就行,当然也可以手动的进行判断。发送数据前需要先打开串口。
<span style="font-size:18px;"> try
{
if (!serial.IsOpen) //判断串口是否打开,会返回一个布尔值
{
serial.Open(); //如果串口没有打开就打开串口
}
byte[] by = ASCIIEncoding.ASCII.GetBytes("b"); //将要发送的数据转换成二进制
serial.Write(by, 0, by.Length); //发送
}
catch (Exception ex)
{
return "请求结束出错:" + ex.Message;
}</span>
因为要打开串口,串口是硬件资源,打开的时候很可能会失败抛异常,故用一个try...catch...语句包起来。发送数据的方法还有一个WriteLine,但个人觉得用Wrte更好。其实严格的讲,在发送之前应该先判断是否能够进行发送,这可以通过属性来完成,在这里就没有判断了,直接发送。
3、创建一个接收数据的后台线程
本次用串口来进行通信主要是用来接收数据,就收数据中没有采用系统提供的事件机制,而是创建了一个后台的线程来进行不断的监视读取缓存中有没有数据。先创建后台线程:
<span style="font-size:18px;"> private string LoadThread()
{
try
{ Thread thread = new Thread(ReceiveDate); //传递的是接收数据的方法,这个方法中用来接收数据
thread.Name = "serialThread";
thread.IsBackground = true;//设置线程为后台线程,前台关闭,此线程也就关闭
thread.Start();
}
catch (Exception ex)
{
return "出错了!" + ex.Message;
}
return "OK";
}</span>
4、数据的接收和处理
设计中事先约定好的通信协议就是:总共七位数据,第一位是ABCDE五个字符中任意一个,第二位是数字,第三位是小数点,第4~6位是数字,最后一位是字符V。
由于ASCII中得到的空格和换行符是用"\0"和“\n”来表示的,利用string.trim()方法是不能够将这个给移除的,所以每次都只是读取一位数据,当然这样肯定会影响通信的效率。读取一位数据后先判断是不是空格和换行,是就将数据丢弃,一般空格和换行都是出现在上一组数据发送完成后才有的,没有考虑数据出错后变为"\0"和"\n"的问题,这也算是一个漏洞。七位数据接收完成后,通过正则表达式来进行验证,验证通过后将数据存入到事先准备好的字典中,字典的关键字是七位数据中的第一位子字符串,值是一个字符串集合,用来将小数点去掉后四位数字组成的字符串存储下来。
代码如下:
<span style="font-size:18px;"> //声明一个字典,存放数据
Dictionary<string, List<string>> receiveDate = null;
private void ReceiveDate ()
{
string date = ""; //保存接收的数据
//实例化这个字典
receiveDate = new Dictionary<string, List<string>>();
string datePath = "";//用来存放,当前是那一路的信号
int index = 0; //七位数据,用来标识接收的是第几位数据
DateTime time1=DateTime.Now;
while (true)
{
try
{
if (serial.IsOpen) //如果串口打开就进行数据的读取
{
if (serial.BytesToRead > 0) //先判断读缓存中有没有数据
{
byte[] byteDate = new byte[1]; //设置每一次读取的字节数为1
serial.Read(byteDate, 0, byteDate.Length);
string strDate = ASCIIEncoding.ASCII.GetString(byteDate);
if (strDate == "\0" || strDate == "\n")
{
index = 0;
date = "";
continue;
}
else
{
index++; //接收的是多少位数
date += strDate;
}
if (index == 7) //七位数据接收完成
{
//利用正则表达式来进行匹配和数据的提取
Regex reg = new Regex(@"^([ABCDE]{1})(\d{1})\.(\d{3})V$");
Match match = reg.Match(date, 0, date.Length);
if (match.Success)
{
datePath = match.Groups[1].Value;
string numStr = match.Groups[2].Value + match.Groups[3].Value;
int num = -1;
//将接收到的数据进行一个转换,转换成功后保存
if (int.TryParse(numStr, out num))
{
//经过正则表达式验证后,datePath一定是ABCDE中的一个数据,先判断是否包含这个关键字,如果不包含就添加
if (!receiveDate.ContainsKey(datePath))
{
receiveDate[datePath] = new List<int>();//添加关键字就需要声明一个集合赋值给它
}
receiveDate[datePath].Add(num);//将数据存储起来
time = DateTime.Now; //记录正确接收数据的时间
}
}
//清空,进入下一轮的数据接收
date = "";
datePath = "";
index = 0;
}
}
else
{
<span style="white-space: pre;"> </span>//这个else中做的事情是如果长时间接收不到数据就添加0,代码就不附加了
}
}
}
catch (Exception ex)
{ }
}
}</span>
到此,一个简单的串口通信程序就搞定了。
C#--简单的串口通信程序的更多相关文章
-
Qt编写串口通信程序全程图文解说
(说明:我们的编程环境是windows xp下,在Qt Creator中进行,假设在Linux下或直接用源代码编写,程序稍有不同,请自己修改.) 在Qt中并没有特定的串口控制类,如今大部分人使用的是第 ...
-
转:Qt编写串口通信程序全程图文讲解
转载:http://blog.csdn.net/yafeilinux/article/details/4717706 作者:yafeilinux (说明:我们的编程环境是windows xp下,在Q ...
-
Qt编写串口通信程序全程图文讲解 .
在Qt中并没有特定的串口控制类,现在大部分人使用的是第三方写的qextserialport类,我们这里也是使用的该类.我们可以去 http://sourceforge.net/projects/qex ...
-
【转】Qt编写串口通信程序全程图文讲解
本文章原创于www.yafeilinux.com 转载请注明出处. (说明:我们的编程环境是windows xp下,在Qt Creator中进行,如果在Linux下或直接用源码编写,程序稍有不同,请自 ...
-
C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序
C#中缓存的使用 缓存的概念及优缺点在这里就不多做介绍,主要介绍一下使用的方法. 1.在ASP.NET中页面缓存的使用方法简单,只需要在aspx页的顶部加上一句声明即可: <%@ Outp ...
-
创建C#串口通信程序详解
在.NET平台下创建C#串口通信程序,.NET 2.0提供了串口通信的功能,其命名空间是System.IO.Ports.这个新的框架不但可以访问计算机上的串口,还可以和串口设备进行通信.我们将使用标准 ...
-
C#串口通信程序详解
C#串口通信程序详解 摘要:创建C#串口通信程序需要注意什么呢?创建C#串口通信程序的步骤是什么?那么本文就向你详细介绍创建C#串口通信程序集体的内容. 在.NET平台下创建C#串口通信程序,.NET ...
-
C语言PIC16 serial bootloader和C#语言bootloader PC端串口通信程序
了解更多关于bootloader 的C语言实现,请加我QQ: 1273623966 (验证信息请填 bootloader),欢迎咨询或定制bootloader(在线升级程序). 新PIC16 Boot ...
-
C#实现简单的串口通信
前言 本着学习研究的态度,用c#语言实现简单的串口通信工具. 一.串口通信原理 串口通信 串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节.尽管比 ...
随机推荐
-
关于项目中值对象Identifier的设计-领域驱动
到现在为止做了不项目,发现每个实体都会有个相应的值对象. 先简单说一下值对象和实体之间的区别: (以下内容来着<领域驱动设计>一书) 当一个小孩画画的时候,他注意的是画笔的颜色和笔尖的粗细 ...
-
(转)解决:本地计算机 上的 OracleOraDb10g_home1TNSListener服务启动后停止
原文地址:http://justsee.iteye.com/blog/1320059 手动启动一个问题:本地计算机 上的 OracleOraDb10g_home1TNSListener服务启动后停止. ...
-
ToolBar Style
colorPrimaryDark 状态栏背景色. 在 style 的属性中设置. textColorPrimary App bar 上的标题与更多菜单中的文字颜色. 在 style 的属性中设置. A ...
-
【MySQL for Mac】在Mac终端导入&;导出.sql文件
导入 打开终端输入:(前提是已经配置过MySQL环境变量) mysql -u root -p create database name; use name; source 『将.sql文件直接拖拽至终 ...
-
Visual Assist X 快捷键
Shift+Alt+F Find References 查找引用 Shift+Alt+S FindSynbolDialog 打开查找符号对话框 Alt+G GotoImplementation 在定义 ...
-
学习【Web前端开发修炼之道】总结
网页布局 1.申明文档模式 2.设置css标签重置,避免各浏览器解析不同. 3.网页css模块划分,base.css,common.css,page.css 4.低权重原则---避免滥用子选择器 cs ...
-
Ext.grid.CheckboxSelectionModel复选框设置某行不可以选中
var sm = new Ext.grid.CheckboxSelectionModel({ renderer:function(v,c,r){ if(r.get("isEdit" ...
-
java向前引用
根据看书和看得文章,引出了一个关于"向前引用"的问题: public class InstanceInitTest { static { // { a = 6; System.ou ...
-
Java并发编程的4个同步辅助类
Java并发编程的4个同步辅助类(CountDownLatch.CyclicBarrier.Semphore.Phaser) @https://www.cnblogs.com/lizhangyong/ ...
-
Angular4.0中常用指令
Angular 4.0 1. 指令:*ngFor 循环带索引的两种方法: <tr *ngFor="let item of listWorkingDetails index as i&q ...