首页 > 编程语言 >C#实现串口通讯的方法

C#实现串口通讯的方法

时间:2024-01-14 10:04:07浏览次数:48  
标签:控件 通讯 C# cb list serialPort1 串口 port

帖子只用于记录本人的学习记录,算是给未来的自己出一份傻瓜式教学。

 在C#语言上,一般上位机是由Winform开发,也有WPF,但是我不会WPF

上位机无非就是发送数据与接收数据,可以使用C#的SerialPort方法

winform自带SerialPort控件,可以将此控件直接拖到页面上,然后实例化该控件,也可以直接实例化SerialPort类,这样就不需要SerialPort控件了,个人建议这样,省去一个控件

下面的代码我是使用SerialPort控件来开发,控件名为:serialPort1

1、定义一个串口参数结构体,写在命名空间

//串口参数结构体
struct COMPORT_ATTRIBUTE
{
    public int bandrate;//波特率
    public int data_bit;//数据位
    public Parity parity_check_bit;//校验位
    public StopBits stop_bit;//停止位
    public string comport_number;//最新的串口名称
};

2、给串口参数设置一些常用的默认值,我写在了窗体加载事件里

//波特率设置
            cb_BoTeLv.DataSource = new string[] { "4800", "9600", "14400", "19200", "38400", "56000", "57600", "115200", "128000", "256000" };
            cb_BoTeLv.SelectedIndex = 1;
            //初始化波特率
            uart_port.bandrate = int.Parse(cb_BoTeLv.Text);
            // 初始化数据位
            cb_DataBits.DataSource = new string[] { "8", "7", "6", "5" };
            cb_DataBits.SelectedIndex = 0;
            uart_port.data_bit = int.Parse(cb_DataBits.Text);
            // 初始化停止位
            cb_StopBits.DataSource = new string[] { "0", "1", "2", "1.5" };
            cb_StopBits.SelectedIndex = 1;
            uart_port.stop_bit = (StopBits)cb_StopBits.SelectedIndex;
            // 初始化校验位
            cb_Parity.DataSource = new string[] { "无", "奇校验", "偶校验", "1", "0" };
            cb_Parity.SelectedIndex = 0;
            uart_port.parity_check_bit = (Parity)cb_Parity.SelectedIndex;

3、设置完参数以后,就可以进行打开或者关闭串口的操作了,打开串口需要选择串口号,需要用户自己去选择,我们应将扫描到的串口绑定在页面上供用户选择,下面是扫描串口和打开、关闭的方法

/// <summary>
        /// 扫描串口
        /// </summary>
        public void InitializePorts()
        {
            string[] port_names = SerialPort.GetPortNames();
            string last_name = "";
            cb_DuanKou.Items.Clear();//清除数据
            if (port_names == null)
            {
                cb_DuanKou.Text = "无串口";
                return;
            }
            foreach (string s in SerialPort.GetPortNames())
            {
                //获取有多少个COM口就添加进COMBOX项目列表  
                cb_DuanKou.Items.Add(s);
                last_name = s;//保存最新的一个
            }
            cb_DuanKou.Text = last_name;//显示最新的一个串口
            uart_port.comport_number = last_name;//赋值变量
        }
/// <summary>
        /// 打开串口
        /// </summary>
        private void OpenSerialPort()
        {
            if (serialPort1.IsOpen)
            {
                return;
            }
            try
            {
                serialPort1.PortName = cb_DuanKou.Text;//端口号
                serialPort1.BaudRate = uart_port.bandrate;//波特率
                serialPort1.DataBits = uart_port.data_bit;      //数据位
                serialPort1.Parity = uart_port.parity_check_bit;//校验位
                serialPort1.StopBits = uart_port.stop_bit;      //停止位
                serialPort1.Open();
                AddText("端口打开成功");
            }
            catch(Exception ex)
            {
                AddText("端口打开失败,"+ex.Message);
            }
        }
        /// <summary>
        /// 关闭串口
        /// </summary>
        private void CloseSerialPort()
        {
            if (!serialPort1.IsOpen)
            {
                return;
            }
            try
            {
                serialPort1.Close();
                AddText("端口关闭成功");
            }
            catch (Exception ex)
            {
                AddText("端口关闭失败," + ex.Message);
            }
        }

其中 AddText()是我定义的一个提示方法,为了更让用户使用方便,我还加了许多颜色和控件提示,在这里的代码中我阉割掉了,开发的时候要站在用户的角度

4、打开串口以后就可以进行收发数据,串口是以byte数组的形式进行传输,我们需要将用户输入的内容或者定好的内容转成byte数字进行发送

4.1、发送

BitConverter.GetBytes(Convert.ToInt16(data))

此段代码是C#封好的,将用户输入的int16类型的数据转换为byte字节,对应的Float32类型和Double类型为ToSingle和ToDouble,别的数据类型也是一样,int8是直接ToByte

特别注意:C#的所有转换,不管是字节转数字还是数字转字节都是按照低位在前来转换的,有些需要高位在前的需要转换完以后再Reverse()一下。

将所有要发送的字节放到一个byte[]数组里,我是先用List<byte>将字节逐个添加,然后直接 byte[] sendData = list.ToArray();

这样sendData就是我们要发送的字节数组,发送方法很简单:

serialPort1.Write(sendData, 0, sendData.Length);

在发送完成以后,我们可以调用

serialPort1.DiscardOutBuffer();

来清除发送缓存区的内容,可以避免一些后续数据发错的问题;

示例:

