C#实现串口通讯的方法
  WDCdPJue8CCV 2023年12月22日 15 0

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

 在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();

一次完整的通讯到此结束

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月22日 0

暂无评论

推荐阅读
WDCdPJue8CCV