[转]C# SerialPort串口通信发送接收,处理接收数据完整
废话少说,直接上干货。感兴趣的读者自己去研究代码吧。请见谅。
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading; namespace SerialPortCom
{
public class SerialPortComImplement
{
public delegate void RecEventHandler(byte[] queueByte);
public event RecEventHandler DataReceivedEvent;
private SerialPort serialPort;
private List<byte> buffer = new List<byte>(4096);
/// <summary>
/// 初始化
/// </summary>
/// <param name="portName">端口名称</param>
/// <param name="baudRate">波特率</param>
/// <param name="dataBits">数据位</param>
public SerialPortComImplement(string portName, int baudRate, int dataBits)
{
serialPort = new SerialPort(portName, baudRate, Parity.None);
serialPort.DataBits = dataBits;
serialPort.StopBits = StopBits.One;
serialPort.ReadTimeout = 2000;
serialPort.WriteBufferSize = 1024;
serialPort.ReadBufferSize = 1024;
serialPort.RtsEnable = true;
serialPort.DtrEnable = true;
serialPort.ReceivedBytesThreshold = 1;
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceivedEventHandler);
}
/// <summary>
/// 串口数据接收事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void serialPort_DataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] readBuffer = null;
int n = serialPort.BytesToRead;
byte[] buf = new byte[n];
serialPort.Read(buf, 0, n);
//1.缓存数据
buffer.AddRange(buf);
//2.完整性判断
while (buffer.Count >= 7)
{
//至少包含标头(1字节),长度(1字节),校验位(2字节)等等
//2.1 查找数据标记头
if (buffer[0] == 0x00) //传输数据有帧头,用于判断
{
int len = buffer[1];
if (buffer.Count < len + 2)
{
//数据未接收完整跳出循环
break;
}
readBuffer = new byte[len + 2];
//得到完整的数据,复制到readBuffer中
buffer.CopyTo(0, readBuffer, 0, len + 2);
//从缓冲区中清除
buffer.RemoveRange(0, len + 2); //触发外部处理接收消息事件 }
}
else //开始标记或版本号不正确时清除
{
buffer.RemoveAt(0);
}
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
}
}
/// <summary>
/// 打开端口
/// </summary>
public bool Open()
{
try
{
if (!serialPort.IsOpen)
{
serialPort.Open();
return true;
}
else
{
return true;
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
return false;
} }
/// <summary>
/// 发送字节
/// </summary>
/// <param name="writeBytes">要发送的字节</param>
/// <returns></returns>
public bool Write(byte[] writeBytes)
{
if (Open())
{
try
{
serialPort.Write(writeBytes, 0, writeBytes.Length);
string mergeStr = "发送:";
for (int j = 0; j < writeBytes.Length; j++)
{
mergeStr = mergeStr + writeBytes[j].ToString("x") + " ";
}
SerialPortLog.Info(mergeStr);
return true;
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
return false;
}
}
return false;
}
/// <summary>
/// 发送字符串
/// </summary>
/// <param name="writestrs"></param>
/// <returns></returns>
public bool Write(string writeStrs)
{
if (Open())
{
try
{
serialPort.Write(writeStrs);
Thread.Sleep(100);
return true;
}
catch
{
return false;
}
}
return false;
}
/// <summary>
/// 读取数据
/// </summary>
/// <param name="NumBytes">读取的字节数</param>
/// <returns></returns>
public byte[] Read(int NumBytes)
{
byte[] inbuffer = null; if (serialPort.IsOpen && serialPort.BytesToRead > 0)
{
if (NumBytes > serialPort.BytesToRead)
{
NumBytes = serialPort.BytesToRead;
}
try
{
inbuffer = new byte[NumBytes];
int count = serialPort.Read(inbuffer, 0, NumBytes);
}
catch (TimeoutException timeoutEx)
{
//超时异常
SerialPortLog.Error(timeoutEx, "");
}
}
return inbuffer;
}
public byte[] Read()
{
return Read(serialPort.BytesToRead);
}
public string ReadLine()
{
try
{
if (serialPort.IsOpen && serialPort.BytesToRead > 0)
{
string s = serialPort.ReadExisting();
return serialPort.ReadLine();
}
return null;
}
catch (TimeoutException timeoutEx)
{
SerialPortLog.Error(timeoutEx, "");
return timeoutEx.Message;
}
}
/// <summary>
/// 关闭串口
/// </summary>
public void Close()
{
try
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
}
} public bool IsOpen
{
get
{
return serialPort.IsOpen;
}
}
}
}
原文链接:
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
namespace SerialPortCom
{
public class SerialPortComImplement
{
public delegate void RecEventHandler(byte[] queueByte);
public event RecEventHandler DataReceivedEvent;
private SerialPort serialPort;
private List<byte> buffer = new List<byte>(4096);
/// <summary>
/// 初始化
/// </summary>
/// <param name="portName">端口名称</param>
/// <param name="baudRate">波特率</param>
/// <param name="dataBits">数据位</param>
public SerialPortComImplement(string portName, int baudRate, int dataBits)
{
serialPort = new SerialPort(portName, baudRate, Parity.None);
serialPort.DataBits = dataBits;
serialPort.StopBits = StopBits.One;
serialPort.ReadTimeout = 2000;
serialPort.WriteBufferSize = 1024;
serialPort.ReadBufferSize = 1024;
serialPort.RtsEnable = true;
serialPort.DtrEnable = true;
serialPort.ReceivedBytesThreshold = 1;
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceivedEventHandler);
}
/// <summary>
/// 串口数据接收事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void serialPort_DataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] readBuffer = null;
int n = serialPort.BytesToRead;
byte[] buf = new byte[n];
serialPort.Read(buf, 0, n);
//1.缓存数据
buffer.AddRange(buf);
//2.完整性判断
while (buffer.Count >= 7)
{
//至少包含标头(1字节),长度(1字节),校验位(2字节)等等
//2.1 查找数据标记头
if (buffer[0] == 0x00) //传输数据有帧头,用于判断
{
int len = buffer[1];
if (buffer.Count < len + 2)
{
//数据未接收完整跳出循环
break;
}
readBuffer = new byte[len + 2];
//得到完整的数据,复制到readBuffer中
buffer.CopyTo(0, readBuffer, 0, len + 2);
//从缓冲区中清除
buffer.RemoveRange(0, len + 2);
//触发外部处理接收消息事件
}
}
else //开始标记或版本号不正确时清除
{
buffer.RemoveAt(0);
}
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
}
}
/// <summary>
/// 打开端口
/// </summary>
public bool Open()
{
try
{
if (!serialPort.IsOpen)
{
serialPort.Open();
return true;
}
else
{
return true;
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
return false;
}
}
/// <summary>
/// 发送字节
/// </summary>
/// <param name="writeBytes">要发送的字节</param>
/// <returns></returns>
public bool Write(byte[] writeBytes)
{
if (Open())
{
try
{
serialPort.Write(writeBytes, 0, writeBytes.Length);
string mergeStr = "发送:";
for (int j = 0; j < writeBytes.Length; j++)
{
mergeStr = mergeStr + writeBytes[j].ToString("x") + " ";
}
SerialPortLog.Info(mergeStr);
return true;
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
return false;
}
}
return false;
}
/// <summary>
/// 发送字符串
/// </summary>
/// <param name="writestrs"></param>
/// <returns></returns>
public bool Write(string writeStrs)
{
if (Open())
{
try
{
serialPort.Write(writeStrs);
Thread.Sleep(100);
return true;
}
catch
{
return false;
}
}
return false;
}
/// <summary>
/// 读取数据
/// </summary>
/// <param name="NumBytes">读取的字节数</param>
/// <returns></returns>
public byte[] Read(int NumBytes)
{
byte[] inbuffer = null;
if (serialPort.IsOpen && serialPort.BytesToRead > 0)
{
if (NumBytes > serialPort.BytesToRead)
{
NumBytes = serialPort.BytesToRead;
}
try
{
inbuffer = new byte[NumBytes];
int count = serialPort.Read(inbuffer, 0, NumBytes);
}
catch (TimeoutException timeoutEx)
{
//超时异常
SerialPortLog.Error(timeoutEx, "");
}
}
return inbuffer;
}
public byte[] Read()
{
return Read(serialPort.BytesToRead);
}
public string ReadLine()
{
try
{
if (serialPort.IsOpen && serialPort.BytesToRead > 0)
{
string s = serialPort.ReadExisting();
return serialPort.ReadLine();
}
return null;
}
catch (TimeoutException timeoutEx)
{
SerialPortLog.Error(timeoutEx, "");
return timeoutEx.Message;
}
}
/// <summary>
/// 关闭串口
/// </summary>
public void Close()
{
try
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
}
}
public bool IsOpen
{
get
{
return serialPort.IsOpen;
}
}
}
}
------------恢复内容开始------------
废话少说,直接上干货。感兴趣的读者自己去研究代码吧。请见谅。
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading; namespace SerialPortCom
{
public class SerialPortComImplement
{
public delegate void RecEventHandler(byte[] queueByte);
public event RecEventHandler DataReceivedEvent;
private SerialPort serialPort;
private List<byte> buffer = new List<byte>(4096);
/// <summary>
/// 初始化
/// </summary>
/// <param name="portName">端口名称</param>
/// <param name="baudRate">波特率</param>
/// <param name="dataBits">数据位</param>
public SerialPortComImplement(string portName, int baudRate, int dataBits)
{
serialPort = new SerialPort(portName, baudRate, Parity.None);
serialPort.DataBits = dataBits;
serialPort.StopBits = StopBits.One;
serialPort.ReadTimeout = 2000;
serialPort.WriteBufferSize = 1024;
serialPort.ReadBufferSize = 1024;
serialPort.RtsEnable = true;
serialPort.DtrEnable = true;
serialPort.ReceivedBytesThreshold = 1;
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceivedEventHandler);
}
/// <summary>
/// 串口数据接收事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void serialPort_DataReceivedEventHandler(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] readBuffer = null;
int n = serialPort.BytesToRead;
byte[] buf = new byte[n];
serialPort.Read(buf, 0, n);
//1.缓存数据
buffer.AddRange(buf);
//2.完整性判断
while (buffer.Count >= 7)
{
//至少包含标头(1字节),长度(1字节),校验位(2字节)等等
//2.1 查找数据标记头
if (buffer[0] == 0x00) //传输数据有帧头,用于判断
{
int len = buffer[1];
if (buffer.Count < len + 2)
{
//数据未接收完整跳出循环
break;
}
readBuffer = new byte[len + 2];
//得到完整的数据,复制到readBuffer中
buffer.CopyTo(0, readBuffer, 0, len + 2);
//从缓冲区中清除
buffer.RemoveRange(0, len + 2); //触发外部处理接收消息事件 }
}
else //开始标记或版本号不正确时清除
{
buffer.RemoveAt(0);
}
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
}
}
/// <summary>
/// 打开端口
/// </summary>
public bool Open()
{
try
{
if (!serialPort.IsOpen)
{
serialPort.Open();
return true;
}
else
{
return true;
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
return false;
} }
/// <summary>
/// 发送字节
/// </summary>
/// <param name="writeBytes">要发送的字节</param>
/// <returns></returns>
public bool Write(byte[] writeBytes)
{
if (Open())
{
try
{
serialPort.Write(writeBytes, 0, writeBytes.Length);
string mergeStr = "发送:";
for (int j = 0; j < writeBytes.Length; j++)
{
mergeStr = mergeStr + writeBytes[j].ToString("x") + " ";
}
SerialPortLog.Info(mergeStr);
return true;
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
return false;
}
}
return false;
}
/// <summary>
/// 发送字符串
/// </summary>
/// <param name="writestrs"></param>
/// <returns></returns>
public bool Write(string writeStrs)
{
if (Open())
{
try
{
serialPort.Write(writeStrs);
Thread.Sleep(100);
return true;
}
catch
{
return false;
}
}
return false;
}
/// <summary>
/// 读取数据
/// </summary>
/// <param name="NumBytes">读取的字节数</param>
/// <returns></returns>
public byte[] Read(int NumBytes)
{
byte[] inbuffer = null; if (serialPort.IsOpen && serialPort.BytesToRead > 0)
{
if (NumBytes > serialPort.BytesToRead)
{
NumBytes = serialPort.BytesToRead;
}
try
{
inbuffer = new byte[NumBytes];
int count = serialPort.Read(inbuffer, 0, NumBytes);
}
catch (TimeoutException timeoutEx)
{
//超时异常
SerialPortLog.Error(timeoutEx, "");
}
}
return inbuffer;
}
public byte[] Read()
{
return Read(serialPort.BytesToRead);
}
public string ReadLine()
{
try
{
if (serialPort.IsOpen && serialPort.BytesToRead > 0)
{
string s = serialPort.ReadExisting();
return serialPort.ReadLine();
}
return null;
}
catch (TimeoutException timeoutEx)
{
SerialPortLog.Error(timeoutEx, "");
return timeoutEx.Message;
}
}
/// <summary>
/// 关闭串口
/// </summary>
public void Close()
{
try
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
}
catch (Exception ex)
{
SerialPortLog.Error(ex, "");
}
} public bool IsOpen
{
get
{
return serialPort.IsOpen;
}
}
}
}
原文链接:C# SerialPort串口通信发送接收,处理接收数据完整
[转]C# SerialPort串口通信发送接收,处理接收数据完整的更多相关文章
- System.IO.Ports.SerialPort串口通信接收完整数据
C#中使用System.IO.Ports.SerialPort进行串口通信网上资料也很多,但都没有提及一些细节: 比如 串口有时候并不会一次性把你想要的数据全部传输给你,可能会分为1次,2次,3次分别 ...
- winform SerialPort串口通信问题
一.串口通信简介串行接口(串口)是一种可以将接受来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接受的串行数据流转换为并行的数据字符供给CPU的器件.一般完成这种功能的电路,我们称为串 ...
- Linux串口通信中一种接收不到数据的问题的解决
转载来源:嵌入式系统之初学者点滴 (百度空间) 原文 在这篇文章()中,实现了Linux环境下的串口读写操作,程序也运行成功了.但是再进一步测试时发现,如果开机之后直接如上文中所说,分别运行读程序和写 ...
- C#串口通信发送数据
1 发送数据 需要2个串口 http://www.openedv.com/thread-228847-1-1.html 下载源文件 File_Protocol_Test.rar
- ESP32 BLE蓝牙 微信小程序通信发送大于20字符数据
由于微信小程序只支持BLE每次发送数据不大于20个字节,ESP32则有经典蓝牙.低功耗蓝牙两种模式. 要解决发送数据大于20个字节的问题,最简单实用的方式就是分包发送.如下图所示: 1.什么起始字符和 ...
- Qt 串口通信
在Qt5之前,串口通信基本依赖于第三方库,下面是我曾接触过的串口通信类库: 名称 语言 平台 QextSerialPort QT C++ Win/Linux http://sourceforge. ...
- Linux与Windows串口通信
串口是常用的计算机与外部串行设备之间的数据传输通道,由于串行通信方便易行,所以应用广泛.现在国际上不断有串口新技术及新规格推出,结合社会各方面需要,串口通信发展的空间庞大.串口通讯技术因其自身的优势和 ...
- 在C#中实现串口通信的方法
通常,在C#中实现串口通信,我们有四种方法: 第一:通过MSCOMM控件这是最简单的,最方便的方法.可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册,不在本文讨论范围.可以访问h ...
- c#中实现串口通信的几种方法
c#中实现串口通信的几种方法 通常,在C#中实现串口通信,我们有四种方法: 第一:通过MSCOMM控件这是最简单的,最方便的方法.可功能上很难做到控制自如,同时这个控件并不是系统本身所带,所以还得注册 ...
- C#串口通信—向串口发送数据,同步接收返回数据
最近写C#串口通信程序,系统是B/S架构.SerialPort类有一个DataReceived事件,用来接收串口返回的数据,但这种方式在C/S架构下很好用,但B/S就不好处理了.所以写了一个同步模式接 ...
随机推荐
- 云原生周刊:Kubernetes 1.29 中的删除、弃用和主要更改 | 2023.11.27
开源项目推荐 Orphaned ConfigMaps 该版本库包含一个脚本,用于识别 Kubernetes 命名空间中的孤立的配置映射.孤立的配置映射是指那些未被命名空间中的任何活动 Pod 或容器引 ...
- KubeSphere 社区双周报 | FluentBit 新增 tcp 输入插件 | 2023.09.29-10.12
KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...
- Readme 《Machine Learning by Andrew NG》
本文系列内容是吴恩达老师的机器学习公开课的文本对应.需要具备英文,微积分,线性代数,程序设计的基础.从第二周开始有编程作业,到第九周.总共8个作业.感谢吴恩达老师⸜₍๑•⌔•๑ ₎⸝ 2021年9月1 ...
- ArgoWorkflow教程(八)---基于 LifecycleHook 实现流水线通知提醒
本篇介绍一下 ArgoWorkflow 中的 ExitHandler 和 LifecycleHook 功能,可以根据流水线每一步的不同状态,执行不同操作,一般用于发送通知. 1. 概述 本篇介绍一下 ...
- 2024 Navicat Premium 16+17安装教程(附激活方法)
Navicat Premium,作为一款功能全面的集成数据库管理工具,无缝支持多样化的数据库类型,为用户带来前所未有的高效与便捷管理体验.它不仅涵盖了连接管理.数据导入导出.同步迁移.备份恢复等核心功 ...
- games101_Homework2
完成函数static bool insideTriangle(): 测试点是否在三角形内. 一段优雅的easy代码,没什么好说的.(但是需要修改这里传入的xy的类型为float,默认为int是想让我通 ...
- Visual Studio 存在版本之间冲突
1 . 检查项目中有没有重复引用的包,如果有的话卸掉一个. 2.. 检查项目中引用的包是否自带所重复的包,这样会导致项目之间引发包冲突. 举个例子: 我的项目里ICSharpCode.SharpZip ...
- delphi Image32 动画演示2
Image 32 自带的Demo,添加一些注解. unit uFrmAnimation2; interface uses Winapi.Windows, Winapi.Messages, System ...
- AI智能学生体测小程序解决方案
引言: 近年来,随着教育理念的提升,对学生综合素质的教育越发重视,特别是越发重视学生的身体素质提升,各阶段的升学考试也将体测纳入考核范围.学校也推出了各种体测锻炼促进手段,今天为您介绍一个基于小程序的 ...
- Windows 使用 Intel(R) Arc(TM) GPU 推理ONNX 模型
这不刚换了一个笔记本电脑,Thinkpad T14P,带有Intel ARC GPU,今天我们来尝试用这个GPU来推理ONNX模型. 环境安装 查阅了相关文档,最好使用py310环境,其他版本可能存在 ...