List<byte> list = new List<byte>();//新建一个list数组临时用
//添加要发送的字节
list.AddRange(BitConverter.GetBytes(Convert.ToInt16(data));
list.AddRange(BitConverter.GetBytes(Convert.ToUInt16(data));
list.AddRange(BitConverter.GetBytes(Convert.ToInt32(data));
list.AddRange(BitConverter.GetBytes(Convert.ToUInt32(data));
list.AddRange(BitConverter.GetBytes(Convert.ToSingle(data));
list.AddRange(BitConverter.GetBytes(Convert.ToDouble(data));
//将list数组放到byte数组里
byte[] sendData = list.ToArray();
//通过打开过的串口发送数据
serialPort1.Write(sendData, 0, sendData.Length);
//给数据发送一些时间然后清除发送缓存区,清除时间自己算一下发送需要多久
Thread.Sleep(300);
serialPort1.DiscardOutBuffer();
//完成

4.2、接收

把接收事件写在serialPort1_DataReceived里,这是控件自带的事件

先让他睡0.1秒,防止我们读取的时候数据还没接收完

Thread.Sleep(100);

随后获取接收缓存区的数据

byte[] b = new byte[serialPort.BytesToRead];
serialPort.Read(b, 0, b.Length);

b就是接收到的字节数据

接下来怎么处理这些数据就看业务需要了,把字节转换为数字的方法是

BitConverter.ToSingle(b, 4).ToString();

这是从下标为4的字节开始,往后取4个字节转换为浮点数,别的数据类型也是一样的格式,接收完毕以后清除一下接收缓存区的内容

serialPort1.DiscardInBuffer();

一次完整的通讯到此结束

 



标签:控件,通讯,C#,cb,list,serialPort1,串口,port
From: https://blog.51cto.com/u_16371710/9238173

相关文章

  • C#中substring ()的用法
    String.SubString(int index,int length)  index:开始位置,从0开始   length:你要取的子字符串的长度  示例:usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespacestr_sub{classProgram{staticvoidMain(string[]args){strin......
  • C#常用工具安装方法及资源整理
    1、GitGit下载地址Git安装教程2、SQLServer2019下载地址安装教程3、VisualStudio2022下载地址安装教程4、TortoiseGit(x64)  2.13.0.1中文版下载地址安装教程5、sqlserver2014下载及安装教程......
  • Helm概述,安装,部署,chart模板使用
    Helm概述Helm是一个用于管理Kubernetes应用程序的工具,它提供了一个简单而有效的方式来定义、安装和部署应用程序。Helm通过使用可重复使用的模板(称为Charts)来描述应用程序的Kubernetes资源,并提供了一个命令行界面来管理这些Charts。Helm的核心概念包括:Chart:Chart是Helm的基本单元,它......
  • React-hook-form-mui(一):基本使用
    前言在项目开发中,我们选择了React+MUI作为技术栈。在使用MUI构建form表单时,我们发现并没有与antd类似的表单验证功能,于是我们选择了MUI推荐使用的react-hook-form-mui库去进行验证。但是发现网上关于这个库的使用方法和demo比较少且比较简单,并没有复杂的表单验证的demo。因此本文及......
  • Auto CAD
    快捷命令 L直线M移动C圆EL椭圆XL射线轴线RO旋转E删除H填充TR修剪EX延伸PO点S拉伸U返回DDI直径标注DAN角度标注OP系统选项设置A圆弧T多行文字B块定义I块插入W定义块文件CO复制MI镜像O偏移F倒直角或圆角D标注样式DLI线......
  • centos安装gcc 4.9.4 版本
    系统:centos7.6因为在安装hyperf热加载时需要用到fswatch,安装fswatch需要gcc4.9以上的版本,但是系统自带的gcc只有4.8的版本,所以我们需要安装4.9的,这里我安装的是4.9.4的版本:yuminstall-ygccgcc-c++#因为我有自带的gcc所以不用安装,如果没有的话。需要先安装yum自带的gcc......
  • React 详解(1)
    React简介React基础JSX的本质JSX并不是标准的JS语法,它是JS的语法扩展,浏览器本身不能识别,需要通过解析工具做解析之后才能在浏览器中运行。这里主要依靠BABEL解析工具来解析,下面简单的介绍一下这个解析工具(http://babeljs.io):JSX中使用JS表达式在JSX中可以通过大括号语法......
  • AUTOCAD快捷键
    快捷命令L直线M移动C圆EL椭圆XL射线轴线RO旋转E删除H填充TR修剪EX延伸PO点S拉伸U返回DDI直径标注DAN角度标注OP系统选项设置A圆弧T多行文字B块定义I块插入W定义块文件CO复制MI镜像O偏移F倒直角或圆角D标注样式DLI线性......
  • [活动(深圳)] .NET Love AI 之 .NET Conf China 2023 Party 深圳
    中国.NET社区2023年12月16日在北京成功举办了.NETConfChina2023,虽然北京飘起雪,依然挡不住想要参加活动的全国各地的.NET开发兄弟姐妹的热情。大家可以通过大会精彩照片集:https://live.photoplus.cn/live/79415183体验现场的热度。欢迎访问大会官网了解更详细的信息:https://d......
  • NCTF2023-web-部分wp
    期末考完了,芜湖~~~~复工!NCTF好巧不巧出在我们期末周复习的时间,当时也只是上线看了一点,有些题有点思路,但是还是因为积累知识不足,想不出什么姿势。现在能复现出的就尽量看看吧。logging记忆犹新,因为队里一个佬来了一看,说是一眼签到题,哈哈哈哈哈哈。Java安全以前没怎么接触过,后......