头图

C# Serialport的发送和接收

IC00

C# Serialport的发送和接收

前言:

上次博主为大家讲解了串口控件Serialport的配置,本期讲解一下Serialport的发送和接收,这个SerialPort串口通信的控件对上位机和单片机的通信提供了,很多的方法,可以方便大家使用,使用也很简单。

每日一遍,防止早恋:

6a04b428gy1fyr5kuqgzkg208c08c4pg

1.SerialPort串口控件发送配置

1.1 拿着上篇文章的项目,我在那个项目基础上面的进行设置不会的童鞋可以看博主的上一篇文章,放个链接( https://juejin.cn/post/702183... ),我们先要把界面设置好,发送框,接收框,发送按钮

image-20211030150611201

1.2 我们先来了解一下serialPort的发送它提供的几个接口:

public void Write(byte[] buffer, int offset, int count);
    使用缓冲区中的数据将指定数量的字节写入串行端口。
        // buffer:   包含要写入端口的数据的字节数组。
        //   offset:    buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
        //   count:    要写入的字节数。
public void Write(string text);
    将指定的字符串写入串行端口。
      text:  输出字符串。
public void Write(char[] buffer, int offset, int count);
    使用缓冲区中的数据将指定数量的字符写入串行端口。
        //   buffer:   包含要写入端口的数据的字符数组。
        //   offset:  buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
        //   count: 要写入的字符数。
public void WriteLine(string text);
        //     将指定的字符串和 System.IO.Ports.SerialPort.NewLine 值写入输出缓冲区。
        //     text:   要写入输出缓冲区的字符串。
  1. 3双击发送按钮自动生成方法函数,写入我们发送的方法:

image-20211030151106175

image-20211030153349626

1.4代码如下:可以直接用,前提是你的界面和博主的一样,注意界面的控件是不是和博主函数触发是对应的,不是要改界面的触发,具体参考上一篇文章。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Serilport
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
        }
        private void SearchAndAddSerialToComboBox(object sender, EventArgs e)
        {
            string Buffer;
            comboBox1.Items.Clear();    //清初之前已经扫描的记录
            for (int i = 0; i < 20; i++)
            {
                try
                {
                    Buffer = "COM" + i.ToString(); //获得COM1-20
                    serialPort1.PortName = Buffer;     //获取COM信息
                    serialPort1.Open();                 //打开串口
                    comboBox1.Items.Add(Buffer);
                    comboBox1.Text = Buffer; //添加串口得到记录集
                    serialPort1.Close();                 //关闭串口
                }
                catch { }
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            try
            {
                serialPort1.PortName = comboBox1.Text;
                serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text, 10);
                serialPort1.DataBits = Convert.ToInt32(comboBox3.Text, 10);
                if (comboBox4.Text == "None") { serialPort1.Parity = Parity.None; }
                else if (comboBox4.Text == "奇校验") { serialPort1.Parity = Parity.Odd; }
                else if (comboBox4.Text == "偶校验") { serialPort1.Parity = Parity.Even; }
                else if (comboBox4.Text == "Mark") { serialPort1.Parity = Parity.Mark; }
                else if (comboBox4.Text == "空格校验") { serialPort1.Parity = Parity.Space; }
                if (comboBox5.Text == "1")
                {
                    serialPort1.StopBits = StopBits.One;
                }
                else if (comboBox5.Text == "1.5")
                {
                    serialPort1.StopBits = StopBits.OnePointFive;
                }
                else if (comboBox5.Text == "1.5")
                {
                    serialPort1.StopBits = StopBits.Two;
                }
                //serialPort1.ReadTimeout(2000);
                serialPort1.Open();
                button2.Enabled = false;//打开串口按钮不可用
                //button3.Enabled = true;//关闭串口
            }
            catch
            {
                MessageBox.Show("端口错误,请检查串口", "错误");
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string str = textBox2.Text;//获取发送框的数据
            byte[] Data = new byte[1];//作为发送的容器
            if (serialPort1.IsOpen)//判断我们的串口是不是打开了
            {
                for (int j = 0; j < str.Length; j++)//遍历我们的发送语句,博主现在采用一个一个的发送
                {
                    if (str[j] == ' ')//我们的发送语句有空格隔开,我们要遍历掉
                    {
                        continue;
                    }
                    else
                    {
                        try
                        {
                            Data[0] = Convert.ToByte(str.Substring(j, 2), 16);//substring是从j的位置取str字符串2个字节,16进制数
                        }
                        catch
                        {
                            MessageBox.Show("请核对输入的十六进制数据格式错误");
                        }
                        try
                        {
                            serialPort1.Write(Data, 0, 1);//这个意思是发送,data数据,从0的位置开始,取一个值。
                            j++;
                        }
                        catch
                        {
                            MessageBox.Show("端口发送失败,系统将关闭当前串口错误");
                            serialPort1.Close();//关闭串口
                        }
                    }

                }
            }
        }
    }
}

