C#实现串口通信解析

article/2025/10/6 19:05:55

1. 串口硬件信号定义

串口通信(Serial Communications)是指外设和计算机间通过数据信号线、地线等按位(bit)进行传输数据的一种通信方式,属于串行通信方式,能够实现远距离通信,长度可达1200米。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。

串口通信的接口标准有很多,有 RS-232C、RS-232、RS-422A、RS-485 等。常用的就是 RS-232 和 RS-485。串口通信使用的大多都是 DB9 接口,如下图。
在这里插入图片描述

1 载波检测(DCD)
2 接受数据(RXD)
3 发出数据(TXD)
4 数据终端准备好(DTR)
5 信号地线(SG)
6 数据准备好(DSR)
7 请求发送(RTS)
8 清除发送(CTS)
9 振铃指示(RI)
在这里插入图片描述
DB9 Connector 信号定义。串口测试将2、3针脚短接即可。在这里插入图片描述

这里我们以 RS-232 接口进行演示。

1、数据包格式定为(10bytes):

帧头(0xAA,0x55),命令字(1byte),地址位(2bytes),数据位(2bytes),校验位(1byte,和校验),帧尾(0xFE,0xFE)

地址位和数据位都是高位在前。

2、串口端口号搜索

string[] portList = System.IO.Ports.SerialPort.GetPortNames();
for (int i = 0; i < portList.Length; i++)
{string name = portList[i];comboBox.Items.Add(name);
}

还有一种通过调用API的方法来获取实现,可以获取详细的完整串口名称,对于USB-to-COM虚拟串口来说特别适用。

3、串口属性参数设置

SerialPort mySerialPort = new SerialPort("COM2");//端口
mySerialPort.BaudRate = 9600;//波特率
mySerialPort.Parity = Parity.None;//校验位
mySerialPort.StopBits = StopBits.One;//停止位
mySerialPort.DataBits = 8;//数据位
mySerialPort.Handshake = Handshake.Non;
mySerialPort.ReadTimeout = 1500;
mySerialPort.DtrEnable = true;//启用数据终端就绪信息
mySerialPort.Encoding = Encoding.UTF8;
mySerialPort.ReceivedBytesThreshold = 1;//DataReceived触发前内部输入缓冲器的字节数
mySerialPort.DataReceived += new SerialDataReceivedEvenHandler(DataReceive_Method);mySerialPort.Open();

4、串口发送信息

  • Write(Byte[], Int32, Int32) :将指定数量的字节写入串行端口
  • Write(Char[], Int32, Int32) :将指定数量的字符写入串行端口
  • Write(String) :将指定的字符串写入串行端口
  • WriteLine(String) :将指定的字符串和NewLine值写入输出缓冲区
// Write a string
port.Write("Hello World");// Write a set of bytes
port.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3);// Close the port
port.Close();

5. 串口接收信息

  • Read(Byte[], Int32, Int32):从SerialPort输入缓冲区读取一些字节,并将那些字节写入字节数组中指定的偏移量处
  • ReadByte():从SerialPort输入缓冲区中同步读取一个字节
  • ReadChar(): 从SerialPort输入缓冲区中同步读取一个字符
  • ReadExisting() :在编码的基础上,读取SerialPort对象的流和输入缓冲区中所有立即可用的字节
  • ReadLine() :一直读取到输入缓冲区中的NewLine值
  • ReadTo(String) :一直读取到输入缓冲区中的指定value的字符串
string serialReadString;
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{serialReadString = port.ReadExisting());this.txt1.Invoke( new MethodInvoker(delegate { this.txt1.AppendText(serialReadString); }));
}

6、循环接收数据

void com_DataReceived(object sender, SerialDataReceivedEventArgs e)
{// Use either the binary OR the string technique (but not both)// Buffer and process binary datawhile (com.BytesToRead > 0)bBuffer.Add((byte)com.ReadByte());ProcessBuffer(bBuffer);// Buffer string datasBuffer += com.ReadExisting();ProcessBuffer(sBuffer);
}private void ProcessBuffer(string sBuffer)
{// Look in the string for useful information// then remove the useful data from the buffer
}private void ProcessBuffer(List<byte> bBuffer)
{// Look in the byte array for useful information// then remove the useful data from the buffer
}

7、 C# 串口接收数据不完整解决办法

