前言:
现在各位老铁们对“串口通信程序c语言代码”可能比较关怀,大家都想要学习一些“串口通信程序c语言代码”的相关知识。那么小编在网络上搜集了一些对于“串口通信程序c语言代码””的相关知识,希望我们能喜欢,我们快快来学习一下吧!一、串口简述
串口通讯是指外设和计算机间通过数据信号线,地线,控制线等,按位进行传输数据的一种通讯方式。这种通讯方式使用的数据线少,在远距离通信中可以节约成本,但其传输速度比并行通讯慢。
串行接口是一种可以将接受来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时也可将接受的串行数据流转换为并行的数据字符供给CPU的器件。
串口通讯的速度与波特率有关,波特率就是发送二进制数据位的速率, 习惯上用 baud 表示, 即我们发送一位二进制数据的持续时间=1/baud。
一个字节是 8 位,当要发送数据之前,先发一位 0 表示起始位,然后发送 8 位数据位,数据位是先低后高的顺序,数据位发完后再发一位 1 表示停止位。这样本来要发送一个字节的 8 位数据,而实际上我们一共发送了 10 位。
以波特率9600为例,发送一位的时间为1/9600,那么发送一个字节的时间为10x1/9600,大约为1.042ms,我们可以利用这个通讯时间来处理数据分包和黏包的问题。
二、C#中的串口通讯
C#中提供了System.IO.Ports.SerialPort类,根据SerialPort类提供的简单操作步骤,可以很容易的完成串口的信息收发程序,从特定的串口中接收到数据也可以进行数据的发送。
1、开发环境和工具
①WIN10系统
②Visual Studio社区版 2022(C#)
2、创建一个类,命名为SerialBase
①添加一个自定义控件,右键解决方案,点击添加,点击新建项
②添加类,并命名为SerialBase,然后点击添加
③在SerialBase这个cs文件里面添加以下程序
using System;using System.Collections.Generic;using System.IO.Ports;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;namespace Serial{ public class SerialBase : IDisposable { /// <summary> /// 实例化一个无参的构造方法 /// </summary> public SerialBase() { serialPort = new SerialPort(); } /// <summary> /// 初始化串口信息,9600波特率,8位数据位,1位停止位,无奇偶校验 /// </summary> /// <param name="portName">端口号信息</param> public void SerialPortInit(string portName) { SerialPortInit(portName, 9600); } /// <summary> /// 初始化串口信息,波特率,8位数据位,1位停止位,无奇偶校验 /// </summary> /// <param name="portName">端口号信息,例如"COM3"</param> /// <param name="baudRate">波特率</param> public void SerialPortInit(string portName, int baudRate) { SerialPortInit(portName, baudRate, 8, StopBits.One, Parity.None); } /// <summary> /// 初始化串口信息,波特率,数据位,停止位,奇偶校验 /// </summary> /// <param name="portName">端口号信息,例如"COM3"</param> /// <param name="baudRate">波特率</param> /// <param name="dataBits">数据位</param> /// <param name="stopBits">停止位</param> /// <param name="parity">奇偶校验</param> public void SerialPortInit(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity) { if (serialPort.IsOpen) { return; } serialPort.PortName = portName; // 串口 serialPort.BaudRate = baudRate; // 波特率 serialPort.DataBits = dataBits; // 数据位 serialPort.StopBits = stopBits; // 停止位 serialPort.Parity = parity; // 奇偶校验 PortName = serialPort.PortName; BaudRate = serialPort.BaudRate; } /// <summary> /// 根据自定义初始化方法进行初始化串口信息 /// </summary> /// <param name="init">初始化的委托方法</param> public void SerialPortInit(Action<SerialPort> init) { if (serialPort.IsOpen) { return; } serialPort.PortName = "COM10"; serialPort.BaudRate = 9600; serialPort.DataBits = 8; serialPort.StopBits = StopBits.One; serialPort.Parity = Parity.None; init.Invoke(serialPort); PortName = serialPort.PortName; BaudRate = serialPort.BaudRate; } /// <summary> /// 打开串行端口 /// </summary> public void Open() { if (!serialPort.IsOpen) { serialPort.Open(); } } /// <summary> /// 指示串口是否处打开 /// </summary> /// <returns>是或否</returns> public bool IsOpen() { return serialPort.IsOpen; } /// <summary> /// 关闭端口连接 /// </summary> public void Close() { if (serialPort.IsOpen) { serialPort.Close(); } } public void write(string buf) { serialPort.Write(buf); } /// <summary> /// 读取串口的数据 /// </summary> /// <param name="send">发送的原始字节数据</param> /// <returns>带接收字节的结果对象</returns> public byte[] ReadBase(byte[] send) { if(IsClearCacheBeforeRead) ClearSerialCache(); int sendResult = SendByte(send); if(sendResult != 0) { } byte[] receiveResult = ReceivedByte(serialPort, true); return receiveResult; } /// <summary> /// 发送数据到串口里去 /// </summary> /// <param name="serialPort">串口对象</param> /// <param name="data">字节数据</param> /// <returns>是否发送成功,0发送成功,1发送报错,2发送内容为空</returns> public int SendByte(byte[] data) { if (data != null && data.Length > 0) { try { serialPort.Write(data, 0, data.Length); return 0; } catch { return 1; } } else { return 2; } /// <summary> /// 从串口接收一串数据信息,可以指定是否一定要接收到数据 /// </summary> /// <param name="serialPort">串口对象</param> /// <param name="awaitData">是否必须要等待数据返回</param> /// <returns>结果数据对象</returns> public byte[] ReceivedByte(SerialPort serialPort, bool awaitData) { byte[] buffer = new byte[1024]; System.IO.MemoryStream ms = new System.IO.MemoryStream(); DateTime start = DateTime.Now;// 开始时间,用于确认是否超时的信息 while (true) { Thread.Sleep(sleepTime); try { if (serialPort.BytesToRead < 1) //没有数据进来,进行判断 { //超时 if ((DateTime.Now start).TotalMilliseconds >receiveTimeout&& receiveTimeout!=0) { ms.Dispose(); break; } else if (ms.Length > 0) //数据接收完成 { break; } else if (awaitData) //等待数据传入 { continue; } else { break; } } //有数据进来,继续接收数据 int receive = serialPort.Read(buffer, 0, buffer.Length); ms.Write(buffer, 0, receive); } catch { ms.Dispose(); } } byte[] result = ms.ToArray(); ms.Dispose(); return result; } /// <summary> /// 是否在发送数据前清空缓冲数据,默认是false /// </summary> public bool IsClearCacheBeforeRead { get { return isClearCacheBeforeRead; } set { isClearCacheBeforeRead = value; } } /// <summary> /// 清除串口缓冲区的数据,并返回该数据,如果缓冲区没有数据,返回的字节数组长度为0 /// </summary> /// <returns>是否操作成功的方法</returns> public byte[] ClearSerialCache() { return ReceivedByte(serialPort, false); } /// <summary> /// 返回表示当前对象的字符串 /// </summary> /// <returns>字符串</returns> public override string ToString() { return "SerialBase"; } /// <summary> /// 接收数据的超时时间,默认5000ms,设为0则表示无超时报警 /// </summary> public int ReceiveTimeout { get { return receiveTimeout; } set { receiveTimeout = value; } } /// <summary> /// 连续串口缓冲数据检测的间隔时间,默认20ms /// </summary> public int SleepTime { get { return sleepTime; } set { if (value > 0) sleepTime = value; } } /// <summary> /// 本连接对象的端口号名称 /// </summary> public string PortName { get; private set; } /// <summary> /// 本连接对象的波特率 /// </summary> public int BaudRate { get; private set; } private bool disposedValue; protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // TODO: 释放托管状态(托管对象) serialPort?.Dispose(); } // TODO: 释放未托管的资源(未托管的对象)并替代终结器 // TODO: 将大型字段设置为 null disposedValue = true; } } //// TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器 // ~SerialBase() // { // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中 // Dispose(disposing: false); // } public void Dispose() { // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中 Dispose(disposing: true); GC.SuppressFinalize(this); } private SerialPort serialPort = null; // 串口交互 private int receiveTimeout = 5000; // 接收数据的超时时间 private int sleepTime = 20; // 睡眠的时间 private bool isClearCacheBeforeRead = false; // 是否在发送前清除缓冲 }}
3、在Winform中调用SerialBase
①从左侧工具箱拖曳控件并布局,如下图所示
②实现程序
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.IO.Ports;using System.Data.SqlTypes;using System.Xml.Linq;namespace Serial{ public partial class Form1 : Form { public Form1() { InitializeComponent(); } SerialBase serial = new SerialBase();//定义一个串口 private void SerialInit(SerialPort Init) { Init.PortName = cboxPort.Text; //串口号 Init.BaudRate = Convert.ToInt16(cboxBaudRate.Text); //波特率 Init.DataBits = 8; Init.StopBits = StopBits.One; Init.Parity = Parity.None; } private void btnFlesh_Click(object sender, EventArgs e) { string[] names=SerialPort.GetPortNames();//查找可用串口 cboxPort.Items.Clear(); for(int i=0;i<names.Length;i++) { cboxPort.Items.Add(names[i]); //串口号下拉菜单,增加一个条目 } } private void btnOpenPort_Click(object sender, EventArgs e) { serial.SerialPortInit(SerialInit); //初始化串口 serial.Open(); //打开串口 } private void btnSend_Click(object sender, EventArgs e) { byte[] rece = new byte[1024]; //发送数据 rece = serial.ReadBase(new byte[] { 0x00,0x01,0x02,0x03,0x04,0x05}) ; txtBoxRece.Text += rece.Length > 0 ? DataTrans.ByteToHexString(rece)+ "\r\n" : "接收数据超时" + "\r\n"; }
4、效果演果
视频加载中...
标签: #串口通信程序c语言代码