C#上位机之—WinForm实现串口通信示例
上位机开发常用到串口通信来控制设备,串口通信的主要参数: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实现串口通信示例的更多相关文章
- 倍福TwinCAT3上位机与PLC通信测试(ADS通信) 包含C#和C++代码
倍福TwinCAT3上位机与PLC通信测试(ADS通信) 包含C#和C++代码 本次测试需要环境: VS2013,TwinCAT3(本人版本TC31-Full-Setup.3.1.4018.16) 代 ...
- 上位机开发之西门子PLC-S7通信实践
写在前面: 就目前而言,在中国的工控市场上,西门子仍然占了很大的份额,因此对于上位机开发而言,经常会存在需要与西门子PLC进行通信的情况.然后对于西门子PLC来说,通信方式有很多,下面简单列举一下: ...
- winform SerialPort串口通信问题
一.串口通信简介串行接口(串口)是一种可以将接受来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接受的串行数据流转换为并行的数据字符供给CPU的器件.一般完成这种功能的电路,我们称为串 ...
- C#上位机之—WinForm实现Socket异步通讯示例
工作中常用到的一些知识点,总是用完就忘,第一次尝试用博客记录下来,以备后用: Socket通讯,Socket(套接字)是基于TCP/IP通讯方式的封装好的类,调用时需要添加下面的服务引用: using ...
- C#做一个简单的进行串口通信的上位机
C#做一个简单的进行串口通信的上位机 1.上位机与下位机 上位机相当于一个软件系统,可以用于接收数据.控制数据.即可以对接收到的数据直接发送操控命令来操作数据.上位机可以接收下位机的信号.下位机是 ...
- 【精讲版】上位机C#/.NET与西门子PLC通信
618来啦 亲们,腾讯课堂101机构打榜了,快来助力<新阁教育>,<免费赠送课程>! 1.手机QQ(微信请也来一遍)扫下方二维码↓,找到<新阁教育> 2.点击“支持 ...
- 上位机开发之三菱FX3U以太网通信实践
上次跟大家介绍了一下上位机与三菱Q系列PLC通信的案例,大家可以通过点击这篇文章:上位机开发之三菱Q系列PLC通信实践(←戳这里) 今天以三菱FX3U PLC为例,跟大家介绍一下,如何实现上位机与其之 ...
- Stm32串口通信(USART)
Stm32串口通信(UART) 串口通信的分类 串口通信三种传递方式 串口通信的通信方式 串行通信的方式: 异步通信:它用一个起始位表示字符的开始,用停止位表示字符的结束.其每帧的格式如下: 在一帧格 ...
- [python] 3 、基于串口通信的嵌入式设备上位机自动测试程序框架(简陋框架)
星期一, 20. 八月 2018 01:53上午 - beautifulzzzz 1.前言 做类似zigbee.ble mesh...无线网络节点性能测试的时候,手动操作然后看表象往往很难找出真正的原 ...
随机推荐
- Easy C 编程 in Linux
入坑Ubuntu有4,5天了,当时各种不习惯,但现在渐渐喜欢上了这种简单大方的显示界面和快速高效的命令行模式,各种没有的功能也都有网页版,非常不错呢. 现在最让我感到神奇之处,便是Linux的C编程是 ...
- python实例:自动爬取豆瓣读书短评,分析短评内容
思路: 1.打开书本“更多”短评,复制链接 2.脚本分析链接,通过获取短评数,计算出页码数 3.通过页码数,循环爬取当页短评 4.短评写入到txt文本 5.读取txt文本,处理文本,输出出现频率最高的 ...
- 关于MySQL5.6配置文件my-default.ini不生效问题
一.问题描述 首先,由于工作要求,需使用MySQL5.6版本(绿色版),从解压到修改root密码,一切都很顺利,但是在我要修改mysql的最大连接数的时候,出现问题了,配置不生效.完蛋.还好有万能的百 ...
- ios--->ios消息机制(NSNotification 和 NSNotificationCenter)
问题的背景 IOS中委托模式和消息机制基本上开发中用到的比较多,一般最开始页面传值通过委托实现的比较多,类之间的传值用到的比较多,不过委托相对来说只能是一对一,比如说页面A跳转到页面B,页面的B的值改 ...
- 自动化运维之Ansible入门
Ansible简介 Ansible是什么? Ansible 简单的说是一个配置管理系统(ConfiGuration Management System).你只需要可以使用ssh访问你的服务器或设备.它 ...
- JDK Proxy和CGLIB Proxy
动态代理在Java中有着广泛的应用,比如Spring AOP,Hibernate数据查询.测试框架的后端mock.RPC,Java注解对象获取等.静态代理的代理关系在编译时就确定了,而动态代理的代理关 ...
- I Love GPLT
这道超级简单的题目没有任何输入. 你只需要把这句很重要的话 —— “I Love GPLT”——竖着输出就可以了. 所谓“竖着输出”,是指每个字符占一行(包括空格),即每行只能有1个字符和回车. 输入 ...
- 秒秒钟破解eval加密
前言 准确的说eval处理过的代码应该叫做压缩代码,不过效果上算是加密过了一样!很多小伙伴不想直接让别人看到自己的js代码往往就会采取这样的处理措施.不过,其实这样的方法只能防御那些小白.对于真正的 ...
- Java并发读书笔记:线程安全与互斥同步
目录 导致线程不安全的原因 什么是线程安全 不可变 绝对线程安全 相对线程安全 线程兼容 线程对立 互斥同步实现线程安全 synchronized内置锁 锁即对象 是否要释放锁 实现原理 啥是重进入? ...
- 部署 harbor 私有仓库
安装下载依赖包 安装docker-compose 从 docker compose 发布页面下载最新的 docker-compose 二进制文件,本文以1.25.4为例 cd /opt/k8s/wor ...