SerialPort类的用法与示例

文章目录

  • SerialPort类的用法与示例
    • 1. 串口硬件信号定义
    • 2. 串口端口号搜索
    • 3. 串口属性参数设置
    • 4. 串口发送信息
    • 5. 串口接收信息
    • 串口工具类
    • 串口使用注意事项

从Microsoft .Net 2.0版本以后,就默认提供了 System.IO.Ports.SerialPort类,用户可以非常简单地编写少量代码就完成串口的信息收发程序。本文将介绍如何在PC端用C# .Net 来开发串口应用程序。

1. 串口硬件信号定义

DB9 Connector 信号定义

针脚 信号 定义 作用
1 DCD 载波检测 Received Line Signal Detector(Data Carrier Detect)
2 RXD 接收数据 Received Data
3 TXD 发送数据 Transmit Data
4 DTR 数据终端准备好 Data Terminal Ready
5 SGND 信号地 Signal Ground
6 DSR 数据准备好 Data Set Ready
7 RTS 请求发送 Request To Send
8 CTS 清除发送 Clear To Send
9 RI 振铃提示 Ring Indicator

2. 串口端口号搜索

一个最简单的办法:

string[] portList = System.IO.Ports.SerialPort.GetPortNames();  // 静态方法

还有一种通过调用API的方法来获取实现,可以获取详细的完整串口名称,对于USB-to-COM虚拟串口来说特别适用。它可以获取到与设备管理器中一样的名字,例如“Prolific USB-to-Serial Comm Port(COM34)”, 而上面的方法只能获取到“COM34”。

3. 串口属性参数设置

SerialPort类所包含的属性详见下表:

名称 说明
BaseStream 获取 Stream 对象的基础 SerialPort 对象。
BaudRate 获取或设置串行波特率。
BreakState 获取或设置中断信号状态。
BytesToRead 获取接收缓冲区中数据的字节数。
BytesToWrite 获取发送缓冲区中数据的字节数。
CanRaiseEvents 获取一个值,该值指示组件是否可以引发一个事件。(继承自 Component。)
CDHolding 获取端口的载波检测行的状态。
Container 获取 IContainer ,其中包含 Component。(继承自 Component。)
CtsHolding 获取“可以发送”行的状态。
DataBits 获取或设置每个字节的标准数据位长度。
DesignMode 获取一个值,该值指示是否 Component 当前处于设计模式。(继承自 Component。)
DiscardNull 获取或设置一个值,该值指示 null 字节在端口和接收缓冲区之间传输时是否被忽略。
DsrHolding 获取数据设置就绪 (DSR) 信号的状态。
DtrEnable 获取或设置一个值,该值在串行通信过程中启用数据终端就绪 (DTR) 信号。
Encoding 获取或设置传输前后文本转换的字节编码。
Events 获取的事件处理程序附加到此列表 Component。(继承自 Component。)
Handshake 使用 Handshake 中的值获取或设置串行端口数据传输的握手协议。
IsOpen 获取一个值,该值指示 SerialPort 对象的打开或关闭状态。
NewLine 获取或设置用于解释 ReadLine 和 WriteLine 方法调用结束的值。
Parity 获取或设置奇偶校验检查协议。
ParityReplace 获取或设置一个字节,该字节在发生奇偶校验错误时替换数据流中的无效字节。
PortName 获取或设置通信端口,包括但不限于所有可用的 COM 端口。
ReadBufferSize 获取或设置 SerialPort 输入缓冲区的大小。
ReadTimeout 获取或设置读取操作未完成时发生超时之前的毫秒数。
ReceivedBytesThreshold 获取或设置 DataReceived 事件发生前内部输入缓冲区中的字节数。
RtsEnable 获取或设置一个值,该值指示在串行通信中是否启用请求发送 (RTS) 信号。
Site 获取或设置 ISite 的 Component。(继承自 Component。)
StopBits 获取或设置每个字节的标准停止位数。
WriteBufferSize 获取或设置串行端口输出缓冲区的大小。
WriteTimeout 获取或设置写入操作未完成时发生超时之前的毫秒数。

简单初始化串口参数的示例程序:

SerialPort mySerialPort = new SerialPort("COM2"); // 构造参数指定串口名
//serialPort.PortName = "COM2";
mySerialPort.BaudRate = 9600;
mySerialPort.Parity=Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;mySerialPort.Open();  // 打开串口// DataReceived是串口类的一个事件,通过+=运算符订阅事件,如果串口接收到数据就触发事件,调用DataReceive_Method事件处理方法
mySerialPort.DataReceived += new SerialDataReceivedEvenHandler(DataReceive_Method);// 事件处理方法
public static void DataReceive_Method(object sender, SerialDataReceivedEventArgs e)
{//sender是事件触发对象,通过它可以获取到mySerialPortSerialPort mySerialPort = (SerialPort)sender;
}mySerialPort.Close();  // 关闭串口

4. 串口发送信息

SerialPort类定义了多种方法用于串口发送信息。

Write(Byte[], Int32, Int32)使用缓冲区中的数据将指定数量的字节写入串行端口

