python c#上位機_C#上位機之—WinForm實現序列埠通訊範例

上位機開發常用到序列埠通訊來控制裝置,序列埠通訊的主要引數:COM口,波特率(9600),停止位(One),資料位(8),校驗位(None),括弧中的是常用值,具體意思我也不太懂,會用能實現功能就行哈哈;

開發工具:VS2012; 開發前需要新增以下服務引用:

.......using System.IO.Ports;

窗體建置,因為沒有序列埠裝置供除錯 ,所以我用虛擬序列埠即兩個序列埠互相連接來實現通訊,窗體分為上下兩部分,對應兩個序列埠區,上圖為虛擬序列埠設定,下圖為Winform樣式:

2130570c2d86e938f674d9887066b01f.png

294071b240f356ce555cdfd16421f327.png

首先建立一個baseCom類:

1.宣告變數,建構函式:

eda2b81235fd8f7cae79d52d3e160a23635.jpg

dde1a60abb6e48d30dbc3bee2829a475678.jpg

public delegate void delegateOnShowMsg(comType type,stringmsg);public delegate void delegateOnOpenCom(comType type, boolonOff);public eventdelegateOnShowMsg OnShow;public eventdelegateOnOpenCom OnOpen;

comType type;string baudRate = string.Empty;string parity = string.Empty;string stopBits = string.Empty;string dataBits = string.Empty;string portName = string.Empty;public System.IO.Ports.SerialPort comPort = newSystem.IO.Ports.SerialPort();public baseCom(string portName, string baudRate, string stopBits, string dataBits, stringparity,comType type)

{this.portName =portName;this.baudRate =baudRate;this.stopBits =stopBits;this.dataBits =dataBits;this.parity =parity;this.type =type;

}

View Code

2.開啟序列埠和關閉序列埠函式:

19035964ec2d06ed05a1c005a08f404600f.jpg

ef9666cc3301cb8ef3bed1cdef44618d0b9.jpg

public voidOpenPort()

{try{if(comPort.IsOpen)

comPort.Close();

comPort.BaudRate= int.Parse(baudRate);

comPort.StopBits= (StopBits)Enum.Parse(typeof(StopBits), stopBits);

comPort.DataBits= int.Parse(dataBits);

comPort.Parity= (Parity)Enum.Parse(typeof(Parity), parity);

comPort.PortName=portName;

comPort.Handshake=Handshake.None;

comPort.Open();if(comPort.IsOpen)

{

showOnoff(true);

comPort.Handshake=Handshake.None;

comPort.DataReceived+=comPort_DataReceived;

}

showMsg(portName+ "Open Success");

}catch(Exception ex)

{

showMsg("Unable to Open" +portName);

showMsg(ex.Message);

showOnoff(false);

}

}public voidClosePort()

{if(comPort.IsOpen)

{

comPort.Close();

comPort.Dispose();

showOnoff(false);

showMsg(portName+ "Close Success");

}

}

View Code

3.接受資料和發送資料函式:

e6b7d9ba776aec21611c653b87ff5379fdf.jpg

a50ef0a598b7de684c15973f3328c95ade2.jpg

public void comPort_DataReceived(objectsender,SerialDataReceivedEventArgs e)

{try{int n =comPort.BytesToRead;if (n == 0)return;byte[] buffer = new byte[n];

comPort.Read(buffer,0, n);string rcv = Encoding.Default.GetString(buffer, 0, buffer.Length);

showMsg("RECV:" +rcv);

}catch(Exception ex)

{

ClosePort();

showMsg("Com Closed:" +ex.Message);

}

}public void comPort_SendData(stringmsg)

{if (msg == "")

{

showMsg("CAN Not EMPTY");return;

}if (comPort == null)

{

showMsg("First Open Port");return;

}if (!comPort.IsOpen)

{

showMsg("COM Not Open");return;

}byte[] data =Encoding.Default.GetBytes(msg);

comPort.Write(data,0, data.Length);

showMsg("SEND:" +msg);

}

View Code

4.顯示訊息,顯示狀態函式:

8d1b8eabe69a388a3d207d8b7ebcf1db780.jpg

834a692a3ff4c5e3a687a624d5fb67143fb.jpg

public void showMsg(stringmsg)

{if (OnShow != null)

OnShow(type, msg);

}public void showOnoff(boolflag)

{if (OnOpen != null)

OnOpen(type, flag);

}public enumcomType

{

_up,

_down

}

View Code

OK,baseCOM類已定義完成,現在撰寫窗體各控制項的功能函式:

1.初始化控制項,主要是下拉式選單的Item的新增,初始值,初始狀態:

f18b04cc278a2c5948be00499d5328cc0b9.jpg

e1909841af52aef63cd940260940d026aa6.jpg

public string[] baudRates = { "2400", "4800", "9600", "19200", "39400", "43000", "56000"};public string[] paritys = { "None", "ODD", "Even"};public string[] dataBits = { "5", "6", "7", "8"};public string[] stopBits = { "None", "One", "Two", "OnePointFive"} ;public voidInitControls()