/针对数据协议:head + len + playload + check 类型private List<byte> buffer = new List<byte>(4096);private void sp_DataReceived(objectsender, EventArgs e) //sp是串口控件
{int n = sp.BytesToRead;byte[] buf = new byte[n];sp.Read(buf, 0, n);//1.缓存数据buffer.AddRange(buf);//2.完整性判断while (buffer.Count >= 4) //至少包含帧头(2字节)、长度(1字节)、校验位(1字节);根据设计不同而不同{//2.1 查找数据头if (buffer[0] == 0x01) //传输数据有帧头,用于判断{int len = buffer[2];if (buffer.Count < len + 4) //数据区尚未接收完整{break;}//得到完整的数据,复制到ReceiveBytes中进行校验byte[] ReceiveBytes = new byte[len + 4];buffer.CopyTo(0, ReceiveBytes, 0, len + 4);byte jiaoyan; //开始校验---自定义实现jiaoyan = this.JY(ReceiveBytes);//if (jiaoyan != ReceiveBytes[len+3]) //校验失败,最后一个字节是校验位{buffer.RemoveRange(0, len + 4);MessageBox.Show("数据包不正确!");continue;}buffer.RemoveRange(0, len + 4);///执行对数据进行处理操作RunReceiveDataCallback(ReceiveBytes);}else //帧头不正确时,记得清除{buffer.RemoveAt(0);}}
}
//针对协议类型: head + len +cmd + seq+ playload +check + tail; private List<byte> buffer = new List<byte>(4096);
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e){ try{try{int nCount = serialPort1.BytesToRead;if (nCount == 0){return;}byte[] btAryBuffer = new byte[nCount];serialPort1.Read(btAryBuffer, 0, nCount);//缓存数据buffer.AddRange(btAryBuffer);int index = 1;while (buffer.Count>0x07)  //最短协议长度{if (buffer[0] == 0x01)   //协议头{if (buffer[index] != 0x03)  //查询协议尾{index++;if (index > buffer.Count)    //没有接受到帧尾 0x03{break;              //退出继续接收}}else  // 接收到协议尾 得到完整一帧数据{byte[] ReceiveBytes = new byte[index+1];buffer.CopyTo(0, ReceiveBytes, 0, index+1);RunReceiveDataCallback(ReceiveBytes);buffer.RemoveRange(0, index);}}else{buffer.RemoveAt(0);}}            }catch (System.Exception ex){}}catch(Exception ex){MessageBox.Show(ex.Message);}finally{handerListening = false;}}

8、封装

1、数据封装方法:

//数据打包
private byte[] DataPackage(byte cmd, int addr, int data){byte[] package = new byte[10];package[0] = 0xAA;//帧头package[1] = 0x55;package[2] = cmd;//命令字    byte[] dataaddr = IntToByteArray(addr);package[3] = dataaddr[0];//地址高字节package[4] = dataaddr[1];//地址低字节byte[] value = IntToByteArray(data);package[5] = value[0];//数据高字节package[6] = value[1];//数据低字节package[7] = CheckSum(package);//校验位package[8] = 0xFE;//帧尾package[9] = 0xFE;return package;}//将int转换成2位数组private static byte[] IntToByteArray(int value){int hvalue = (value >> 8) & 0xFF;int lValue = value & 0xFF;byte[] arr = new byte[] { (byte)hvalue, (byte)lValue };return arr;}//得到和校验码private byte CheckSum(byte[] package){byte checksum = 0;for (int i = 0; i < package.Length; i++){checksum += package[i];}return checksum;}

2、串口调用封装类CommHelper.cs

internal class CommHelper{//委托public delegate void EventHandle(byte[] readBuffer);public event EventHandle DataReceived;public SerialPort serialPort;private Thread thread;volatile bool _keepReading;public CommHelper(){serialPort = new SerialPort();thread = null;_keepReading = false;serialPort.ReadTimeout = -1;serialPort.WriteTimeout = 1000;}//获取串口打开状态public bool IsOpen{get{return serialPort.IsOpen;}}//开始读取private void StartReading(){if (!_keepReading){_keepReading = true;thread = new Thread(new ThreadStart(ReadPort));thread.Start();}}//停止读取private void StopReading(){if (_keepReading){_keepReading = false;thread.Join();thread = null;}}//读数据private void ReadPort(){while (_keepReading){if (serialPort.IsOpen){int count = serialPort.BytesToRead;if (count > 0){byte[] readBuffer = new byte[count];try{Application.DoEvents();serialPort.Read(readBuffer, 0, count);DataReceived?.Invoke(readBuffer);Thread.Sleep(100);}catch (TimeoutException){}}}}}//写数据public void WritePort(byte[] send, int offSet, int count){if (IsOpen){serialPort.Write(send, offSet, count);}}//打开public void Open(){Close();try{serialPort.Open();serialPort.RtsEnable = true;if (serialPort.IsOpen){StartReading();}else{MessageBox.Show("串口打开失败!");}}catch{}}//关闭public void Close(){StopReading();serialPort.Close();            }}

http://chatgpt.dhexx.cn/article/Xe6opNil.shtml

相关文章

10、STM32的串口(UART)及串口通信原理(内附代码)

一、通信接口介绍 1、处理器与外部设备通信的两种方式&#xff1a; 并行通信 - 传输原理&#xff1a;数据各个位同时传输。 -优点&#xff1a;速度快 -缺点&#xff1a;占用引脚资源多 串行通信 - 传输原理&#xff1a;数据按位顺序传输&#xff0…

串口通信的概念与实现

uart串口通信概念数据结构termios作用与设置串口读写实现 UART串口通信概念 通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;通常称作uart&#xff0c;是一种异步收发传输器&#xff0c;uart作为异步串口通信协议的一种&#xff0c;…

java基于RXTXcomm的串口程序

准备工作 首先下载官方提供的jar包和.dll文件&#xff0c;dll文件有两个&#xff0c;一个是rxtxSerial&#xff0c;一个是rxtxParallel&#xff0c;分别表示串口和并口。因为我开发串口&#xff0c;所以把rxtxSerial.dll放到了jdk1.8.0_171/jre/bin和jre1.8.0_171/bin目录下&a…

51单片机串口多机通信的原理与编程实现

51单片机串口多机通信 需要用的的寄存器 (了解的可直接跳到下一节&#xff09; TMOD 定时器/计数器模式控制寄存器TCON 定时器控制寄存器SCON 串口控制寄存器PCON 电源控制位寄存器IE 中断中断使能寄存器 补充说明&#xff0c;TH1 预置值计算&#xff0c;中断源 波特率计算公式…

Java串口通信详解

序言 说到开源&#xff0c;恐怕很少有人不挑大指称赞。学生通过开源代码学到了知识&#xff0c;程序员通过开源类库获得了别人的成功经验及能够按时完成手头的工程&#xff0c;商家通过开源软件赚到了钱……&#xff0c;总之是皆大欢喜。然而开源软件或类库的首要缺点就是大多缺…

Java串口通信(RXTX)

这几天要用到串口通信,而我最会的Java,所以我就去学了一下怎么用Java进行串口通信 用的jar包是RXTX官网:http://rxtx.qbang.org/ 下载地址:http://fizzed.com/oss/rxtx-for-java 下载好Jar包后,首先需要配置,这里我用的Eclipse Window->Preferences->Java->Build …

十一、串口通信的基本原理与应用

通常用&#xff1a;SMOD 0&#xff0c;0xfd 利用51单片机的串行接口与上位机建立传输信道进行数据的收发。采用8位UART模式&#xff0c;即模式1&#xff0c;波特率为9600BPS。数据发送采用查询方式&#xff0c;数据接收采用中断方式。 系统上电初始化之后&#xff0c;单片机向…

【超简单的串口通信的工作原理】

下图是电脑收到单片机经过串口发送的信息&#xff0c; 那么电脑是如何与单片机进行串口通信的呢&#xff1f; 首先&#xff0c;任何一种通信都要包括硬件物理接口和软件通信协议。 串口通信物理接口如下图。单片机通过发送端将数据从左往右一位一位按顺序发送&#xff1b;且在…

串口通信基本原理

目录 串口通信连线&#xff1a; 串口通信时序&#xff1a; 起始位&#xff1a; 数据位&#xff1a; 校验位&#xff1a; 停止位&#xff1a; 总结&#xff1a; 串口通信特点&#xff1a; 基于串口的通讯接口&#xff1a; 串口通信连线&#xff1a; 任何通信都要有信息…

一篇短文让你彻底理解什么是串口通信

1 并行与串行通信 机器的通信方式有两种&#xff0c;分别是并行通信与串行通信。 并行通信&#xff1a;并行通信是指多比特数据同时通过并行线进行传送&#xff0c;这样数据传送速度大大提高&#xff0c;但并行传送的线路长度受到限制&#xff0c;因为长度增加&#xff0c;干…

Java RXTX 实现串口通信

目录 串口&#xff08;通信&#xff09;概述 串口调试助手 RXTX 下载与依赖 Java 开发实战 串口(通信)概述 1、串口通信是指串口按位&#xff08;bit&#xff09;发送和接收字节 2、串口通信可以在使用一根线发送数据的同时用另一根线接收数据 3、串口通信常用的协议包括…

串口通信原理

并行通信是指数据的各个位用多条数据线同时进行传输 优点&#xff1a;传输速度快 缺点&#xff1a;占用引脚资源多 串行通信是将数据分成一位一位的形式在一条传输线上逐个传输 优点&#xff1a;通信线路简单、占用引脚资源少 缺点&#xff1a;传输速度慢 同步通信&#xf…

串口通讯基本原理 【详细】

串口通信的基本知识 本文介绍了串口通讯的基本概念、数据格式、通讯方式、典型的串口通讯标准等内容。 串口通讯&#xff0c;RS232,RS485&#xff0c;停止位&#xff0c;奇校验&#xff0c;偶校验 1 串口通讯 串口通讯(Serial Communication)&#xff0c;是指外设和计算…

串口通信的基本原理详解

目录 串口通信 串口通信的两种基本方式 异步数据的数据发送过程 异步通信的数据接收过程 9针串口&#xff08;DB9&#xff09; TTL与RS232区别 TTL: RS232&#xff1a; 串口通信的数据格式 通讯方式 偶校验与奇校验 停止位 波特率&#xff08;波特率就是每秒钟传输…

串口通信原理详解

串口通信是一种串行异步通信&#xff0c;通信双方以字符帧作为数据传输单位&#xff0c;字符帧按位依次传输&#xff0c;每个位占固定的时间长度。两个字符帧之间的传输时间间隔可以是任意的&#xff0c;即传输完一个字符帧之后&#xff0c;可以间隔任意时间再传输下一个字符帧…

14_串口通信原理

通信方式的两种: 并行通讯: 传输原理:数据各个位同时传输。 优点:速度快 缺点:占用引脚资源多 串行通信: 传输原理:数据按位顺序传输。 优点:占用引脚资源少 缺点:速度相对较慢 串行通信: 按照数据传送方向,分为: 单工:数据传输只支持数据在一个方向上传输。 半双工:…

【Linux】基于美信串行解串器实现UART串口通信

文章目录 前言一、环境介绍二、硬件配置1. MAX967632. MAX96752F 三、串口通信协议1. 帧格式2. 同步帧3. 应答帧4. 包格式&#xff08;包由帧组成&#xff09; 四、内核模块实现 前言 车载项目中串行/解串器是十分常见的外设&#xff0c;目前常用的有两种标准&#xff1a;GMSL…

毫米波雷达图解算法原理(基于TI雷达)

毫米波雷达数据处理原理 前言基础bin文件解读 以下我们取1帧进行操作&#xff1a;对数据矩阵进行操作前的转换——开始计算结果矩阵一维FFT&#xff08;距离&#xff09;二维FFT&#xff08;速度&#xff09;角度维FFT &#xff08;假设利用结果已经获取目标&#xff09;对目标…

【阵列信号处理】DOA估计算法

DOA估计中的ESPRIT算法 ESPRIT算法时一种利用子空间旋转法估计DOA参数的方法&#xff0c;其算法的基本思想是将阵列在结构上分成两个完全一致的子列&#xff0c;两个子列相应阵元偏移的距离相等&#xff0c;也就是说阵列的阵元被分成一对对的形式&#xff0c;而且每一对之间具…

Hector SLAM 原理详解、算法解析

目录 1.原理详解 2.算法解析 1.原理详解 Hector整体算法很直接&#xff0c;就是将激光点与已有的地图“对齐”&#xff0c;即扫描匹配。扫描匹配就是使用当前帧与已经有的地图数据构建误差函数&#xff0c;使用高斯牛顿法得到最优解和偏差量。其工作是实现激光点到栅格地图的转…