注意一字节(Byte)是8个比特(bit),而一个十六进制数是4个比特,两个十六进制数就是8个比特,即一个字节。所以要想发送十六进制数就得用写入字节的函数。

byte[] t = new byte[2];
t[0] = 0xAA;
t[1] = 0xBB;
串口对象.Write(t,0,2);

==Write(Char[], Int32, Int32)==使用缓冲区中的数据将指定数量的字符写入串行端口
==Write(String)==将指定的字符串写入串行端口
==WriteLine(String)==将指定的字符串和NewLine值写入输出缓冲区

下面是一个简单的例子说明如何通过串口发送字符串和字节数据:

private static void SendSampleData()
{SerialPort port = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);port.Open();port.Write("Hello World");port.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3);port.Close();
}

下面是如何发送一个文本文件的例子:

private static void SendTextFile(SerialPort port, string FileName)
{port.Write(File.OpenText(FileName).ReadToEnd());
}

下面是如何发送一个二进制文件的例子:

private static void SendBinaryFile(SerialPort port, string FileName)
{using (FileStream fs = File.OpenRead(FileName))port.Write((new BinaryReader(fs)).ReadBytes((int)fs.Length), 0, (int)fs.Length);
}

5. 串口接收信息

SerialPort类定义了多种方法用于串口接收信息。

Read(Byte[], Int32, Int32) 从SerialPort输入缓冲区读取一些字节,并将那些字节写入字节数组中指定的偏移量处
Read(Byte[], Int32, Int32)从SerialPort输入缓冲区读取一些字符,并将那些字符写入字符数组中指定的偏移量处
ReadByte() 从SerialPort输入缓冲区中同步读取一个字节
ReadChar() 从SerialPort输入缓冲区中同步读取一个字符
ReadExisting() 在编码的基础上,读取SerialPort对象的流和输入缓冲区中所有立即可用的字节
ReadLine()一直读取到输入缓冲区中的NewLine值
ReadTo(String)一直读取到输入缓冲区中的指定value的字符串

通常一个比较常见的用法就是将串口里面立即能用的字符或数据读取然后打印在textbox等控件中显示。

private SerialPort port = new SerialPort("COM1",9600, Parity.None, 8, StopBits.One);port.DataReceived += newSerialDataReceivedEventHandler(port_DataReceived);port.Open();private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{Console.WriteLine(port.ReadExisting());
}

另外还有一种应用场合是需要缓存一段串口接收数据,然后在缓存数据中查找有用信息,这时可以采用下面例子所用的办法。

SerialPort com = new SerialPort(SerialPort.GetPortNames()[0],9600, Parity.None, 8, StopBits.One);List<byte> bBuffer = new List<byte>();
string sBuffer = String.Empty;com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);com.Open();void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{while (com.BytesToRead > 0)bBuffer.Add((byte)com.ReadByte());ProcessBuffer(bBuffer);sBuffer += com.ReadExisting();ProcessBuffer(sBuffer);
}private void ProcessBuffer(string sBuffer)
{}private void ProcessBuffer(List<byte> bBuffer)
{}

串口工具类

public class SerialPortUtils
{public static SerialPort serialPort = null;   // 定义一个静态的串口对象/// <summary>/// 搜索串口/// </summary>/// <returns></returns>public static string[] GetPortNames() {return SerialPort.GetPortNames();}/// <summary>/// 打开或者关闭串口/// </summary>/// <param name="comName"></param>/// <param name="baud"></param>/// <returns></returns>public static SerialPort OpenClosePort(string comName, int baud){//串口未打开if (serialPort == null || !serialPort.IsOpen){serialPort = new SerialPort();//串口名称serialPort.PortName = comName;//波特率serialPort.BaudRate = baud;//数据位serialPort.DataBits = 8;//停止位serialPort.StopBits = StopBits.One;//校验位serialPort.Parity = Parity.None;//打开串口serialPort.Open();//串口数据接收事件实现serialPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);return serialPort;}//串口已经打开else{serialPort.Close();return serialPort;}}/// <summary>/// 接收数据/// </summary>/// <param name="sender"></param>/// <param name="e"></param>public static void ReceiveData(object sender, SerialDataReceivedEventArgs e){SerialPort _SerialPort = (SerialPort)sender;int _bytesToRead = _SerialPort.BytesToRead;byte[] recvData = new byte[_bytesToRead];_SerialPort.Read(recvData, 0, _bytesToRead);//向控制台打印数据Debug.WriteLine("收到数据:" + recvData);}/// <summary>/// 发送数据/// </summary>/// <param name="data"></param>/// <returns></returns>public static bool SendData(byte[] data){if (serialPort != null && serialPort.IsOpen){serialPort.Write(data, 0, data.Length);Debug.WriteLine("发送数据:" + data);return true;}else{return false;}}
}

串口使用注意事项

参考:https://blog.csdn.net/wuyazhe/article/details/5606276

Open()打开串口的时候会创建一个监听线程ListenThread,DataReceived事件就是在这个线程进行处理的,与此同时还有一个主线程即UIThread,这个时候要注意线程同步问题。

