Modbus-ASCII 协议 + LRC校验

一、Modbus 全部功能码 必考对照表(完整版)

考试必背:区分线圈、离散输入、保持寄存器、输入寄存器读写权限

  • 01 功能码 :读取线圈状态(可读可写),存储 开关量 0/1

  • 02 功能码:读取离散输入状态(只读),传感器开关信号

  • 03 功能码:读取保持寄存器(可读可写),存储数值、温度、压力

  • 04 功能码:读取输入寄存器(只读),下位机采集数据上传

  • 06 功能码:写入单个保持寄存器

  • 16 功能码:写入多个保持寄存器

重点区别 : 线圈是 位存储(0/1状态) ,8个状态占1字节 寄存器是 字存储(数值),1个寄存器=2字节

二、Modbus-RTU 与 Modbus-ASCII 核心区别(简答题满分)

2.1 Modbus-RTU(二进制模式)

  • 传输格式:纯字节流二进制

  • 校验方式:CRC16

  • 帧首尾:无特殊标记,靠时间间隔判定帧结束

  • 效率高、工业最常用

2.2 Modbus-ASCII(字符串模式)

  • 传输格式:ASCII字符串

  • 校验方式:LRC纵向冗余校验

  • 帧头:冒号 :

  • 帧尾:\r\n 回车换行

  • 可读性强、效率低

2.3 帧格式对比

RTU帧:从机地址 + 功能码 + 起始地址 + 长度 + CRC(纯8字节二进制)

ASCII帧:: + 地址功能码数据字符串 + LRC校验 + \r\n

示例::010300000004E0\r\n

三、LRC 校验算法原理 + 逐行代码(必考手写)

3.1 LRC 计算三步流程(背诵)

  1. 对所有有效参与校验字节累加求和

  2. 总和 按8位取反 + 1(补码运算)

  3. 和 0xFF 与运算,强制截断保留8位,得到LRC校验码

3.2 LRC 核心代码(可直接默写)

cs 复制代码
/// <summary>
/// LRC纵向冗余校验(Modbus-ASCII专用)
/// </summary>
public static string CalcLRC(byte[] data)
{
    //1.所有字节累加求和
    uint sum = (uint)data.Sum(x => x);
    //2.8位取反+1  3.截断8位
    uint res = (~sum + 1) & 0xff;
    //返回两位十六进制大写
    return res.ToString("X2");
}

四、ASCII 请求帧组装原理与代码

4.1 组帧规则

  • 所有字节转两位16进制字符串

  • 拼接LRC校验码

  • 头部加 : 尾部加 \r\n

4.2 完整组帧代码

cs 复制代码
public static string GetRequestFrame(byte[] data)
{
    //计算LRC校验
    string lrc = CalcLRC(data);
    //字节数组转十六进制字符串
    string requestData = "";
    foreach (byte b in data)
    {
        requestData += b.ToString("X2");
    }
    //拼接ASCII标准帧格式
    return ":" + requestData + lrc + "\r\n";
}

五、03读取寄存器 业务代码(ASCII)

5.1 读取请求帧组装

cs 复制代码
// 固定格式:从机地址01 + 功能码03 + 起始地址0000 + 读取长度0004
string s2 = GetRequestFrame(new byte[] { 01, 03, 00, 00, 00, 04 });
port.Write(s2);

5.2 响应帧数据解析算法

ASCII返回为字符串,每4个字符代表1个寄存器数值

cs 复制代码
/// <summary>
/// ASCII字符串批量解析为寄存器数值
/// </summary>
public static ushort[] StringToUshort(string s, int valueCount, int startIndex = 7)
{
    //长度校验
    if (valueCount * 4 + startIndex > s.Length)
    {
        throw new ArgumentException("响应字符串个数不够");
    }

    ushort[] bs = new ushort[valueCount];
    for (int i = 0; i < valueCount; i++)
    {
        //截取4位16进制字符串
        string value = s.Substring(startIndex, 4);
        startIndex += 4;
        //转为数值
        bs[i] = Convert.ToUInt16(value);
    }
    return bs;
}

六、06写入单个寄存器 完整代码(考试重点)

