目录

串口通讯

硬件流控制(RTS/CTS)

SerialPort的使用

SerialPort常用属性

SerialPort常用方法

SerialPort事件

创建SerialPort对象以及配置参数

方式一

方式二

SerialPort实现串口通信完整例子


串口通讯

串行通信作为计算机通信方式之一,主要起到主机与外设以及主机之间的数据传输作用,串行通信具有传输线少、成本低的特点,主要适用于近距离的人-机交换、实时监控等系统通信工作当中,借助于现有的电话网也能实现远距离传输,因此串行通信接口是计算机系统当中的常用接口。

硬件流控制(RTS/CTS)

RTS/CTS流控制是硬件流控制的一种,需要按下图连线:

串口设备A给串口设备B发送数据。B忙不过来时(B的串口输入缓冲区快满了)会设置自己的RTS为低电平,这样A的CTS也变为低电平。A发现自己的CTS为低电平后,会停止发送数据;B的串口输入缓冲区快空时,会设置自己的RTS为高电平,这样A的CTS也变为高电平。A发现自己的CTS为高电平后,会继续发送数据。

相同的道理,DTR/DSR也可以做硬件流控制。

为什么打开串口时需要设置DTR、RTS为高电平呢?原因就在于:如果对方设置了硬件流控制,而这边的DTR、RTS为低电平,那么对方就不会给这边发送数据。

SerialPort的使用

SerialPort是一个串口传输的一个非常方便的控件,对从事上位机测试的人是一个很好的控件,很多做嵌入式开发的人,他们的大部分界面都是用C#写的,难免会用到这个控件

SerialPort常用属性

PortName获取或设置通信端口,包括但不限于所有可用的 COM 端口(设置使用哪个串口)
BaudRate设置或获取波特率
StopBits设置或获取数据停止位
DataBits设置或获取数据位
Parity获取或设置奇偶校验检查协议
BytesToRead获取缓冲区中读到数据的长度
ReadTimeout或者或设置读取操作的超时时间
WriteTimeout或者或设置写入操作的超时时间

SerialPort常用方法

public static string[] GetPortNames获取当前计算机的串行端口名的数组。
Open开串口连接
Close关闭串口连接
Read从 SerialPort 输入缓冲区中读取数据
Write向 SerialPort 写入数据

