故事背景:公司生產線上新購一臺機臺(本來有兩臺同型號的老機器),結果本來的用VB寫的測試電壓的程序在新機器上沒法使用,讀取不到電腦COM口上機臺返回的數據;最鬱悶的是電話問廠商人家說新的機器沒有改變什麼(最坑的就是這句話了),只是比老機器效率高點,而後就沒了,沒辦法,已經付過錢了,人家吊的不行。萬般無奈之下,只有本身找緣由了;因而乎,上網找各類資料,本身寫了一個Winform的測試COM通訊的程序,寫完後結果和VB程序 同樣的問題,讀取不到COM口數據,通過兩天的研究終於搞定了,緣由是新設備中的通訊協議中的握手協議改了。廢話很少說,上圖片和代碼:ide
1.Winform界面以下:測試
其中:波特率的的Items包括spa
300
600
1200
2400
4800
9600
19200
38400
43000
56000
57600
115200code
數據位的Items有:orm
1
2
4
8blog
中止位的Items有:圖片
1
1.5
2ip
校驗位的Items有:string
無
奇校驗
偶校驗it
備註:界面上的toolStrip能夠改成StatusStrip更好些,發送數據的兩個RadioButton的名字能夠改下(由於這個是在度娘裏找的,懶的改代碼裏的名字,因此我也就沒改)
2.上代碼(已運行過的代碼,可直接使用;因爲我只要測試COM的通訊,因此定製發送數據和保存設置的功能沒寫,可根據需求自行添加)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO.Ports; namespace TestCOM { public partial class Form1 : Form { SerialPort sp1 = new SerialPort(); public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; sp1.DataReceived+=new SerialDataReceivedEventHandler(sp1_DataReceived); string[] str = SerialPort.GetPortNames(); if (str == null) { MessageBox.Show("本機沒有串口!", "Error"); return; } //添加串口項目 foreach (string s in System.IO.Ports.SerialPort.GetPortNames()) {//獲取有多少個COM口 cbSerial.Items.Add(s); } //串口設置默認選擇項 cbSerial.SelectedIndex = 0; //設置cbSerial的默認選項 cbBaudRate.SelectedIndex = 5; cbDataBits.SelectedIndex = 3; cbStop.SelectedIndex = 0; cbParity.SelectedIndex = 0; radio2.Checked = true; //發送數據的「16進制」單選按鈕 rbRcvStr.Checked = true; } private void btnSwitch_Click(object sender, EventArgs e) { if (!sp1.IsOpen) { try { string serialName = cbSerial.SelectedItem.ToString(); sp1.PortName = serialName; string strBaudRate = cbBaudRate.Text; string strDateBits = cbDataBits.Text; string strStopBits = cbStop.Text; Int32 iBaudRate = Convert.ToInt32(strBaudRate); Int32 iDateBits = Convert.ToInt32(strDateBits); sp1.BaudRate = iBaudRate; sp1.DataBits = iDateBits; switch (cbStop.Text) { case "1": sp1.StopBits = StopBits.One; break; case "1.5": sp1.StopBits = StopBits.OnePointFive; break; case "2": sp1.StopBits = StopBits.Two; break; default: MessageBox.Show("Error:參數不正確!", "Error"); break; } switch (cbParity.Text) { case "無": sp1.Parity = Parity.None; break; case "奇校驗": sp1.Parity = Parity.Odd; break; case "偶校驗": sp1.Parity = Parity.Even; break; default: MessageBox.Show("Error:參數不正確!", "Error"); break; } //sp1.ReceivedBytesThreshold = 1; //sp1.Handshake = Handshake.RequestToSend;//握手協議:RTS硬件流控制 //我遇到的問題就是這裏的問題,Handshake默認是None,可是有些設備的Handshake可能就不是這個,因此要根據鏈接的設備而定;若是是用跳線測試電腦COM通訊的話這裏就用默認的,改爲RTS的話是不行的 if (sp1.IsOpen == true) { sp1.Close(); } //狀態欄設置 tsSpNUM.Text = "串口號:" + sp1.PortName + "|"; tsBaudRate.Text = "波特率:" + sp1.BaudRate + "|"; tsDataBits.Text = "數據位:" + sp1.DataBits + "|"; tsStopBits.Text = "中止位:" + sp1.StopBits + "|"; tsParity.Text = "校驗位:" + sp1.Parity + "|"; cbSerial.Enabled = false; cbBaudRate.Enabled = false; cbDataBits.Enabled = false; cbStop.Enabled = false; cbParity.Enabled = false; sp1.Open(); btnSwitch.Text = "關閉串口"; } catch (Exception ex) { MessageBox.Show("Error:" + ex.Message + "Error"); return; } } else { tsSpNUM.Text = "串口號:未指定|"; tsBaudRate.Text = "波特率:未指定|"; tsDataBits.Text = "數據位:未指定|"; tsStopBits.Text = "中止位:未指定|"; tsParity.Text = "校驗位:未指定|"; cbSerial.Enabled = true; cbBaudRate.Enabled = true; cbDataBits.Enabled = true; cbStop.Enabled = true; cbParity.Enabled = true; sp1.Close(); btnSwitch.Text = "打開串口"; } } private void btnSend_Click(object sender, EventArgs e) { if (!sp1.IsOpen) { MessageBox.Show("請先打開串口", "Error"); return; } string strSend = txtSend.Text; if (radio1.Checked == true) { string sendBuf = strSend; string sendnoNull = sendBuf.Trim(); string sendNOComma = sendnoNull.Replace(',', ' '); string sendNOComma1 = sendNOComma.Replace(',', ' '); string strSendNoComma2 = sendNOComma1.Replace("0x", ""); strSendNoComma2.Replace("0X", ""); string[] strArray = strSendNoComma2.Split(' '); int byteBufferLength = strArray.Length; for (int i = 0; i < strArray.Length; i++) { if (strArray[i] == "") { byteBufferLength--; } } byte[] byteBuffer = new byte[byteBufferLength]; int ii = 0; for (int i = 0; i < strArray.Length; i++) { Byte[] bytesOfStr = Encoding.Default.GetBytes(strArray[i]); int decNum = 0; if (strArray[i] == "") { continue; } else { decNum = Convert.ToInt32(strArray[i],16); } try { byteBuffer[ii] = Convert.ToByte(decNum); } catch (Exception) { MessageBox.Show("字節越界,請逐個字節輸入!","Error"); return; } ii++; } sp1.Write(byteBuffer,0,byteBuffer.Length); } else { sp1.WriteLine(txtSend.Text); } } private void sp1_DataReceived(object sender, SerialDataReceivedEventArgs e) { if (sp1.IsOpen) { byte[] byteRead = new byte[sp1.BytesToRead]; if (rbRcvStr.Checked) { txtRcv.Text += sp1.ReadLine() + "\r\n"; sp1.DiscardInBuffer(); } else { try { Byte[] receivedData = new Byte[sp1.BytesToRead]; sp1.Read(receivedData, 0, receivedData.Length); sp1.DiscardInBuffer(); string strRcv = null; for (int i = 0; i < receivedData.Length; i++) { strRcv += receivedData[i].ToString("X2"); } txtRcv.Text += strRcv + "\r\n"; } catch (Exception ex) { MessageBox.Show(ex.Message,"出錯提示"); txtSend.Text = ""; } } } else { MessageBox.Show("請打開某個串口","錯誤提示"); } } private void btnClear_Click(object sender, EventArgs e) { txtRcv.Text = string.Empty; } private void btnExit_Click(object sender, EventArgs e) { Application.Exit(); } } }
備註:我處理的這個機臺的Handshake的方式就是RTS,可是應該有不少設備的Handshake是None的(默認的),因此要根據具體的設備(設備的說明書上應該有說的)。