[转]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就不好处理了.所以写了一个同步模式接 ...
随机推荐
- RHEL 环境下 Subversion 服务器部署与配置
RHEL 环境下 Subversion 服务器部署与配置 1. 更新系统 首先确保系统软件包是最新的: sudo yum update -y 2. 安装Apache和Subversion 2.1 安装 ...
- springboot-实现excle文件导出的单元格相同内容合并
导出excle文件中的单元格有些需要合并如何操作 例如:左边的表格想合并单元格成右边的表格更加便于观看 一.依赖文件 <!-- excle操作--> <depen ...
- 工作中的技术总结_JAVA_AA-00001 关于Session的使用 _20210825
AA-00001 关于Session的使用 _20210825 Session Java 中的Session:javax.servlet.http.HttpSession; 应用: 在我自己的项目中 ...
- 一文彻底弄懂spring boot自动转配的过程
Spring Boot 的自动配置机制是它的重要特性之一,极大地简化了 Spring 应用的配置工作.自动配置的核心思想是基于类路径中的依赖.环境配置以及自定义代码进行智能化配置,避免了开发者手动编写 ...
- Graphische Datenverarbeitung Ⅰ 学习笔记
1. Pipeline 1.1 Graphische Primitive 1.2 Model and View Transform 1.3 Vertex Shading 1.4 Clipping 1. ...
- 看图认识Javascript
- Nuxt.js 应用中的 nitro:build:public-assets 事件钩子详解
title: Nuxt.js 应用中的 nitro:build:public-assets 事件钩子详解 date: 2024/11/5 updated: 2024/11/5 author: cmdr ...
- 华为三折屏Mate XT
相关: https://www.youtube.com/watch?v=vMx3kVnp11Q
- STM32单片机 32.768Khz和8Khz晶振外部电容容值选取问题
一.前言 绘制STM32C8T6最小系统的晶振电路的时候,看到了并联在晶振两端的电容,就好奇具体的容值该怎么选取,故有了这篇博客. 二.外部晶振电路
- div跟随浏览器大小而改变
<head> <style> .main { position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; ...