Open`​ 打开串口连接打开后一般要设置`DtrEnable、RtsEnable`​为true,具体原因见下文
      xxx.Open();
      xxx.DtrEnable = true;
      xxx.RtsEnable = true;

SerialPort事件

DataReceived指示已通过由 SerialPort 对象表示的端口接收了数据。
ErrorReceived指示由 SerialPort 对象表示的端口上发生了错误。

创建SerialPort对象以及配置参数

方式一

通过对应的属性进行配置

private SerialPort serialPort = new SerialPort();
 
    public SerialPortExample()
    {
        serialPort.PortName = "COM3"; // 设置串口名称
        serialPort.BaudRate = 9600; // 设置波特率
        serialPort.Parity = Parity.None; // 设置奇偶校验
        serialPort.DataBits = 8; // 设置数据位数
        serialPort.StopBits = StopBits.One; // 设置停止位
        serialPort.Handshake = Handshake.None; // 设置握手协议
 
        serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler); // 接收到数据时的事件
    }
方式二

通过构造函数进行配置

SerialPort port = new SerialPort("COM2",9600,Parity.None,8,(StopBits)1);

SerialPort实现串口通信完整例子

public partial class Form1 : Form
{
    // 创建一个全局的串口对象
    readonly SerialPort port = new SerialPort();


    public Form1()
    {
        InitializeComponent();

        // 对串口添加一下配置
        // 单位是bit/s,常见的波特率1s是9600bit,1Byte是8bit  9600bit/8 = 1200字节,也就是1s发送1200个字节
        // 注意波特率不能太大 也不能太小,如果太大了传输的数据不稳定,如果俩端的波特率不一致会导致数据不一致,如果太小了反应太慢
        port.BaudRate = 9600; // 设置波特率

        // 2 StopBits停止位
        // StopBits是一个枚举类型,可选择有1位,1.5位,2位,默认值是1位
        port.StopBits = StopBits.One;

        // 3 DataBits 数据位:  通信中真正的有效信息,数据位可以双方通过约定进行控制 一般可以5、6/7/8
        // 默认值是8位
        port.DataBits = 8;

        // 4 Parity 奇数校检位 只占1位,指定是逻辑高位是奇数或者偶数个,高位就是1,地位就是0
        // 可取值有Parity.None 不采用校检
        // Parity.Odd  奇数校检,保证传输过程汇总高位个数是奇数个
        // Parity.Even 偶数校检,保证传输过程中高位个数是偶数个
        port.Parity = Parity.None;

        // 5 PortName设置连接串口名
        port.PortName = "COM1";

        // 6 Encoding 编码格式,设置显示以什么格式显示
        // 默认16进制格式
        port.Encoding = Encoding.Default;

        // 必须配置的 波特率 和 设置串口
        // 11 接收数据的事件
        port.DataReceived += Port_DataReceived;

    }



    bool isDefault = true; // 代表编码方式 true代表默认编码
    /// <summary>
    /// 接收数据的事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // 接收数据并且显示,
        // 13 port.BytesToRead 从缓存区读取数据的长度
        byte[] bs = new byte[port.BytesToRead];

        // 14 Read 从缓存区读取数据
        port.Read(bs, 0, bs.Length);

        string value = null;
        // 以哪种编码方式展示数据
        this.Invoke((EventHandler)delegate
        {
            if (isDefault)
            {
                // 十六进制
                foreach (var b in bs)
                {
                    value += " " + b.ToString("X"); //X代表16进制
                }
            }
            else
            {
                // GetEncoding("gb2312")  国标2312编码格式
                value = Encoding.GetEncoding("gb2312").GetString(bs);
            }
            this.richTextBox1.AppendText(value+"\r\n");
            this.richTextBox1.ScrollToCaret();

            // DiscardInBuffer 清空缓存区
            port.DiscardInBuffer(); // 清空缓存区
        });

    }



    /// <summary>
    /// 打开串口
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button1_Click(object sender, EventArgs e)
    {
        // 7 IsOpen 当前串口是否是打开状态,
        // true 为打开状态
        // false 关闭状态
        if (!port.IsOpen) // 没打开
        { 
            // 8 打开串口
            port.Open();

            // 9 打开之后 要设置一下俩个属性为true
            // DtrEnable 为true,启用数据终端就绪,发送一个dtr信号。
            port.DtrEnable = true;
            // RtsEnable 为true,证明请求可以发送了,发送一个rts信号
            port.RtsEnable = true;


            button1.Text = "关闭";
        }
        else
        {
            button1.Text = "打开";

            // 10 关闭串口
            port.Close(); 
        }
    }


    /// <summary>
    /// 发送数据
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button3_Click(object sender, EventArgs e)
    {
        byte[] bs = Encoding.UTF32.GetBytes(this.textBox1.Text);
        // 12 Write 发送数据
        port.Write(bs,0,bs.Length);
    }


    /// <summary>
    /// 检测串口
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void DetectionSerialButton_Click(object sender, EventArgs e)
    {
        // 获取电脑下所有串口端口 
        SerialList = System.IO.Ports.SerialPort.GetPortNames();
        if (SerialList.Length!=0)
        {
            this.SerialComboBox.DataSource = SerialList;
            this.SerialComboBox.SelectedIndex = 0;
        }
        else
        {
            MessageBox.Show("未获取到串口!!!","提示",MessageBoxButtons.OK,MessageBoxIcon.Warning);
        }
    
    }

    
}

本文部分借鉴网络,如有侵权请联系删除!!!

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