c#串口通讯详解(附源码)
串口通讯
串口通讯是计算机传输数据的一种通讯方式,只不过是以比特位来传输数据的
串口通讯的相关参数
波特率:
波特率的大小代表每秒钟可以传输多少个二进制位,如波特率是9600,能每秒传输9600二进制位
起始位、停止位
数据包从起始位开始,到停止位结束。起始信号用逻辑0的数据位表示,停止信号由0.5、1、1.5或2个逻辑1的数据位表示,只要双方约定一致即可。标识这本次通讯单元的结束
数据位
起始位之后便是传输的主体数据内容了,也称为有效数据,其长度一般被约定为5、6、7或8位长。表示一次通讯真正的要发送的有效数据
奇偶校验位
由于在通讯过程中易受到外部干扰导致传输数据出现偏差,所以在有效数据之后加上校验位解决。是串口通讯中的一周检错方式
界面展示
发送跟接收支持ASCII跟Hex格式
代码部分如下:
后端代码
public partial class Comm : Form{public Comm(){InitializeComponent();ComHelper.Data += AddContent;ComHelper.ReceiveNum += AddNums;ComHelper.SendNum += AddNum;}//页面启动事件private void Comm_Load(object sender, EventArgs e){//读取计算机所有串口string[] strCom = SerialPort.GetPortNames();if (strCom == null){MessageBox.Show("本机没有串口!", "Error");return;}//GetPortNames()方法:获取当前计算机的串行端口名的数组foreach (string com in System.IO.Ports.SerialPort.GetPortNames()){com_port.Items.Add(com);}//默认选中第一个com_port.SelectedIndex = 0;com_jyw.SelectedIndex = 0;com_data.Text = "8";com_stop.SelectedIndex = 0;com_bps.Text = "4800";receive_ascii.Checked = true;send_ascii.Checked = true;}//选中保存目录private void receive_file_Click(object sender, EventArgs e){OpenFileDialog dialog = new OpenFileDialog();dialog.Multiselect = true;//该值确定是否可以选择多个文件dialog.Title = "请选择文件夹";dialog.Filter = "所有文件(*.*)|*.*";if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK){receive_FileSrc.Text = dialog.FileName;}}private void AddNum(object content){int sendnum = int.Parse(content.ToString()); ;num1.Text = (int.Parse(num1.Text) + sendnum).ToString();}private void AddNums(object content){int sendnum = int.Parse(content.ToString()); ;num2.Text = (int.Parse(num2.Text) + sendnum).ToString();}//将接受到的内容显示出来private void AddContent(object content){this.BeginInvoke(new MethodInvoker(delegate{string str = content as string;if (IsTime.Checked == true){string Title = DateTime.Now.ToString();bt_ReceiveData.AppendText("[" + Title + "]# RECV " + (receive_ascii.Checked == true ? "ASCII" : "HEX") + "\r\n");}bt_ReceiveData.AppendText(str + " ");if (IsLine.Checked == true){bt_ReceiveData.AppendText("\r\n");}bt_ReceiveData.Focus();//先获取焦点bt_ReceiveData.Select(bt_ReceiveData.TextLength, 0);//选中数据末尾0个字符bt_ReceiveData.ScrollToCaret();//将滚动条移动到当前位置//记录收到的字符个数//toolStripStatusLabel1.Text += (int.Parse(toolStripStatusLabel1.Text) + content.Length).ToString();}));}//清空接收区private void receive_clean_Click(object sender, EventArgs e){this.bt_ReceiveData.Text = "";}//清空发送区private void send_clean_Click(object sender, EventArgs e){this.bt_SendData.Text = "";}/// 打开串口private void com_open_Click(object sender, EventArgs e){//实例化串口配置ComClass com = new ComClass(){PortName = com_port.Text,BaudRate = int.Parse(this.com_bps.Text),Databit = int.Parse(com_data.Text),Stopbit = float.Parse(com_stop.Text),Paritybit = this.com_jyw.Text};//判断端口是否打开if (!ComHelper.port.IsOpen){ComHelper.SerialClass(com);//判断是否已经打开串口控件禁用if (ComHelper.OpenPart()){this.com_state.Checked = true;this.com_port.Enabled = false;this.com_bps.Enabled = false;this.com_data.Enabled = false;this.com_stop.Enabled = false;this.com_jyw.Enabled = false;this.com_open.Text = "关闭串口";}}else{ComHelper.closePort();this.com_port.Enabled = true;this.com_bps.Enabled = true;this.com_data.Enabled = true;this.com_stop.Enabled = true;this.com_jyw.Enabled = true;this.com_state.Checked = false;this.com_open.Text = "打开串口";}}//发送数据private void bt_send_Click(object sender, EventArgs e){string SendData = this.bt_SendData.Text.Trim();//判断是否是HEX发送if (send_hex.Checked == true){if (!ComHelper.IsHexadecimal(SendData)) { MessageBox.Show("输入非16进制数据"); }ComHelper.SendData(SendData, true);}else{ComHelper.SendData(SendData, false);}}//选中HEX时判断输入内容是否为HEX数据,如果不是将其转换成Hexprivate void send_hex_Click(object sender, EventArgs e){if (send_hex.Checked == true && !ComHelper.IsHexadecimal(this.bt_SendData.Text)){this.bt_SendData.Text = ComHelper.GetHexFromChs(bt_SendData.Text);}}//接收是否为Hex格式private void receive_hex_CheckedChanged(object sender, EventArgs e){if (receive_hex.Checked == true){ComHelper.ReceiveIsHex = true;}else{ComHelper.ReceiveIsHex = false;}}private void send_file_Click(object sender, EventArgs e){OpenFileDialog dialog = new OpenFileDialog();dialog.Multiselect = true;//该值确定是否可以选择多个文件dialog.Title = "请选择文件夹";dialog.Filter = "所有文件(*.*)|*.*";if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK){this.bt_SendData.Text = ComHelper.fileToString(dialog.FileName);}}}
}
ComClass实体类
namespace MSComm
{public class ComClass{private string _portName;private int _baud;private float _stopbit;private int _databit;private string _paritybit;public string PortName { get => _portName; set => _portName = value; }//获取串口名public int BaudRate { get => _baud; set => _baud = value; }//波特率public float Stopbit { get => _stopbit; set => _stopbit = value; }//停止位public int Databit { get => _databit; set => _databit = value; }//数据位public string Paritybit { get => _paritybit; set => _paritybit = value; }//校验位}
}
ComHelper类
namespace MSComm
{public class ComHelper{public delegate void ReceiveData(object str);public static event ReceiveData Data;public static event ReceiveData ReceiveNum;public static event ReceiveData SendNum;//是否Hex接收public static bool ReceiveIsHex = false;//实例化串口public static SerialPort port = new SerialPort();//读取缓存区数据static StringBuilder Datas = new StringBuilder("");static bool rest = true;//打开串口配置串口public static void SerialClass(ComClass p){port.PortName = p.PortName;port.BaudRate = p.BaudRate;port.DataBits = p.Databit;switch (p.Stopbit){case 1:port.StopBits = StopBits.One; //使用一个停止位break;case 1.5f:port.StopBits = StopBits.OnePointFive; //使用一个停止位break;case 2:port.StopBits = StopBits.Two; //使用一个停止位break;default:break;}switch (p.Paritybit){case "NONE":port.Parity = Parity.None;break;case "ODD":port.Parity = Parity.Odd;break;case "EVEN":port.Parity = Parity.Even;break;case "MARK":port.Parity = Parity.Mark;break;case "SPACE":port.Parity = Parity.Space;break;default:break;}//port.Handshake = Handshake.None;port.RtsEnable = true;port.DtrEnable = true;//获取或设置一个值,改值在串行通讯过程中启用数据终端就绪(DTR)信号。port.ReadTimeout = 2000;port.DataReceived += Sp1_DataReceived;}/// <summary>/// 打开串口/// </summary>/// <returns></returns>public static bool OpenPart(){bool ok = false;//如果串口是打开的,先关闭if (port.IsOpen) port.Close();try{//打开串口port.Open();ok = true;}catch (Exception Ex){throw Ex;}return ok;}/// <summary>/// 关闭串口/// </summary>public static void closePort(){if (port.IsOpen){port.Close();}}/// <summary>/// 数据发送/// </summary>/// <param name="Data">数据</param>/// <param name="IsHEX">是否Hex发送</param>public static void SendData(string Data, bool IsHEX){byte[] sendData = null;if (!port.IsOpen) //如果没打开{return;}String strSend = Data;try{if (IsHEX){sendData = ConvertHexStringToBytes(strSend.Trim());}else{sendData = Encoding.Default.GetBytes(strSend.Trim());}//sp1.WriteLine(txtSendStr.Text); //写入数据SendNum(sendData.Length);port.Write(sendData, 0, sendData.Length);}catch (Exception ex){}}/// <summary>/// 监听返回值/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private static void Sp1_DataReceived(object sender, SerialDataReceivedEventArgs e){if (ComHelper.port.IsOpen) //判断是否打开串口{string content = "";int Lengths = port.BaudRate/10;//输出当前时间DateTime dt = DateTime.Now;try{Byte[] receivedData = new Byte[port.BytesToRead]; //创建接收字节数组port.Read(receivedData, 0, receivedData.Length); //读取数据ReceiveNum(receivedData.Length);//foreach (byte item in receivedData)//{// Datas.Append(Convert.ToChar(item));//}//是否解析成16进制if (ReceiveIsHex){content = bytetohex(receivedData, receivedData.Length).Trim();}else{content = Encoding.Default.GetString(receivedData);}//委托传值Data(content);}catch (Exception ex){}}}/// <summary>/// 从汉字转换到16进制/// </summary>/// <param name="s"></param>/// <returns></returns>public static string GetHexFromChs(string s){if ((s.Length % 2) != 0){s += " ";//空格//throw new ArgumentException("s is not valid chinese string!");}System.Text.Encoding chs = System.Text.Encoding.GetEncoding("gb2312");byte[] bytes = chs.GetBytes(s);string str = "";for (int i = 0; i < bytes.Length; i++){str += string.Format("{0:X}", bytes[i]) + " ";}return str;}/// <summary>/// byte[]转HEXString/// </summary>/// <param name="byteArray">byte数组</param>/// <param name="lenght">长度</param>/// <returns></returns>public static string bytetohex(byte[] byteArray, int lenght){// string str = "";var str = new System.Text.StringBuilder();int start = Environment.TickCount;//计时器Console.WriteLine("wait...");for (int i = 0; i < lenght; i++){str.Append(String.Format("{0:X2} ", byteArray[i]));//var拼接}string s = str.ToString();Console.WriteLine(Math.Abs(Environment.TickCount - start));//在调试窗口可查用时return s;}/// 判断是否十六进制格式字符串/// </summary>/// <param name="str"></param>/// <returns></returns>public static bool IsHexadecimal(string str){str = str.Replace(" ", "");bool IsHex = System.Text.RegularExpressions.Regex.IsMatch(str, "^[0-9A-Fa-f]+$");return IsHex;}/// <summary>/// 16进制原码字符串转字节数组/// </summary>/// <param name="hexString">"AABBCC"或"AA BB CC"格式的字符串</param>/// <returns></returns>public static byte[] ConvertHexStringToBytes(string hexString){hexString = hexString.Replace(" ", "");if (hexString.Length % 2 != 0){throw new ArgumentException("参数长度不正确");}byte[] returnBytes = new byte[hexString.Length / 2];for (int i = 0; i < returnBytes.Length; i++){returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);}return returnBytes;}/// <summary>/// 获取文件中的数据/// </summary>/// <param name="args"></param>public static string fileToString(String filePath){StringBuilder strData = new StringBuilder("");try{string line;// 创建一个 StreamReader 的实例来读取文件 ,using 语句也能关闭 StreamReaderusing (System.IO.StreamReader sr = new System.IO.StreamReader(filePath, System.Text.Encoding.GetEncoding("gb2312"))){// 从文件读取并显示行,直到文件的末尾 while ((line = sr.ReadLine()) != null){//Console.WriteLine(line);strData.Append( line);}}}catch (Exception e){// 向用户显示出错消息Console.WriteLine("The file could not be read:");Console.WriteLine(e.Message);}return strData.ToString();}public static void WriteLog(string FileName){}}
}
源码链接
c#串口通讯详解(附源码)相关推荐
- python嗅探工具详解附源码(使用socket,带tkinter界面)
python嗅探工具详解(带tkinter界面) 点击详见原理 点击详见原理 TCP/IP协议号补充 必备基础知识 IP数据包格式 详见点此 TCP报文格式 详见点此 struct模块 在Python ...
- java反射源码_java反射技术详解附源码
在学校学习Java时,由于学的不扎实,也没经历过太多实战项目,所以很多重要的知识点瞟一眼就过去了,比如现在要讲的反射,当时直接就忽略掉了,可现在发现很多地方需要反射,不得不重新学习一下,上学欠了太多债 ...
- 【Vue 实战项目】后台管理系统登录页详解附源码
提示:前端查漏补缺,仅代表个人观点. 文章目录 一.先看效果图 二.实战步骤 1. 创建项目 2. 引入库 3. 登录页关键代码 三.页面源代码 总结 提示:项目源代码除了登录页面还有动态路由 一.先 ...
- Linux下stream内存带宽测试参数和示例详解附源码(总结)
目录 一.简介 二.使用简介 2.1 测试内容简介 2.2 编译参数简介 2.3 具体参数示例 三.源码下载及使用 四.其他相关知识链接 FIO测试硬盘性能参数和实例总结 一.简介 本文通过实例详细讲 ...
- python开发技术详解pdf下载_python开发技术详解附源码-python开发技术详解电子书pdf下载高清去水印版-精品下载...
Python开发技术详解适合Python爱好者.大中专院校的学生.社会培训班的学生以及用Python语言进行系统管理.GUI开发.Web开发.数据库编程.网络编程的人员使用. 内容提要 Python是 ...
- dom操作获取盒子宽高位置的三种方法,offset/scroll/client三大家族使用详解(附源码及注释)
结论:页面body的高度==视口的高度+滚动条滚动的距离. 这是一个恒等式,看完本篇博客,你将了解offset/scroll/clent三大事件获取宽高位置的具体含义,运用所学内容可以推导出这样的恒等 ...
- C# OpenCV EmguCV实现扫描文本图像倾斜矫正 实现详解(附源码)
一.扫描文本倾斜矫正 实现步骤可以参考如下链接: https://blog.csdn.net/stq054188/article/details/120031667?spm=1001.2014.300 ...
- 「兔了个兔」CSS如此之美,看我如何实现可爱兔兔LOADING页面(万字详解附源码)
- 小程序获取城市行政区号_微信小程序 省市区选择器实例详解(附源码下载)
微信小程序 省市区选择器: 最近学习微信小程序,为了检验自己的学习效果,自己做一个小示例,网上搜索下类似的实例,发现这个更好,大家看下. 一.区域间手势滑动切换,标题栏高亮随之切换 思路是:拿当前的c ...
最新文章
- 智能车竞赛技术报告 | 双车接力组 - 辽宁工业大学 - 灵越1队
- 科学家们竟用乐高观察细胞,网友:万万没想到啊
- ubuntu设置自启动服务程序
- Python3爬虫之中文乱码问题分析与解决方法
- qt 串口发送char 数组乱码_串口的波特相差多大会误码
- java细节_java细节知识
- install and use zookeeper C client API
- 爱立顺m33+android+4.4.2,更美丽更流畅 爱立顺M33升级Android 4.4.2
- PS笔记:调色之通道混合器
- 3d vision可以卸载吗_3D Vision是什么
- Android虚拟机、模拟器识别
- Source Insight工程导入
- Adobe Dreamweaver CS5 简体中文绿色版
- 利用python进行单边T检验
- python 外星人游戏怎么打开_Python外星人入侵游戏开发—创建游戏窗口
- 大数据技术有哪些,为什么说云计算能力是大数据的根本!
- ese如何实现支付 nfc_意法半导体David Renno:eSE融合NFC、eSIM、 TEE的安全移动支付方案...
- 因误删文件导致CentOS7开机卡死无法进入图形登录界面
- 机器人底盘的主要三大技术
- 土壤C、N动态对大气臭氧污染的生态学响应