C#中的通信(写单线圈和写多线圈)

写单线圈

if (flag == 5)
{
    List<byte> datas = new List<byte>();
    datas.Add(0x01);
    datas.Add(0x05);
​
    ushort addr = 11;// 起始地址
    datas.Add((byte)(addr / 256));
    datas.Add((byte)(addr % 256));
    datas.Add(0x00);// 表示置为off
    datas.Add(0x00);
​
    datas = CRC16(datas);// Modbus
    SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
    serialPort.Open();
    // 发送读取请求报文
    serialPort.Write(datas.ToArray(), 0, datas.Count);
}
 static List<byte> CRC16(List<byte> value, ushort poly = 0xA001, ushort crcInit = 0xFFFF)
 {
     if (value == null || !value.Any())
         throw new ArgumentException("");
​
     //运算
     ushort crc = crcInit;
     for (int i = 0; i < value.Count; i++)
     {
         crc = (ushort)(crc ^ (value[i]));
         for (int j = 0; j < 8; j++)
         {
             crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ poly) : (ushort)(crc >> 1);
         }
     }
     byte hi = (byte)((crc & 0xFF00) >> 8);  //高位置
     byte lo = (byte)(crc & 0x00FF);         //低位置
​
     List<byte> buffer = new List<byte>();
     buffer.AddRange(value);
     buffer.Add(lo);
     buffer.Add(hi);
     return buffer;
 }

写多线圈

if (flag == 6)
{
    List<byte> datas = new List<byte>();
    datas.Add(0x01);
    datas.Add(0x0F);// 十进制  15
​
    ushort addr = 10;// 起始地址
    datas.Add((byte)(addr / 256));
    datas.Add((byte)(addr % 256));
    // 写入数量:写入多个个寄存器
​
    // 
    List<bool> status = new List<bool>() {
        true, false, true, true, true, false, true, false, true, true 
    };
    // C#设备中已有的状态
    // 逻辑   
​
    // 写了入寄存器数量
    datas.Add((byte)(status.Count / 256));
    datas.Add((byte)(status.Count % 256));
    // 0101 1101    0x5D
    // 0000 0011    0x03
​
​
    // 0001 1101    0x1D
​
    // 0000 0000  数据初始值
​
    // 0000 0001   temp   <<0
    // 0000 0001  第一次或运算结果
​
    // 第二次没有结果   因为为false不用管
    // 0000 0100   temp   <<2
    // 0000 0101  第三次或运算结果
    // 0000 1000   temp   <<3
    // 0000 1101  第四次或运算结果
    // 0001 0000   temp   <<4
    // 0001 1101  第五次或运算结果
​
    List<byte> vbs = new List<byte>();
    //byte data = 0;
    int index = 0;
    for (int i = 0; i < status.Count; i++)
    {
        //status.Count  =10   每8个一个字节
        if (i % 8 == 0)
            vbs.Add(0x00);// 初始值
        index = vbs.Count - 1;
​
        if (status[i])
        {
            // True
            byte temp = (byte)(1 << (i % 8));
            vbs[index] |= temp;
        }
        else
        {
            // False  取反操作
​
        }
    }
    datas.Add((byte)vbs.Count);// 写入字节数
    datas.AddRange(vbs);
​
    datas = CRC16(datas);// Modbus
    SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
    serialPort.Open();
    // 发送读取请求报文
    serialPort.Write(datas.ToArray(), 0, datas.Count);
​
​
    // 连续写
}
static List<byte> CRC16(List<byte> value, ushort poly = 0xA001, ushort crcInit = 0xFFFF)
{
    if (value == null || !value.Any())
        throw new ArgumentException("");
​
    //运算
    ushort crc = crcInit;
    for (int i = 0; i < value.Count; i++)
    {
        crc = (ushort)(crc ^ (value[i]));
        for (int j = 0; j < 8; j++)
        {
            crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ poly) : (ushort)(crc >> 1);
        }
    }
    byte hi = (byte)((crc & 0xFF00) >> 8);  //高位置
    byte lo = (byte)(crc & 0x00FF);         //低位置
​
    List<byte> buffer = new List<byte>();
    buffer.AddRange(value);
    buffer.Add(lo);
    buffer.Add(hi);
    return buffer;
}

读线圈消息帧格式 - 0x01、0x02

请求

响应

写单线圈消息帧 - 0x05

请求 响应

写多线圈消息帧 – 0x0F

请求

响应

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值