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

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

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

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

                 

首先创建一个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实现串口通信示例的更多相关文章

  1. 倍福TwinCAT3上位机与PLC通信测试(ADS通信) 包含C#和C++代码

    倍福TwinCAT3上位机与PLC通信测试(ADS通信) 包含C#和C++代码 本次测试需要环境: VS2013,TwinCAT3(本人版本TC31-Full-Setup.3.1.4018.16) 代 ...

  2. 上位机开发之西门子PLC-S7通信实践

    写在前面: 就目前而言,在中国的工控市场上,西门子仍然占了很大的份额,因此对于上位机开发而言,经常会存在需要与西门子PLC进行通信的情况.然后对于西门子PLC来说,通信方式有很多,下面简单列举一下: ...

  3. winform SerialPort串口通信问题

    一.串口通信简介串行接口(串口)是一种可以将接受来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接受的串行数据流转换为并行的数据字符供给CPU的器件.一般完成这种功能的电路,我们称为串 ...

  4. C#上位机之—WinForm实现Socket异步通讯示例

    工作中常用到的一些知识点,总是用完就忘,第一次尝试用博客记录下来,以备后用: Socket通讯,Socket(套接字)是基于TCP/IP通讯方式的封装好的类,调用时需要添加下面的服务引用: using ...

  5. C#做一个简单的进行串口通信的上位机

    C#做一个简单的进行串口通信的上位机   1.上位机与下位机 上位机相当于一个软件系统,可以用于接收数据.控制数据.即可以对接收到的数据直接发送操控命令来操作数据.上位机可以接收下位机的信号.下位机是 ...

  6. 【精讲版】上位机C#/.NET与西门子PLC通信

    618来啦 亲们,腾讯课堂101机构打榜了,快来助力<新阁教育>,<免费赠送课程>! 1.手机QQ(微信请也来一遍)扫下方二维码↓,找到<新阁教育> 2.点击“支持 ...

  7. 上位机开发之三菱FX3U以太网通信实践

    上次跟大家介绍了一下上位机与三菱Q系列PLC通信的案例,大家可以通过点击这篇文章:上位机开发之三菱Q系列PLC通信实践(←戳这里) 今天以三菱FX3U PLC为例,跟大家介绍一下,如何实现上位机与其之 ...

  8. Stm32串口通信(USART)

    Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...

  9. [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)

    星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...

随机推荐

  1. CQOI十二省联考游记

    Day 0 看似稳如老狗的我实则慌得一逼 看了一上午的CRT,一个字没看进去 我反复安慰自己:我才高一,我才高一 但是,明年的联赛会不会跟今年一样高呢? 明年的心态会不会有现在这么好呢? 明年同届的d ...

  2. Python中关于__main__变量的问题

    在Python代码的编写中,经常会用到这么一句: if __name__ == "__main__": .... 这句代码之前的语句在整个模块被其他文件调用的时候会被运行,而这句代 ...

  3. CSS-01-引入css的三种方法

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. linux--->阿里云centos6.9环境配置安装lnmp

    阿里云centos6.9环境配置安装lnmp mysql安装 本人博客:http://www.cnblogs.com/frankltf/p/8615418.html PHP安装 1.安装依赖关系 yu ...

  5. CTF--HTTP服务--路径遍历(提升root用户权限)

    开门见山 1. 在上次实验取的靶机低用户权限,查看该系统的内核版本 2. 查看该系统的发行版本 3. 查看该内核版本是否存在内核溢出漏洞,并没有 如果有内核溢出漏洞,则可以 4. 在靶机查看/etc/ ...

  6. 详解隐马尔可夫模型(HMM)中的维特比算法

    笔记转载于GitHub项目:https://github.com/NLP-LOVE/Introduction-NLP 4. 隐马尔可夫模型与序列标注 第3章的n元语法模型从词语接续的流畅度出发,为全切 ...

  7. YUM安装软件提示[Errno 14] curl#6 - "Could not resolve host: mirrors.cloud.aliyuncs.com; 未知的错误"

    报错如下: 翻译过来就是 所以问题很简单: 第一种情况:本地DNS服务错误 第二种情况:远程主机挂了 第三种情况:远程主机地址配置错误 第一种解决方法:换DNS 首先验证一下是不是本地DNS错误 从上 ...

  8. C语言系列之自增自减运算符的用法(二)

    运算符中最难理解的有自增自减运算符的使用方法,下面我将简单总结一下他们的使用方法 我们知道,C语言运行是由右向左运行的 下面我们来看一个例子 当i等于3的时候 j=++i; 由上面可知,C语言是由右向 ...

  9. python中Threadlocal变量

    在多线程环境下,每个线程都有自己的数据.一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁. 不加锁就会出现变量会被修改的问题,进而 ...

  10. 实验5: IOS的升级与恢复

    实验5:  IOS的升级与恢复 实验目的 通过本实验可以掌握 1)    掌握IOS 正常的情况下升级IOS2)    IOS 丢失的情况下使用TFTP恢复IOS3)    IOS 丢失的情况下使用X ...