2.SarilPort 串口控件接收配置

2.1 在了解SerialPort 接收方法的接口

public int Read(char[] buffer, int offset, int count);
      从 System.IO.Ports.SerialPort 输入缓冲区中读取一些字符,然后将这些字符写入字符数组中指定的偏移量处。
         //  buffer: 将输入写入到其中的字节数组。
        //   offset: 要写入字节的 buffer 中的偏移量。
        //   count:  最多读取的字节数。 如果 count 大于输入缓冲区中的字节数,则读取较少的字节。
public int Read(byte[] buffer, int offset, int count);
     从 System.IO.Ports.SerialPort 输入缓冲区读取一些字节并将那些字节写入字节数组中指定的偏移量处。
         // buffer: 将输入写入到其中的字节数组。
        //   offset:要写入字节的 buffer 中的偏移量。
        //   count:最多读取的字节数。 如果 count 大于输入缓冲区中的字节数,则读取较少的字节。
public int ReadByte();
     从 System.IO.Ports.SerialPort 输入缓冲区中同步读取一个字节。
public int ReadChar();
     从 System.IO.Ports.SerialPort 输入缓冲区中同步读取一个字符。
public string ReadExisting();
     在编码的基础上,读取 System.IO.Ports.SerialPort 对象的流和输入缓冲区中所有立即可用的字节。
public string ReadLine();
     一直读取到输入缓冲区中的 System.IO.Ports.SerialPort.NewLine 值。
public string ReadTo(string value);
    一直读取到输入缓冲区中的指定 value 的字符串。
     value: 指示读取操作停止位置的值。

2.2,根据截图创建接收函数,SerialPort自动接收数据

image-20211030195152589

image-20211030201629543

2.3 如果你想不使用循环,可以采取一次性读取出来数据,这样就不会那么麻烦,仔细阅读它自己的接口,找到适合自己的接口,我把我的代码发给大家参考一下:

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            byte data = 0;
            int len = 0;
            int bufsize = (int)serialPort1.BytesToRead;//获取缓存字节数
            while (len < bufsize)//获取之后一个一个取
            {
                data = (byte)serialPort1.ReadByte();//获取串口的值
                len++;
                string str = Convert.ToString(data, 16).ToUpper();//获取之后我们要在TextBox中输出
                if (str.Length == 1)//如果我们获取的值是一位我们在前面补个0
                {
                    textBox1.AppendText(" 0" + str);
                }
                else
                {
                    textBox1.AppendText(" " + str);//两个值就在前面加一个空格分隔 
                }
            }  
            textBox1.AppendText(System.Environment.NewLine);//换行
            serialPort1.DiscardInBuffer();//清除之前的缓存

        }

3.展示一下,SerialPort的发送接收,博主这里刚好有一个单片机,给大家演示一下,如果对这个感兴趣,也可以采用虚拟串口,模拟一下玩一玩。

image-20211030205846839

注:博主在运行的时候报一个线程的错 C# 异常:已引发: "线程间操作无效: 从不是创建控件“textBox1”的线程访问它。" (System.InvalidOperationException),需要在Form1里面添加添加代码System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;禁止捕获对错误线程的调用。

总结:

博主只是简单的介绍了,C# SerialPort串口控件的发送和接收,并演示了一下,对这方面感兴趣的同学可以学一下,博主也只是初学者,因为最近在做一个项目所以才学习的,学C#的同学很少很少,希望大家不喜勿喷,创作不易,点赞,关注,评论哦。

6a04b428gy1fyr5kw88tig208c08cx5k

阅读 1.2k
1 声望
0 粉丝
0 条评论
1 声望
0 粉丝
文章目录
宣传栏