6.1 写入帧结构

从机地址(1) + 功能码06(1) + 写入地址(2) + 写入数据(2) 共6字节,再算LRC

6.2 写入核心代码

cs 复制代码
private void button1_Click(object sender, EventArgs e)
{
    byte add = 0x01;         //从机地址
    byte func = 0x06;        //写入功能码
    ushort addres = 0x0010;  //写入寄存器地址
    ushort value = 0x1234;   //写入数值

    //拆分高低字节
    byte[] bs =
    {
        add,
        func,
        (byte)(addres >> 8),   //地址高位
        (byte)(addres & 0xff),  //地址低位
        (byte)(value >> 8),     //数据高位
        (byte)(value & 0xff)    //数据低位
    };
    //生成ASCII帧并发送
    string s = GetRequestFrame(bs);
    port.Write(s);
}

七、串口接收事件代码(ASCII专属)

cs 复制代码
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    int readLength = port.BytesToRead;
    byte[] bs = new byte[readLength];
    port.Read(bs, 0, readLength);
    //ASCII转字符串,去除首尾换行回车
    string s = Encoding.ASCII.GetString(bs).Trim('\r', '\n');
    Console.WriteLine(s);

    //判断是否为03读取响应帧
    if (s.Contains("03"))
    {
        //解析4个寄存器数据
        ushort[] us = StringToUshort(s, 4);
        Console.WriteLine($"{us[0]}:{us[1]}:{us[2]}:{us[3]}");
    }
}

八、RTU与ASCII 终极考点总结(必背)

对比项 Modbus-RTU Modbus-ASCII
传输格式 二进制字节流 字符串
校验方式 CRC16(0xFFFF,0xA001) LRC纵向校验
帧头帧尾 无标识,靠间隔 帧头: : 帧尾:\r\n
效率 高,工业主流 低,可读性强

九、LRC与CRC核心区别

  • CRC16:16位校验、多项式异或、RTU使用

  • LRC:8位累加取反、算法简单、ASCII使用

十、完整初始化代码

cs 复制代码
private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    int readLength = port.BytesToRead;
    byte[] bs = new byte[readLength];
    port.Read(bs, 0, readLength);
    //ASCII转字符串,去除首尾换行回车
    string s = Encoding.ASCII.GetString(bs).Trim('\r', '\n');
    Console.WriteLine(s);

    //判断是否为03读取响应帧
    if (s.Contains("03"))
    {
        //解析4个寄存器数据
        ushort[] us = StringToUshort(s, 4);
        Console.WriteLine($"{us[0]}:{us[1]}:{us[2]}:{us[3]}");
    }
}
相关推荐
做运维的阿瑞16 分钟前
mysql数据库视图笔记:创建、修改、删除与适用场景
数据库·笔记·mysql
@Mike@26 分钟前
12-数据库学习笔记(五种连接算法)
数据库·笔记·学习
韩明君27 分钟前
alacrity学习笔记
笔记·学习
DP DPharness29 分钟前
手机连不上 DSH 时的排错顺序:从 401 到 WebSocket 放行
websocket·网络协议·智能手机
91刘仁德1 小时前
传输层协议深度拆解:端口寻址、UDP 报文与 TCP 可靠性机制全解析
linux·网络·c++·网络协议·tcp/ip·udp·c
傲世仙尊1 小时前
TCP报头全解-序号确认应答与可靠性是一个准数
驱动开发·网络协议·tcp/ip
AIgorithmGEEK1 小时前
[Linux]HTTP 应用层协议全解(中篇)
linux·网络·网络协议·http
ai_xiaogui1 小时前
PanelAI 1.1.1重磅更新:秒级安装脚本优化 + 无公网IP算力节点组网,私有化AI管理平台全面升级
人工智能·网络协议·tcp/ip·api聚合管理·开发者ai一键部署·ai底层架构解析·ai应用快速变现
坤坤子吖1 小时前
Python基础语法学习:函数
开发语言·笔记·python·学习
91刘仁德1 小时前
HTTPS 加密原理与 CA 数字证书:从对称加密到完整通信流程
网络·笔记·网络协议·http·https