在DataReceived事件处理函数中,一般是调用Read()方法读取串口缓存区数据,读取完后进行容错处理,之后解析数据,解析完成后更新UI。在监听线程中是无法更新主线程的UI的,所以必须调用Invoke方法回到主线程更新UI。但是由于Invoke是同步函数,在UI未完成更新之前,监听线程一直停在DataReceived事件处理函数中。此时主线程如果调用Close()函数关闭串口,由于监听线程的资源还没来得及释放,造成死锁。

解决方法就是用BeginInvoke异步调用去更新UI

SerialPort类的用法与示例相关推荐

  1. php分析图片水印,PHP开发的文字水印,缩略图,图片水印实现类与用法示例

    本文实例讲述了PHP开发的文字水印,缩略图,图片水印实现类与用法.分享给大家供大家参考,具体如下: 1.实现类ImageToTest.class.php参考代码 class ImageToTest { ...

  2. jsonutil java_Java实现的JSONUtil工具类与用法示例

    本文实例讲述了Java实现的JSONUtil工具类与用法.分享给大家供大家参考,具体如下: import java.util.HashMap; import java.util.Map; import ...

  3. php dimage加上域名,PHP全功能无变形图片裁剪操作类与用法示例

    本文实例讲述了PHP全功能无变形图片裁剪操作类与用法.分享给大家供大家参考,具体如下: 如果需要图片裁剪,或生成缩略图,这个基本上没有问题,全部需要的功能都在里面,全部都是无变形的. 这里我们划分为四 ...

  4. sqlite mysql php_PHP实现的简单操作SQLite数据库类与用法示例

    本文实例讲述了PHP实现的简单操作SQLite数据库类与用法.分享给大家供大家参考,具体如下: SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已 ...

  5. php7 匿名继承类_PHP7匿名类的用法示例

    本文实例讲述了PHP7匿名类的用法.分享给大家供大家参考,具体如下: /** * Created by PhpStorm. * User: Itboot * Date: 2019/1/17 * Tim ...

  6. php 类遍历,php数组遍历类与用法示例

    本文实例讲述了php数组遍历类与用法.分享给大家供大家参考,具体如下: class scanArray{ public $arr; public $where; private $str; publi ...

  7. arc lint java,JavaFX 类 Arc用法及代码示例

    Arc类是JavaxFX的一部分.圆弧类在指定的某些给定值上创建圆弧,例如圆弧的中心,起始角度,圆弧的长度(长度)和半径.弧形类扩展了形状类. 该类的构造函数是 Arc():创建弧类的空实例 Arc( ...

  8. php 字符串函数 教程_php字符串函数 str类常见用法示例

    本文实例讲述了php字符串函数 str类常见用法.分享给大家供大家参考,具体如下: str_split(string, leg);//将一个字符 串转换为数组,参数1:要被转换的字符串,参数2:每 段 ...

  9. Dorado用法与示例

    Dorado用法与示例 dorado用后总结 一.dorado概念 dorado的产品全名是"dorado展现中间件".从产品形态上dorado由两部分组成,第一部分是一个具有AJ ...

最新文章

  1. Windows Service
  2. SQL Server 2005实现负载均衡的详细介绍
  3. mysql数据太大,如何导入_MySQL导入文件过大怎么办
  4. vue tag=“li“ 和event原有样式渲染不出来
  5. 六一儿童节,看我用ModelArts让8090梦回童年
  6. 部署 Job (第三部分)
  7. Kubernetes(K8s) 1.14.3常用操作命令
  8. OpenCore安装教程
  9. 知识点九:散列表(中)
  10. centos离线安装谷歌浏览器flash-player
  11. 解决Win10系统下运行unity游戏闪退报错问题 包含 人类一败涂地 波西亚时光等
  12. 谁是赢家,某电视台的娱乐节目有个表演评审环节,每次安排两位艺人表演,他们的胜负由观众投票和 3 名评委投票两部分共同决定。规则为:如果一艺人的观众票数高,且得到至少 1 名评委的认可,该艺人就胜出;
  13. 【复现】CNVD-2020-10487-Tomcat-Ajp-lfi
  14. 升级bigsur_2年内彻底摆脱英特尔,苹果重磅发布自研Mac芯片,并对“五大系统”再升级...
  15. htcm7刷linux,HTC One M7 怎么刷机?刷机图文教程 ?
  16. Android手写签名 附带背景图设置
  17. 分布式架构的几种实现方式
  18. Go基础:for循环
  19. android 账号同步功能吗,android账号管理与同步机制
  20. CFS调度器负载计算

热门文章

  1. 个人整理 HTML全部标签总集,及用法
  2. 黑客讲述 | 我如何逼小偷把 iPhone 还回来
  3. mysql-事务隔离级别以及锁详解
  4. 科学计算机中logo,简单做了个Logo~
  5. ARChon 分析之四:ARC的下载与编译
  6. 深度置信网络matlab_深度学习在机器视觉领域的应用持续增长
  7. 利用模板化应对ERP业务模型的快速变化
  8. 使用AIGC工具提升论文阅读效率
  9. PHP-MySQL停车场车位管理系统(附源码
  10. Linux c 停车场管理系统