上位机开发常用到串口通信来控制设备,串口通信的主要参数:COM口,波特率(9600),停止位(One),数据位(8),校验位(None),括号中的是常用值,具体意思我也不太懂,会用能实现功能就行哈哈;

开发工具:VS2012;   开发前需要添加以下服务引用:

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

窗体搭建,因为没有串口设备供调试 ,所以我用虚拟串口即两个串口互相连接来实现通信,窗体分为上下两部分,对应两个串口区,上图为虚拟串口设置,下图为Winform样式:

C#上位机之—WinForm实现串口通信示例-LMLPHP                   C#上位机之—WinForm实现串口通信示例-LMLPHP

首先创建一个baseCom类:

1.声明变量,构造函数:

        public delegate void delegateOnShowMsg(comType type,string msg);
public delegate void delegateOnOpenCom(comType type, bool onOff);
public event delegateOnShowMsg OnShow;
public event delegateOnOpenCom 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 = new System.IO.Ports.SerialPort();
public baseCom(string portName, string baudRate, string stopBits, string dataBits, string parity,comType type)
{
this.portName = portName;
this.baudRate = baudRate;
this.stopBits = stopBits;
this.dataBits = dataBits;
this.parity = parity;
this.type = type;
}

2.打开串口和关闭串口函数:

        public void OpenPort()
{
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 void ClosePort()
{
if (comPort.IsOpen)
{
comPort.Close();
comPort.Dispose();
showOnoff(false);
showMsg(portName + " Close Success");
}
}

3.接受数据和发送数据函数:

        public void comPort_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
try
{
int n = comPort.BytesToRead;
if (n == )
return;
byte[] buffer = new byte[n];
comPort.Read(buffer, , n);
string rcv = Encoding.Default.GetString(buffer, , buffer.Length);
showMsg("RECV:" + rcv);
}
catch (Exception ex)
{
ClosePort();
showMsg("Com Closed:" + ex.Message);
}
}
public void comPort_SendData(string msg)
{
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, , data.Length);
showMsg("SEND:" + msg);
}

4.显示信息,显示状态函数:

        public void showMsg(string msg)
{
if (OnShow != null)
OnShow(type, msg);
}
public void showOnoff(bool flag)
{
if (OnOpen != null)
OnOpen(type, flag);
}
public enum comType
{
_up,
_down
}

OK,baseCOM类已定义完成,现在编写窗体各控件的功能函数:

1.初始化控件,主要是下拉菜单的Item的添加,初始值,初始状态:

        public string[] baudRates = { "", "", "", "", "", "", "" };
public string[] paritys = { "None", "ODD", "Even" };
public string[] dataBits = { "", "", "", "" };
public string[] stopBits = { "None", "One", "Two", "OnePointFive" } ;
public void InitControls()
{
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 in baudRates)
comboBox_baudRate.Items.Add(v);
foreach (var v in stopBits)
comboBox_StopBit.Items.Add(v);
foreach (var v in paritys)
comboBox_parity.Items.Add(v);
foreach (var v in dataBits)
comboBox_dataBits.Items.Add(v);
foreach (var v in System.IO.Ports.SerialPort.GetPortNames())
{
comboBox_com.Items.Add(v);
comboBox_com2.Items.Add(v);
}
comboBox_com.SelectedIndex = ;
comboBox_baudRate.SelectedIndex = ;
comboBox_dataBits.SelectedIndex = ;
comboBox_parity.SelectedIndex = ;
comboBox_StopBit.SelectedIndex = ;
comboBox_com2.SelectedIndex = ;
}

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):

        private void button_OpenCom_Click(object sender, EventArgs e)
{
string cmd = ((Button)sender).Text.Split(' ')[];
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 = new baseCom(s1, s2, s3, s4, s5,comType._up);
comUp.OnOpen += SignalState;
comUp.OnShow += ShowMsg;
comUp.OpenPort();
}

4.编写发送数据按钮点击事件:

private void button_Send_Click(object sender, EventArgs e)
{
if (comUp != null)
  comUp.comPort_SendData(textBox_ComSend.Text);
}

5.编写数据接受发送显示到文本框及状态指示灯变化函数:

        public void SignalState(comType type,bool onoff)
{
if (this.InvokeRequired)
{
delegateOnOff d = new delegateOnOff(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, string msg)
{
if (this.InvokeRequired)
{
delegateShow d = new delegateShow(ShowMsg);
this.Invoke(d, new object[] { type, msg });
}
else
{
string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff") + "\r\n";
if (type == comType._up)
{
textBox_serialPort.Text += (date + msg + "\r\n");
}
else
{
textBox_serialPort2.Text += (date + msg + "\r\n");
}
}
}

6.Monitor函数,即线程函数,用来实现数据自动发送(没有进行准确定时,大概设了个间隔):

        public void Monitor()
{
double i =;
while (i++<)
{
if (i == )
{
i = ;
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);
}
}
}
}

至此,串口通信功能已基本实现,可在此框架上进行实际应用开发,编码新手,欢迎大家批评指正!看下效果图(COM1和COM11虚拟连接):

C#上位机之—WinForm实现串口通信示例-LMLPHP

05-11 10:50