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接收区清空内容按钮:btnClearReceived 保存数据按钮:btnSaveFile接收数
3、据框:tbReceivedData 发送数据框:tbSendData自动发送:cbAutomaticSend 间隔时间:tbSpaceTime按 16 进制发送: cb16Send 发送区清空内容按钮:btnClearSend读入文件按钮:btnReadFile 发送按钮:btnSend2 创建一个方法类按 Ctrl+shift+A 快捷键创建一个类,名字叫 Methods,代码为:using System;using System.Collections;using System.Collections.Generic;using System.IO.Ports;using System.L
4、inq;using System.Text;using System.Threading.Tasks;namespace 串口助手sddclass Methods/获取有效的COM口public static string ActivePorts()ArrayList activePorts = new ArrayList();foreach (string pname in SerialPort.GetPortNames()activePorts.Add(Convert.ToInt32(pname.Substring(3);activePorts.Sort();string mystr =
5、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 hexValues = new BytehexValuesSplit.Length;Console.WriteLine(hexValues
6、Split.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, ReceivedData.Length);/读取所接收到的数据receivedDatas.AddRange(ReceivedData);tbRece
7、ivedCount.Text = (Convert.ToInt32(tbReceivedCount.Text) + ReceivedData.Length).ToString();if (cb16Display.Checked)tbReceivedData.Text = Methods.ByteTo16Str(receivedDatas.ToArray();elsetbReceivedData.Text = Encoding.Default.GetString(receivedDatas.ToArray();sp.DiscardInBuffer();/丢弃接收缓冲区数据/发送串口数据priva
8、te void DataSend()tryif (cb16Send.Checked)byte hexBytes = Methods._16strToHex(tbSendData16);sp.Write(hexBytes, 0, hexBytes.Length);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text) + hexBytes.Length).ToString();elsesp.WriteLine(tbSendDataStr);tbSendCount.Text = (Convert.ToInt32(tbSendCount.Text)
9、 + tbSendDataStr.Length).ToString();catch (Exception ex)MessageBox.Show(ex.Message.ToString();return;/设置串口属性private void SetPortProperty()sp.PortName = cbxCOMPort.Text.Trim();/设置串口名sp.BaudRate = Convert.ToInt32(cbxBaudRate.Text.Trim();/设置波特率switch (cbxStopBits.Text.Trim()/设置停止位case “1“: sp.StopBits
10、= 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(cbxDataBits.Text.Trim();/设置数据位switch (cbxParity.Text.Trim()/设置奇偶校验位 case “无“: sp.Parity = Parity.None; br
11、eak;case “奇校验“: sp.Parity = Parity.Odd; break;case “偶校验“: sp.Parity = Parity.Even; break;default: sp.Parity = Parity.None; break;sp.ReadTimeout = 5000;/设置超时时间为5sControl.CheckForIllegalCrossThreadCalls = false;/这个类中我们不检查跨线程的调用是否合法(因为.net 2.0以后加强了安全机制,,不允许在winform中直接跨线程访问控件的属性)/定义DataReceived事件的委托,当串口
12、收到数据后出发事件sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);/设置端口显示状态private void DisplayPortState(PortState portState)toolStripStatusLabel1.Text = cbxCOMPort.Text + “端口 处于“ + portState + “状态 “ + cbxBaudRate.Text + “ “ + cbxDataBits.Text + “ “ + cbxStopBits.Text + “ “ + cbxParity
13、.Text;/重新打开串口private void AgainOpenPort()if (sp.IsOpen)trysp.Close();SetPortProperty();isSetProperty = true;sp.Open();catch (Exception)isSetProperty = false;btnOpenCom.Text = “打开串口“;DisplayPortState(PortState.关闭);MessageBox.Show(“串口无效或已被占用!“, “错误提示“);return;DisplayPortState(PortState.打开);elseDisplay
14、PortState(PortState.关闭);public Form1()InitializeComponent();/软件启动时加载事件private void Form1_Load(object sender, EventArgs e)#region 加载配置文件Hashtable ht = new Hashtable();if (File.Exists(path)trystring myline = “;string str = new string2;using (StreamReader sr = new StreamReader(path)myline = sr.ReadLine
15、();while (myline != null)str = myline.Split(=);ht.Add(str0, str1);myline = sr.ReadLine();catch(Exception ex)MessageBox.Show(ex.Message.ToString();#endregion#region 设置窗口为固定大小且不可最大化this.MaximumSize = this.Size;this.MinimumSize = this.Size;this.MaximizeBox = false;#endregion#region 列出常用的波特率cbxBaudRate.
16、Items.Add(“1200“);cbxBaudRate.Items.Add(“2400“);cbxBaudRate.Items.Add(“4800“);cbxBaudRate.Items.Add(“9600“);cbxBaudRate.Items.Add(“19200“);cbxBaudRate.Items.Add(“38400“);cbxBaudRate.Items.Add(“43000“);cbxBaudRate.Items.Add(“56000“);cbxBaudRate.Items.Add(“57600“);cbxBaudRate.Items.Add(“115200“);if (h
17、t.ContainsKey(“cbxBaudRate“)cbxBaudRate.SelectedIndex = cbxBaudRate.Items.IndexOf(ht“cbxBaudRate“.ToString();elsecbxBaudRate.SelectedIndex = 3;cbxBaudRate.DropDownStyle = ComboBoxStyle.DropDownList;#endregion#region 列出停止位cbxStopBits.Items.Add(“1“);cbxStopBits.Items.Add(“1.5“);cbxStopBits.Items.Add(“
18、2“);if (ht.ContainsKey(“cbxStopBits“)cbxStopBits.SelectedIndex = cbxStopBits.Items.IndexOf(ht“cbxStopBits“.ToString();elsecbxStopBits.SelectedIndex = 0;cbxStopBits.DropDownStyle = ComboBoxStyle.DropDownList;#endregion#region 列出数据位cbxDataBits.Items.Add(“8“);cbxDataBits.Items.Add(“7“);cbxDataBits.Item
19、s.Add(“6“);cbxDataBits.Items.Add(“5“);if (ht.ContainsKey(“cbxDataBits“)cbxDataBits.SelectedIndex = cbxDataBits.Items.IndexOf(ht“cbxDataBits“.ToString();elsecbxDataBits.SelectedIndex = 0;cbxDataBits.DropDownStyle = ComboBoxStyle.DropDownList;#endregion#region 列出奇偶校验位cbxParity.Items.Add(“无“);cbxParity
20、.Items.Add(“奇校验“);cbxParity.Items.Add(“偶校验“);if (ht.ContainsKey(“cbxParity“)cbxParity.SelectedIndex = cbxParity.Items.IndexOf(ht“cbxParity“.ToString();elsecbxParity.SelectedIndex = 0;cbxParity.DropDownStyle = ComboBoxStyle.DropDownList;#endregion#region COM口重新加载cbxCOMPort.Items.Clear();/清除当前串口号中的所有串
21、口名称cbxCOMPort.Items.AddRange(Methods.ActivePorts();if (ht.ContainsKey(“cbxCOMPort“) elsecbxCOMPort.SelectedIndex = 0;cbxCOMPort.DropDownStyle = ComboBoxStyle.DropDownList;#endregion#region 初始化计数器tbSendCount.Text = “0“;tbSendCount.ReadOnly = true;tbReceivedCount.Text = “0“;tbReceivedCount.ReadOnly =
22、true;#endregion#region 初始化当前时间toolStripStatusLabel3.Text = DateTime.Now.ToString();#endregion#region 初始化串口状态toolStripStatusLabel1.ForeColor = Color.Blue;if (!isSetProperty)/串口未设置则设置串口属性SetPortProperty();isSetProperty = true;trysp.Open();btnOpenCom.Text = “关闭串口“;DisplayPortState(PortState.打开);catch (
23、Exception)/串口打开失败后,串口属性设置标志位设为falseisSetProperty = false;MessageBox.Show(“串口无效或已被占用!“, “错误提示“);#endregion#region 初始化间隔时间if (ht.ContainsKey(“tbSpaceTime“)tbSpaceTime.Text = ht“tbSpaceTime“.ToString();elsetbSpaceTime.Text = “1000“;#endregion#region 初始化按16进制显示状态if (ht.ContainsKey(“cb16Display“) elsecb1
24、6Display.Checked = false;#endregion#region 初始化按16进制发送状态if (ht.ContainsKey(“cb16Send“) elsecb16Send.Checked = false;#endregion#region 初始化发送区文本if(ht.ContainsKey(“tbSendData16“) tbSendDataStr = ht“tbSendDataStr“.ToString();if (cb16Send.Checked)tbSendData.Text = ht“tbSendData16“.ToString();elsetbSendDat
25、a.Text = ht“tbSendDataStr“.ToString();#endregiontbSendData.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();