{

comboBox_com.Items.Clear();

comboBox_baudRate.Items.Clear();

comboBox_dataBits.Items.Clear();

comboBox_parity.Items.Clear();

comboBox_StopBit.Items.Clear();

comboBox_com2.Items.Clear();foreach (var v inbaudRates)

comboBox_baudRate.Items.Add(v);foreach (var v instopBits)

comboBox_StopBit.Items.Add(v);foreach (var v inparitys)

comboBox_parity.Items.Add(v);foreach (var v indataBits)

comboBox_dataBits.Items.Add(v);foreach (var v inSystem.IO.Ports.SerialPort.GetPortNames())

{

comboBox_com.Items.Add(v);

comboBox_com2.Items.Add(v);

}

comboBox_com.SelectedIndex= 0;

comboBox_baudRate.SelectedIndex= 2;

comboBox_dataBits.SelectedIndex= 3;

comboBox_parity.SelectedIndex= 0;

comboBox_StopBit.SelectedIndex= 1;

comboBox_com2.SelectedIndex= 0;

}

View Code

2.宣告兩個COM類,comUp和comDown:

public delegate void delegateOnOff(comType type,bool onoff);//定義兩個委派

public delegate void delegateShow(comType type,string msg);//為了防止報錯「從不是建立控制項的執行緒控制它」

baseCom comUp; //定義上序列埠COM

baseCom comDown; //定義下序列埠COM

Image imgOn, imgOff; //指示燈

Thread th; //執行緒用來實現自動發送

3.撰寫開啟(關閉)序列埠按鈕點選事件(開啟comUp和開啟comDown程式碼一樣,只貼出comUp):

be31fe153507616170324f18bbf1817f7de.jpg

7293c9d64d9836baad1ba5918d8de1ec56b.jpg

private void button_OpenCom_Click(objectsender, EventArgs e)

{string cmd = ((Button)sender).Text.Split(' ')[0];if (comUp != null)

comUp.ClosePort();if (cmd == "Close")return;string s1 =comboBox_com.SelectedItem.ToString();string s2 =comboBox_baudRate.SelectedItem.ToString();string s3 =comboBox_StopBit.SelectedItem.ToString();string s4 =comboBox_dataBits.SelectedItem.ToString();string s5 =comboBox_parity.SelectedItem.ToString();

comUp= newbaseCom(s1, s2, s3, s4, s5,comType._up);

comUp.OnOpen+=SignalState;

comUp.OnShow+=ShowMsg;

comUp.OpenPort();

}

View Code

4.撰寫發送資料按鈕點選事件:

private void button_Send_Click(objectsender, EventArgs e)

{if (comUp != null)

comUp.comPort_SendData(textBox_ComSend.Text);

}

5.撰寫資料接受發送顯示到文字框及狀態指示燈變化函式:

cf8847718e07ce28dfc0893df302dc0b656.jpg

02f1d140c4b658130c1b5a1da34cda145ed.jpg

public void SignalState(comType type,boolonoff)

{if (this.InvokeRequired)

{

delegateOnOff d= newdelegateOnOff(SignalState);this.Invoke(d,new object[]{type,onoff});

}else{if (type ==comType._up)

{

pictureBox_ComSignal.Image= onoff ?imgOn : imgOff;

button_OpenCom.Text= onoff ? "Close COM" : "Open COM";

}else{

pictureBox_Com2.Image= onoff ?imgOn : imgOff;

button_OpenCom2.Text= onoff ? "Close COM" : "Open COM";

}

}

}public void ShowMsg(comType type, stringmsg)

{if (this.InvokeRequired)

{

delegateShow d= newdelegateShow(ShowMsg);this.Invoke(d, new object[] { type, msg });

}else{string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "
";if (type ==comType._up)

{

textBox_serialPort.Text+= (date + msg + "
");

}else{

textBox_serialPort2.Text+= (date + msg + "
");

}

}

}

View Code

6.Monitor函式,即執行緒函式,用來實現資料自動發送(沒有進行準確定時,大概設了個間隔):

eb016ccf25bffdec0e3073b49fc3ddc8bf2.jpg

f27e4a9bb46197f45c1e9d2ab0bbecf5b68.jpg

public voidMonitor()

{double i =0;while (i++<10000000000)

{if (i == 1000000000)

{

i= 0;if(checkBox_AutoSend.Checked)

{if (comUp != null)

comUp.comPort_SendData(textBox_ComSend.Text);

}if(checkBox_AutoSend2.Checked)

{if (comDown != null)

comDown.comPort_SendData(textBox_comSend2.Text);

}

}

}

}

View Code

至此,序列埠通訊功能已基本實現,可在此框架上進行實際應用開發,編碼新手,歡迎大家批評指正!看下效果圖(COM1和COM11虛擬連接):

6df906c2fdc4d7e8954d873b3dfb205f.png