軟體功能: 使用C#實現PC串口通訊 支持定時發送 支持16進位(hex) ASCII UTF-8 Unicode 四種編碼格式 支持配置文件的保存和讀取 可以可以顯示發送歷史 可以統計總的發送位元組數和接受位元組數 軟體界面: C#源碼: using System; using System.Coll ...
軟體功能:
使用C#實現PC串口通訊
支持定時發送
支持16進位(hex) ASCII UTF-8 Unicode 四種編碼格式
支持配置文件的保存和讀取
可以可以顯示發送歷史
可以統計總的發送位元組數和接受位元組數
軟體界面:
C#源碼:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.IO.Ports; using System.Threading; using System.IO; using System.Xml.Serialization; namespace 串口調試工具 { public partial class Form1 : Form { private SerialPort sp = new SerialPort();//鏈接對象 Config config = new Config();//配置文件 public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //獲取串口列表 string[] comList = SerialPort.GetPortNames(); if (comList.Length == 0) { MessageBox.Show("無可用串口"); return; } foreach (var com in comList) { cmbComList.Items.Add(com); } //添加波特率 int[] baudRate = { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 43000, 56000, 57600, 115200 }; foreach (var br in baudRate) { cmbBautRade.Items.Add(br); } //添加數據位 int[] dataBits = { 8, 7, 6, 5 }; foreach (var db in dataBits) { cmbDataBits.Items.Add(db); } //添加停止位 int[] stopBits = { 1, 2, 3 }; foreach (var sb in stopBits) { cmbStopBits.Items.Add(sb); } //添加檢驗方式 string[] parity = { "None", "Even", "Mark", "Odd", "Space" }; foreach (var p in parity) { cmbParity.Items.Add(p); } //添加常用編碼 string[] encode = { "ASCII","UTF-8","Unicode","Hex"}; foreach (var en in encode) { cmbEncodeSend.Items.Add(en); cmbEncodeRec.Items.Add(en); } //載入配置文件 LoadConfig(); } private void LoadConfig() { //把配置信息賦值給控制項預設值 cmbComList.SelectedItem = config.PortName; if (cmbComList.SelectedIndex == -1) cmbComList.SelectedIndex = 0; cmbBautRade.SelectedItem = config.BautRade; cmbDataBits.SelectedItem = config.DataBits; cmbStopBits.SelectedItem = config.StopBits; cmbParity.SelectedItem = config.Parity; cmbEncodeRec.SelectedItem = config.EncodeRec; cmbEncodeSend.SelectedItem = config.EncodeSend; //激活打開按鈕 this.btnOpen.Enabled = true; } private void btnOpen_Click(object sender, EventArgs e) { if (((Button)sender).Text == "打開串口") { //賦值給串口 sp.PortName = cmbComList.SelectedItem.ToString(); sp.Parity=(Parity)Enum.Parse(typeof(Parity),cmbParity.SelectedItem.ToString()); sp.BaudRate = Convert.ToInt32(cmbBautRade.SelectedItem.ToString()); sp.StopBits = (StopBits)Convert.ToInt32(cmbStopBits.SelectedItem.ToString()); sp.DataBits = Convert.ToInt32(cmbDataBits.SelectedItem.ToString()); try { sp.Open(); //修改控制項狀態 this.btnOpen.Text = "關閉串口"; foreach (Control ctr in groupBox1.Controls) { //把下拉框全部禁用 ctr.Enabled = false; } //開啟新線程,監聽收取內容 Thread thread = new Thread(receive); thread.Start(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } else { if (this.btnAutoSend.Text == "停止發送") { MessageBox.Show("當前定時發送中,請先停止定時發送任務."); return; } sp.Close(); //修改控制項狀態 this.btnOpen.Text = "打開串口"; foreach (Control ctr in this.groupBox1.Controls) { ctr.Enabled = true; } } } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { //窗體關閉時關閉埠 sp.Close(); } private void btnSend_Click(object sender, EventArgs e) { Send(); } private void btnAutoSend_Click(object sender, EventArgs e) { if (this.btnAutoSend.Text == "定時發送") { //根據打開按鈕狀態初步檢查埠是否已經打開 if (this.btnOpen.Text == "打開串口") return; System.Text.RegularExpressions.Regex reg1 = new System.Text.RegularExpressions.Regex(@"^[0-9]\d*$"); if (reg1.IsMatch(txtTime.Text.ToString())) { //激活Timer定時器 this.timer1.Interval = Convert.ToInt32(txtTime.Text.ToString()); this.timer1.Start(); //修改控制項狀態 this.btnAutoSend.Text = "停止發送"; this.btnSend.Enabled = false; } else { MessageBox.Show("發送間隔應為正整數"); txtTime.Text = "1000"; } } else { this.btnAutoSend.Text = "定時發送"; this.btnSend.Enabled = true; this.timer1.Stop(); } } private void Send() { if (sp.IsOpen) { //獲取位元組 byte[] buffer = Encode(); if (buffer.Length == 0) return; try { sp.Write(buffer, 0, buffer.Length); } catch (Exception ex) { MessageBox.Show(ex.Message); } //添加發送歷史 this.txtHistory.AppendText(string.Format("[{0}] {1} \r\n", DateTime.Now.ToString("HH:mm:ss.ff"), txtSend.Text)); //統計發送位元組 this.labSendCount.Text = (Convert.ToInt32(labSendCount.Text) + buffer.Length).ToString(); } else { this.timer1.Stop(); MessageBox.Show("串口尚未打開"); this.btnAutoSend.Text = "定時發送"; } } private void timer1_Tick(object sender, EventArgs e) { //定時發送 Send(); } //位元組反編碼 private byte[] Encode() { byte[] buffer = null; switch (this.cmbEncodeSend.SelectedItem.ToString()) { case "Unicode": buffer = Encoding.Unicode.GetBytes(txtSend.Text); break; case "UTF-8": buffer = Encoding.UTF8.GetBytes(txtSend.Text); break; case "ASCII": buffer = Encoding.ASCII.GetBytes(txtSend.Text); break; case "Hex": buffer = strToToHexByte(txtSend.Text); break; } return buffer; } //編碼 private string UnEncode(byte[] buffer) { string str = string.Empty; switch (this.cmbEncodeSend.SelectedItem.ToString()) { case "Unicode": str = new UnicodeEncoding().GetString(buffer); break; case "UTF-8": str = new UTF8Encoding().GetString(buffer); break; case "ASCII": str = new ASCIIEncoding().GetString(buffer); break; case "Hex": str = byteToHexStr(buffer); break; } return str; } /// <summary> /// 位元組數組轉16進位字元串 /// </summary> /// <param name="bytes"></param> /// <returns></returns> public static string byteToHexStr(byte[] bytes) { string returnStr = ""; if (bytes != null) { for (int i = 0; i < bytes.Length; i++) { returnStr += bytes[i].ToString("X2"); } } return returnStr; } /// <summary> /// 字元串轉16進位位元組數組 /// </summary> /// <param name="hexString"></param> /// <returns></returns> private static byte[] strToToHexByte(string hexString) { hexString = hexString.Replace(" ", ""); if ((hexString.Length % 2) != 0) hexString += " "; 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; } private void receive() { //接收信息 先判斷是否為打開狀態 while (sp.IsOpen) { if (sp.BytesToRead == 0) continue; //準備接收 byte[] buffer = new byte[sp.BytesToRead]; try { //接受動作 sp.Read(buffer, 0, buffer.Length); } catch (Exception ex) { MessageBox.Show(ex.Message); } //更新UI信息 this.Invoke((Action)delegate { this.txtRec.AppendText(UnEncode(buffer)); //是否自動換行 if(cbLine.Checked) this.txtRec.AppendText("\r\n"); //接收統計信息 this.labRecCount.Text = (Convert.ToInt32(this.labRecCount.Text) + buffer.Length).ToString(); }); } } private void button1_Click(object sender, EventArgs e) { //清空發送歷史 this.txtHistory.Clear(); } private void button2_Click(object sender, EventArgs e) { //清空接收 this.txtRec.Clear(); } private void btnLoad_Click(object sender, EventArgs e) { //讀取xml文件 序列化對象 OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "XML(*.xml)|"; if (ofd.ShowDialog() == DialogResult.OK) { string filePath = ofd.FileName; if (File.Exists(filePath)) { try { var mySerializer = new XmlSerializer(typeof(Config)); using (var sr = new StreamReader(new FileStream(filePath, FileMode.Open, FileAccess.Read))) { config = (Config)mySerializer.Deserialize(sr); } LoadConfig(); } catch (Exception ee) { MessageBox.Show(ee.Message); } } else { MessageBox.Show("文件不存在"); } } } private void btnSave_Click(object sender, EventArgs e) { FolderBrowserDialog fbd = new FolderBrowserDialog(); if (fbd.ShowDialog() == DialogResult.OK) { //給對象賦值並序列化保存 config.PortName = cmbComList.SelectedItem.ToString(); config.Parity = cmbParity.SelectedItem.ToString(); config.BautRade = Convert.ToInt32(cmbBautRade.SelectedItem.ToString()); config.StopBits = Convert.ToInt32(cmbStopBits.SelectedItem.ToString()); config.DataBits = Convert.ToInt32(cmbDataBits.SelectedItem.ToString()); XmlSerializer xmlFormat=new XmlSerializer(typeof(Config)); string filePath = fbd.SelectedPath + "\\PortConfig.xml"; using (Stream stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None)) { xmlFormat.Serialize(stream, config); } MessageBox.Show("成功保存到路徑:"+filePath); } } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { System.Diagnostics.Process.Start("http://www.chengchenxu.com"); } } }
軟體下載:
源碼工程文件:
虛擬埠軟體下載:
未實現的功能:
16進位校驗功能,即發送16進位格式的時候檢查輸入值是否為正確的16進位數字
接受文件的完整性校驗功能,有時候一條信息會分兩次接受完整
本文為博主原創,轉載請保留出處:
http://www.chengchenxu.com/Article/30/