Modbus通信(二)

5.Modbus RTU协议下的异常处理

线圈

1.0x07D0→线圈的单次请求长度  2000个线圈/8=250个字节

寄存器

1.0x007D→寄存器单次请求长度→125个寄存器 

异常功能码:

判断异常则判断异常功能码高位是否为0x80

List<byte> respBytes = new List<byte>();
                    while (respBytes.Count < len * 2 + 5)
                    {
                        //  超时处理  
                        respBytes.Add((byte)serialPort.ReadByte());
                        if (respBytes.Count == 5 && respBytes[1] > 0x80)
                        {
                            break;
                        }
                        Console.WriteLine(respBytes.Count);
                    }
                    serialPort.DiscardInBuffer();// 清空接收缓冲区

 注:写法所占内存空间区别

1.ushort value=100;
  byte[] datas=BitConvert.GetBytes(value);//这种写法是ushort类型,占2个字节
2.byte[] datas=BitConvert.GetBytes(value);//这种写法是int类型,占4个字节
6.ModbusAscii 

6.1格式变换 

起始(: → 3A)+RTU基础报文(包含从站地址,除CRC校验部分,PDU)+LRC+结束字符(换行回车 →0D 0A)

获取ASCII编码数组,对应byte[],所有字符必须大写

6.2 ASCII码和byte之间转换
  //byte->ASCII 重点!!!!
                    //转换每个ASCII码  x:16进制   2:2位
                    var bytestr =bytes.Select(x => x.ToString("X2")).ToList();
                    //分别加头+尾  : → 3A  换行回车 "\r\n"  →0D 0A
                    string str=":"+string.Join("",bytestr) + "\r\n";
                    byte[] bytes1=Encoding.ASCII.GetBytes(str);

                    SerialPort serialPort3 = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
                    serialPort3.Open();
                    serialPort3.Write(bytes1.ToArray(), 0, bytes1.Length);

                    //ASCII->byte 重点!!!!!
                    // 响应 头尾(3个字节)+数据头((6个字节)从站+功能码+长度)+数据(4*4)+LRC校验码(2个字节)
                    byte[] datas = new byte[len * 4 + 11];
                    serialPort3.Read(datas, 0, datas.Length);
                    //获取ASCII码形式
                    string asciiStr= Encoding.ASCII.GetString(datas, 0, datas.Length);
                    List<byte> bytes2= new List<byte>();
                    for (int i = 1; i < asciiStr.Length-2; i+=2)
                    {
                        //输出字符串 “01” “03”
                        string temp = asciiStr[i].ToString() + asciiStr[i + 1].ToString();
                        //转换为16进制
                        bytes2.Add(Convert.ToByte(temp,16));
                    }
                    
                    //LRC校验
                    LRC(bytes2);

                    for (int i = 3; i < bytes2.Count-2; i+=2)
                    {
                        byte[] vb = new byte[2] { bytes2[i + 1], bytes2[i] };
                        ushort v = BitConverter.ToUInt16(vb);// 解析出无符号短整型数据
                        Console.WriteLine(v);
                    }
 7.ModbusTcp

结构:

TransactionID(2个字节 65535)、ProtocolID(2个字节 0x00 0x00)、Length(2个字节 0x00 0x06)、Unit ID(单元标识符 1 字节)

PDU(可变长度)

  • 功能码(Function Code):1 字节(表示操作类型,如读寄存器、写寄存器)。

  • 数据域(Data Field):可变长度,取决于功能码。

 MODBUS TCP 响应帧总长度计算公式:n*2 + 3 + 6 其中 n 是寄存器数量,3是从站+功能码+长度,6是 MBAP 前导

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值