c# 串口通信

文章详细介绍了如何定义串口参数、打开和关闭串口,以及使用ModBus协议发送和接收数据,包括CRC校验。还提到如何在无实际串口时进行调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.定义串口相关参数

SerialPort serialPort4 = new SerialPort();
serialPort4.PortName = "COM4";  //串口号
serialPort4.BaudRate = Convert.ToInt32(9600); //波特率
serialPort4.DataBits = Convert.ToInt32(8);  //数据位
serialPort4.StopBits = (StopBits)1;       //停止位
serialPort4.Parity = Parity.None;            //奇偶校验位
serialPort4.ReadTimeout = 100;                       //超时时间
serialPort4.WriteTimeout = 100;//写入超时500毫秒
serialPort4.DataReceived += SerialPortReceiveData;//接收数据事件

2.打开和关闭串口

if (serialPort4.IsOpen)//判断串口是否已经开启
{
   serialPort4.Close();//关闭串口
}
serialPort4.Open();//打开串口

3.串口发送数据

现在串口通信基本上遵循ModBus协议,

包括:

  • Modbus-Rtu
  • Modbus-Ascii
  • Modbus-Tcp
  • ModbusPlus

本人了解尚浅,只是用过Rtu模式,发送数据为十六进制数据,8个字节。RTU格式后续的命令/数据带有循环冗余校验的校验和。

数据格式一般为

                        从机地址 功能码      寄存器地址             数据           校验

例子:                01            03            00 01                     00 01         CRC

1.在大部分情况下03为读的操作,06为写的操作。不同需要根据相关硬件通信的说明书的指令。

2.寄存器地址需要相关说明书,需要根据实际读取。

3.在功能码为03也就是只读的情况下,数据位操作串口要读取多少个寄存器。上述00 01只是读一个,读取6个改为00 06.

4.功能码为06,是写入操作,修改相关参数,这时候数据位是将某个参数值修改为多少。

5.CRC校验从网上找公式即可,代码会贴在下面

public void SendNormalString(SerialPort serialPort, string data)
{
   try
    {
        serialPort.Encoding = Encoding.ASCII;//字节编码
        byte[] buff = HexStringToBinary(data);//自定义方法,处理发过来的十六进制数据,转为十进制存储
        byte[] crc = new byte[buff.Length - 2];//cRc校验码,根据实际情况是否需要
        serialPort.Write(buff, 0, buff.Length);//写入串口,相当于发送数据给串口
        string message = " " + serialPort.PortName + "=>" + data;
        SerialPortMessageUIShow(message);//自定义方法,将串口发送的数据显示在界面
     }
     catch(Exception ex)
     {
        MessageBox.Show(ex.Message);
     }
}
public static byte[] HexStringToBinary(string hexstring)
{
    string[] tmpary = hexstring.Trim().Split(' ');
    byte[] buff = new byte[tmpary.Length];
    for (int i = 0; i < buff.Length; i++)
    {
        buff[i] = Convert.ToByte(tmpary[i], 16);//转换
    }
    return buff;
}

下面是加上CRC校验码的代码

public void SendNormalString(SerialPort serialPort, string data)
{
   try
    {
        serialPort.Encoding = Encoding.ASCII;//字节编码
        byte[] buff = HexStringToBinary(data);//自定义方法,处理发过来的十六进制数据,转为十进制存储
        byte[] crc = new byte[buff.Length - 2];//cRc校验码,根据实际情况是否需要
        if (buff.Length == 8)
        {
           for (int i = 0; i < 6; i++)
            {
                crc[i] = buff[i];
            }
            crc = CRCCalc(crc);//CRC处理
            buff[6] = crc[0];
            buff[7] = crc[1];
        }
        serialPort.Write(buff, 0, buff.Length);//写入串口,相当于发送数据给串口
        string message = " " + serialPort.PortName + "=>" + data;
        SerialPortMessageUIShow(message);//自定义方法,将串口发送的数据显示在界面
     }
     catch(Exception ex)
     {
        MessageBox.Show(ex.Message);
     }
}

public static byte[] CRCCalc(byte[] data)
{
    //crc计算赋初始值
    int crc = 0xffff;
    for (int i = 0; i < data.Length; i++)
    {
        crc = crc ^ data[i];
        for (int j = 0; j < 8; j++)
        {
            int temp;
            temp = crc & 1;
            crc = crc >> 1;
            crc = crc & 0x7fff;
            if (temp == 1)
            {
                crc = crc ^ 0xa001;
            }
            crc = crc & 0xffff;
        }
    }
    //CRC寄存器的高低位进行互换
    byte[] crc16 = new byte[2];
    //CRC寄存器的高8位变成低8位,
    crc16[1] = (byte)((crc >> 8) & 0xff);
    //CRC寄存器的低8位变成高8位
    crc16[0] = (byte)(crc & 0xff);
    //return crc16;
    return crc16;
}

4.串口接收数据

public static void SerialPortReceiveData(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort serialPort = (SerialPort)sender;
    if (!serialPort.IsOpen) return;
    
    byte[] result = new byte[serialPort.BytesToRead];//读取串口缓冲区的字节数据
    serialPort.Read(result, 0, serialPort.BytesToRead);
    for (int i = 0; i < result.Length; i++)
    {
        str += result[i].ToString("X2") + " ";//将接收的数据转为大写的十六进制
    }
    ReceiveMessage = "\t" + serialPort.PortName + " <= " + str;
}

5.调试串口

在没有相关串口的情况下,我们可以虚拟工具模拟串口通信是否正常。

希望各位大神指点不足之处!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值