上位机开发常用到串口通信来控制设备,串口通信的主要参数: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. Java lambda 表达式常用示例

    实体类 package com.lkb.java_lambda.dto; import lombok.Data; /** * @program: java_lambda * @description: ...

  2. 线性最长cover(无讲解)

    #include<bits/stdc++.h> using namespace std; ; int n,f[maxn],cover[maxn],R[maxn]; char str[max ...

  3. 自定义BeanDefinitionRegistryPostProcessor注册bean

    自定义BeanDefinitionRegistryPostProcessor 概述 BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProce ...

  4. iOS--->运行程序屏幕上下有黑边

    iOS--->运行程序屏幕上下有黑边 原因是LaunchImage没有设置好,图片等尺寸没有和对应的手机屏幕大小适配导致. 解决方法 就是要增加启动图片,把屏幕拉伸,匹配好每个机型的屏幕大小,这 ...

  5. DRF框架之Serializer序列化器的序列化操作

    在DRF框架中,有两种序列化器,一种是Serializer,另一种是ModelSerializer. 今天,我们就先来学习一下Serializer序列化器. 使用Serializer序列化器的开发步骤 ...

  6. 虚拟机 ubuntu系统忘记密码如何进入

    重启 虚拟机 按住shift键 会出现下面的界面 按住‘e’进入下面的界面往下翻 更改红框勾到的字符串为:  rw init=/bin/bash 然后按F10进行引导 然后输入 :”passwd”  ...

  7. js的三种输出语句,以及html的运行循序

    js最常见的三种输出语句 1.console.log()这个语句是在浏览器控制台输出的.进入网页点击f12可查看 2.alert()弹出一个对话框, 3.document.write这个语句是在页面输 ...

  8. 利用Atomic, ThreadLocal, 模仿AQS, ReentrantLock

    /** * @description 队列同步器,利用原子整形模仿AQS,非公平锁(简单自适应自旋) * @since 2020/2/4 */ public class QueueSynchroniz ...

  9. C++零食:WTL中使用双缓冲避免闪烁

    双缓冲的原理可以这样形象的理解:把电脑屏幕看作一块黑板.首先我们在内存环境中建立一个"虚拟"的黑板,然后在这块黑板上绘制复杂的图形,等图形全部绘制完毕的时候,再一次性的把内存中绘制 ...

  10. jsp简单实现交互

    test.html <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type&quo ...