1、c#上位机串口通信助手源代码实例详解 一、 功能 1 软件打开时,自动检测有效 COM端口 2 软件打开时,自动复原到上次关闭时的状态 3 丌必关闭串口,即可直接进行更改初始化设置内容(串口号、波特率、数据位、停止位、校验位),可按更改后的信息自动将串口重新打开 4 可统计接收字节和发送字节的个数 5 接收数据可按 16进制数据和非 16进制数据进行整体转换 6 可将接收到数据进行保存 7 可设置自动发送,发送时间可进行实时更改 8 可按字符串、 16进制字节、文件方式进行发送,字符串和 16进制字节可分别进行存储,内容互丌干扰 9 按 16进制发送时,可自动校验格式,丌会输错 10 可清空发
2、送或接收区域的数据 二、 使用工具 Visual Studio2015 三、 程序详解 1 界面创建 图 1 用 winform 创建如图 1 所示界面,控件名字分别为: 端口号: cbxCOMPort 波特率: cbxBaudRate 数据位: cbxDataBits 停止位: cbxStopBits 校验位: label5 打开串口按钮: btnOpenCom 发送( byte): tbSendCount 接收( byte): tbReceivedCount 清空计数按钮: btnClearCount 按 16进制显示: cb16Display 接收区清空内容按钮: btnClearRec
3、eived 保存数据按钮: btnSaveFile 接收数据框: tbReceivedData 发送数据框: tbSendData 自动发送: cbAutomaticSend 间隔时间: tbSpaceTime 按 16进制发送: cb16Send 发送区清空内容按钮: btnClearSend 读入文件按钮: btnReadFile 发送按钮: btnSend 2 创建一个方法类 按 Ctrl+shift+A快捷键创建一个类,名字叫 Methods,代码为: using System; using System.Collections; using System.Collections.Ge
4、neric; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 串口助手 sdd class Methods /获取有效的 COM口 public static string ActivePorts() ArrayList activePorts = new ArrayList(); foreach (string pname in SerialPort.GetPortNames() activePorts.Add(Convert.ToInt3
5、2(pname.Substring(3); activePorts.Sort(); string mystr = new stringactivePorts.Count; int i = 0; foreach (int num in activePorts) mystri+ = “COM“ + num.ToString(); return mystr; /16进制字符串转换为 byte字符数组 public static Byte _16strToHex(string strValues) string hexValuesSplit = strValues.Split( ); Byte hex
6、Values = new BytehexValuesSplit.Length; Console.WriteLine(hexValuesSplit.Length); for (int i = 0; i receivedDatas = new List();/接收数据泛型数组 /接收串口数据 private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e) byte ReceivedData = new bytesp.BytesToRead;/创建接收字节数组 sp.Read(ReceivedData, 0, Re
7、ceivedData.Length);/读取所接收到的数据 receivedDatas.AddRange(ReceivedData); tbReceivedCount.Text = (Convert.ToInt32(tbReceivedCount.Text) + ReceivedData.Length).ToString(); if (cb16Display.Checked) tbReceivedData.Text = Methods.ByteTo16Str(receivedDatas.ToArray(); else tbReceivedData.Text = Encoding.Default
8、.GetString(receivedDatas.ToArray(); sp.DiscardInBuffer();/丢弃接收缓冲区数据 /发送串口数据 private void DataSend() try if (cb16Send.Checked) byte hexBytes = Methods._16strToHex(tbSendData16); sp.Write(hexBytes, 0, hexBytes.Length); tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + hexBytes.Length).ToString()
9、; else sp.WriteLine(tbSendDataStr); tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + tbSendDataStr.Length).ToString(); catch (Exception ex) MessageBox.Show(ex.Message.ToString(); return; /设置串口属性 private void SetPortProperty() sp.PortName = cbxCOMPort.Text.Trim();/设置串口名 sp.BaudRate = Convert.T
10、oInt32(cbxBaudRate.Text.Trim();/设置波特率 switch (cbxStopBits.Text.Trim()/设置停止位 case “1“: sp.StopBits = StopBits.One; break; case “1.5“: sp.StopBits = StopBits.OnePointFive; break; case “2“: sp.StopBits = StopBits.Two; break; default: sp.StopBits = StopBits.None; break; sp.DataBits = Convert.ToInt32(cbx
11、DataBits.Text.Trim();/设置数据位 switch (cbxParity.Text.Trim()/设置奇偶校验位 case “无 “: sp.Parity = Parity.None; break; case “奇校验 “: sp.Parity = Parity.Odd; break; case “偶校验 “: sp.Parity = Parity.Even; break; default: sp.Parity = Parity.None; break; sp.ReadTimeout = 5000;/设置超时时间为 5s Control.CheckForIllegalCros
12、sThreadCalls = false;/这个类中我们丌检查跨线程的调用是否合法 (因为 .net 2.0以后加强了安全机制 ,,丌允许在 winform中直接跨线程访问控件的属性 ) /定义 DataReceived事件的委托,当串口收到数据后出发事件 sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived); /设置端口显示状态 private void DisplayPortState(PortState portState) toolStripStatusLabel1.Text = cbxCOMPor
13、t.Text + “端口 处亍 “ + portState + “状态 “ + cbxBaudRate.Text + “ “ + cbxDataBits.Text + “ “ + cbxStopBits.Text + “ “ + cbxParity.Text; /重新打开串口 private void AgainOpenPort() if (sp.IsOpen) try sp.Close(); SetPortProperty(); isSetProperty = true; sp.Open(); catch (Exception) isSetProperty = false; btnOpenC
14、om.Text = “打开串口 “; DisplayPortState(PortState.关闭 ); MessageBox.Show(“串口无效或已被占用 !“, “错误提示 “); return; DisplayPortState(PortState.打开 ); else DisplayPortState(PortState.关闭 ); public Form1() InitializeComponent(); /软件启动时加载事件 private void Form1_Load(object sender, EventArgs e) #region 加载配置文件 Hashtable ht
15、 = new Hashtable(); if (File.Exists(path) try string myline = “; string str = new string2; using (StreamReader sr = new StreamReader(path) myline = sr.ReadLine(); while (myline != null) str = myline.Split(=); ht.Add(str0, str1); myline = sr.ReadLine(); catch(Exception ex) MessageBox.Show(ex.Message.
16、ToString(); #endregion #region 设置窗口为固定大小且丌可最大化 this.MaximumSize = this.Size; this.MinimumSize = this.Size; this.MaximizeBox = false; #endregion #region 列出常用的波特率 cbxBaudRate.Items.Add(“1200“); cbxBaudRate.Items.Add(“2400“); cbxBaudRate.Items.Add(“4800“); cbxBaudRate.Items.Add(“9600“); cbxBaudRate.Ite
17、ms.Add(“19200“); cbxBaudRate.Items.Add(“38400“); cbxBaudRate.Items.Add(“43000“); cbxBaudRate.Items.Add(“56000“); cbxBaudRate.Items.Add(“57600“); cbxBaudRate.Items.Add(“115200“); if (ht.ContainsKey(“cbxBaudRate“) cbxBaudRate.SelectedIndex = cbxBaudRate.Items.IndexOf(ht“cbxBaudRate“.ToString(); else c
18、bxBaudRate.SelectedIndex = 3; cbxBaudRate.DropDownStyle = ComboBoxStyle.DropDownList; #endregion #region 列出停止位 cbxStopBits.Items.Add(“1“); cbxStopBits.Items.Add(“1.5“); cbxStopBits.Items.Add(“2“); if (ht.ContainsKey(“cbxStopBits“) cbxStopBits.SelectedIndex = cbxStopBits.Items.IndexOf(ht“cbxStopBits“
19、.ToString(); else cbxStopBits.SelectedIndex = 0; cbxStopBits.DropDownStyle = ComboBoxStyle.DropDownList; #endregion #region 列出数据位 cbxDataBits.Items.Add(“8“); cbxDataBits.Items.Add(“7“); cbxDataBits.Items.Add(“6“); cbxDataBits.Items.Add(“5“); if (ht.ContainsKey(“cbxDataBits“) cbxDataBits.SelectedInde
20、x = cbxDataBits.Items.IndexOf(ht“cbxDataBits“.ToString(); else cbxDataBits.SelectedIndex = 0; cbxDataBits.DropDownStyle = ComboBoxStyle.DropDownList; #endregion #region 列出奇偶校验位 cbxParity.Items.Add(“无 “); cbxParity.Items.Add(“奇校验 “); cbxParity.Items.Add(“偶校验 “); if (ht.ContainsKey(“cbxParity“) cbxPar
21、ity.SelectedIndex = cbxParity.Items.IndexOf(ht“cbxParity“.ToString(); else cbxParity.SelectedIndex = 0; cbxParity.DropDownStyle = ComboBoxStyle.DropDownList; #endregion #region COM口重新加载 cbxCOMPort.Items.Clear();/清除当前串口号中的所有串口名称 cbxCOMPort.Items.AddRange(Methods.ActivePorts(); if (ht.ContainsKey(“cbx
22、COMPort“) else cbxCOMPort.SelectedIndex = 0; cbxCOMPort.DropDownStyle = ComboBoxStyle.DropDownList; #endregion #region 初始化计数器 tbSendCount.Text = “0“; tbSendCount.ReadOnly = true; tbReceivedCount.Text = “0“; tbReceivedCount.ReadOnly = true; #endregion #region 初始化当前时间 toolStripStatusLabel3.Text = Date
23、Time.Now.ToString(); #endregion #region 初始化串口状态 toolStripStatusLabel1.ForeColor = Color.Blue; if (!isSetProperty)/串口未设置则设置串口属性 SetPortProperty(); isSetProperty = true; try sp.Open(); btnOpenCom.Text = “关闭串口 “; DisplayPortState(PortState.打开 ); catch (Exception) /串口打开失败后,串口属性设置标志位设为 false isSetPropert
24、y = false; MessageBox.Show(“串口无效或已被占用 !“, “错误提示 “); #endregion #region 初始化间隔时间 if (ht.ContainsKey(“tbSpaceTime“) tbSpaceTime.Text = ht“tbSpaceTime“.ToString(); else tbSpaceTime.Text = “1000“; #endregion #region 初始化按 16进制显示状态 if (ht.ContainsKey(“cb16Display“) else cb16Display.Checked = false; #endreg
25、ion #region 初始化按 16进制发送状态 if (ht.ContainsKey(“cb16Send“) else cb16Send.Checked = false; #endregion #region 初始化发送区文本 if(ht.ContainsKey(“tbSendData16“) tbSendDataStr = ht“tbSendDataStr“.ToString(); if (cb16Send.Checked) tbSendData.Text = ht“tbSendData16“.ToString(); else tbSendData.Text = ht“tbSendDat
26、aStr“.ToString(); #endregion tbSendData.Focus(); /显示当前时间 private void timer1_Tick(object sender, EventArgs e) toolStripStatusLabel3.Text = DateTime.Now.ToString(); /点击打开串口按钮 private void btnOpenCom_Click(object sender, EventArgs e) if (!sp.IsOpen)/串口没有打开时 if (!isSetProperty)/串口未设置则设置串口属性 SetPortProperty();