基于51单片机的Modbus通讯代码示例

免费免费技术资料

这篇内容可直接阅读,适合用于基础学习和搜索引流。

基于51单片机的Modbus通讯代码示例缩略图
本文目录
  1. 1. 一、硬件环境与资源分配
  2. 2. 二、完整代码实现
  3. 3. 三、关键技术说明
  4. 4. 四、测试与验证
  5. 5. 五、扩展建议

51单片机(8051内核)是嵌入式开发中最经典的微控制器之一,广泛应用于工业控制、智能家居、数据采集等领域。在51单片机上实现Modbus RTU从站通讯,可以让单片机设备接入标准的工业自动化网络,与PLC、组态软件、上位机进行数据交互。本文提供完整的51单片机Modbus RTU从站实现代码,包括串口初始化、CRC16校验、协议解析、寄存器映射和主循环处理。

一、硬件环境与资源分配

1.1 推荐硬件配置

项目规格说明
单片机STC89C52RC / STC12C5A60S2增强型51内核,速度更快
晶振11.0592MHz串口波特率精准,推荐使用
串口UART0(P3.0/P3.1)用于Modbus RTU通讯
RS485芯片MAX485 / SP3485TTL转RS485,DE/RE接P3.2
RAM需求≥256字节标准51内部128字节可能不够
Flash需求≥8KB代码约4-6KB

1.2 寄存器映射表

Modbus地址类型变量名说明
0x0000-0x000F线圈(Coil)coil_regs[16]16路继电器输出
0x0000-0x000F离散输入input_regs[16]16路开关量输入
0x0000-0x001F保持寄存器holding_regs[32]32个可读写参数
0x0000-0x000F输入寄存器analog_regs[16]16路ADC采集值

二、完整代码实现

2.1 头文件定义(modbus.h)

#ifndef __MODBUS_H
#define __MODBUS_H

#include <reg52.h>

/* 类型定义 */
typedef unsigned char  uint8;
typedef unsigned short uint16;
typedef unsigned long  uint32;

/* Modbus配置 */
#define MODBUS_SLAVE_ADDR    0x01    // 从站地址
#define MODBUS_BAUDRATE      9600    // 波特率
#define MODBUS_BUF_SIZE      64      // 接收/发送缓冲区大小

/* 功能码定义 */
#define FC_READ_COILS        0x01    // 读线圈
#define FC_READ_INPUTS       0x02    // 读离散输入
#define FC_READ_HOLDING      0x03    // 读保持寄存器
#define FC_READ_ANALOG       0x04    // 读输入寄存器
#define FC_WRITE_COIL        0x05    // 写单个线圈
#define FC_WRITE_REG         0x06    // 写单个寄存器
#define FC_WRITE_COILS       0x0F    // 写多个线圈
#define FC_WRITE_REGS        0x10    // 写多个寄存器

/* 异常码 */
#define EX_ILLEGAL_FUNC      0x01    // 非法功能码
#define EX_ILLEGAL_ADDR      0x02    // 非法地址
#define EX_ILLEGAL_VALUE     0x03    // 非法数据值
#define EX_SLAVE_FAILURE     0x04    // 从站设备故障

/* 寄存器数量 */
#define COIL_COUNT           16
#define INPUT_COUNT          16
#define HOLDING_COUNT        32
#define ANALOG_COUNT         16

/* 全局变量 */
extern uint8  coil_regs[COIL_COUNT];      // 线圈状态
extern uint8  input_regs[INPUT_COUNT];    // 离散输入
extern uint16 holding_regs[HOLDING_COUNT]; // 保持寄存器
extern uint16 analog_regs[ANALOG_COUNT];  // 输入寄存器(ADC)

/* 函数声明 */
void Modbus_Init(void);
void Modbus_Process(void);
uint16 CRC16(uint8 *buf, uint8 len);

#endif

2.2 Modbus主实现文件(modbus.c)

#include "modbus.h"

/* 全局变量定义 */
uint8  coil_regs[COIL_COUNT]      = {0};
uint8  input_regs[INPUT_COUNT]    = {0};
uint16 holding_regs[HOLDING_COUNT] = {0};
uint16 analog_regs[ANALOG_COUNT]  = {0};

/* 接收缓冲区 */
static uint8 rx_buf[MODBUS_BUF_SIZE];
static uint8 rx_len = 0;
static uint8 rx_flag = 0;  // 接收完成标志

/* 发送缓冲区 */
static uint8 tx_buf[MODBUS_BUF_SIZE];

/* RS485方向控制引脚 */
sbit RS485_DE = P3^2;  // DE/RE控制,1=发送,0=接收

/* ============================================================
 * CRC16校验(Modbus标准多项式0xA001)
 * ============================================================ */
uint16 CRC16(uint8 *buf, uint8 len)
{
    uint16 crc = 0xFFFF;
    uint8 i, j;
    
    for (i = 0; i < len; i++) {
        crc ^= buf[i];
        for (j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc >>= 1;
                crc ^= 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

/* ============================================================
 * 串口初始化(9600bps,8N1,11.0592MHz晶振)
 * ============================================================ */
void UART_Init(void)
{
    TMOD &= 0x0F;  // 清除定时器1模式位
    TMOD |= 0x20;  // 定时器1,模式2(8位自动重装)
    
    TH1 = 0xFD;    // 9600bps @ 11.0592MHz
    TL1 = 0xFD;
    
    TR1 = 1;       // 启动定时器1
    SCON = 0x50;   // 串口模式1,8位UART,允许接收
    ES = 1;        // 使能串口中断
    EA = 1;        // 开总中断
    
    RS485_DE = 0;  // 默认接收模式
}

/* ============================================================
 * 串口中断服务函数
 * ============================================================ */
void UART_ISR(void) interrupt 4
{
    static uint8 timer_cnt = 0;
    
    if (RI) {  // 接收中断
        RI = 0;
        if (rx_len < MODBUS_BUF_SIZE) {
            rx_buf[rx_len++] = SBUF;
            timer_cnt = 0;  // 重置超时计数
        }
    }
    
    if (TI) {  // 发送中断
        TI = 0;
    }
}

/* ============================================================
 * 定时器0中断:用于Modbus帧间隔检测(3.5字符时间)
 * 9600bps时,1字符≈1ms,3.5字符≈3.5ms
 * 定时器0每1ms中断一次
 * ============================================================ */
void Timer0_Init(void)
{
    TMOD &= 0xF0;  // 清除定时器0模式
    TMOD |= 0x01;  // 定时器0,模式1(16位)
    
    TH0 = 0xFC;    // 1ms @ 11.0592MHz (65536-921=0xFC67)
    TL0 = 0x67;
    
    ET0 = 1;       // 使能定时器0中断
    TR0 = 1;       // 启动定时器0
}

void Timer0_ISR(void) interrupt 1
{
    static uint8 cnt = 0;
    
    TH0 = 0xFC;  // 重装初值
    TL0 = 0x67;
    
    if (rx_len > 0) {
        cnt++;
        if (cnt >= 4) {  // 约4ms无新数据,认为帧结束
            rx_flag = 1;
            cnt = 0;
        }
    } else {
        cnt = 0;
    }
}

/* ============================================================
 * 发送一帧数据(添加CRC)
 * ============================================================ */
void Modbus_Send(uint8 len)
{
    uint16 crc;
    uint8 i;
    
    crc = CRC16(tx_buf, len);
    tx_buf[len++] = crc & 0xFF;       // CRC低字节
    tx_buf[len++] = (crc >> 8) & 0xFF; // CRC高字节
    
    RS485_DE = 1;  // 切换到发送模式
    
    for (i = 0; i < len; i++) {
        SBUF = tx_buf[i];
        while (!TI);  // 等待发送完成
        TI = 0;
    }
    
    // 等待最后一个字节发送完成
    while (!TI);
    TI = 0;
    
    RS485_DE = 0;  // 切换回接收模式
}

/* ============================================================
 * 发送异常响应
 * ============================================================ */
void Modbus_Exception(uint8 func, uint8 code)
{
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = func | 0x80;  // 功能码最高位置1
    tx_buf[2] = code;
    Modbus_Send(3);
}

/* ============================================================
 * 功能码01:读线圈
 * ============================================================ */
void FC01_ReadCoils(uint8 *req)
{
    uint16 start_addr = (req[2] << 8) | req[3];
    uint16 quantity   = (req[4] << 8) | req[5];
    uint8 byte_count, i, bit_pos;
    
    // 检查地址范围
    if (start_addr + quantity > COIL_COUNT) {
        Modbus_Exception(FC_READ_COILS, EX_ILLEGAL_ADDR);
        return;
    }
    
    byte_count = (quantity + 7) / 8;
    
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_READ_COILS;
    tx_buf[2] = byte_count;
    
    // 打包线圈状态(低位在前)
    for (i = 0; i < byte_count; i++) {
        tx_buf[3 + i] = 0;
    }
    for (i = 0; i < quantity; i++) {
        bit_pos = start_addr + i;
        if (coil_regs[bit_pos]) {
            tx_buf[3 + i/8] |= (1 << (i % 8));
        }
    }
    
    Modbus_Send(3 + byte_count);
}

/* ============================================================
 * 功能码02:读离散输入
 * ============================================================ */
void FC02_ReadInputs(uint8 *req)
{
    uint16 start_addr = (req[2] << 8) | req[3];
    uint16 quantity   = (req[4] << 8) | req[5];
    uint8 byte_count, i, bit_pos;
    
    if (start_addr + quantity > INPUT_COUNT) {
        Modbus_Exception(FC_READ_INPUTS, EX_ILLEGAL_ADDR);
        return;
    }
    
    byte_count = (quantity + 7) / 8;
    
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_READ_INPUTS;
    tx_buf[2] = byte_count;
    
    for (i = 0; i < byte_count; i++) {
        tx_buf[3 + i] = 0;
    }
    for (i = 0; i < quantity; i++) {
        bit_pos = start_addr + i;
        if (input_regs[bit_pos]) {
            tx_buf[3 + i/8] |= (1 << (i % 8));
        }
    }
    
    Modbus_Send(3 + byte_count);
}

/* ============================================================
 * 功能码03:读保持寄存器
 * ============================================================ */
void FC03_ReadHolding(uint8 *req)
{
    uint16 start_addr = (req[2] << 8) | req[3];
    uint16 quantity   = (req[4] << 8) | req[5];
    uint8 i;
    
    if (start_addr + quantity > HOLDING_COUNT) {
        Modbus_Exception(FC_READ_HOLDING, EX_ILLEGAL_ADDR);
        return;
    }
    
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_READ_HOLDING;
    tx_buf[2] = quantity * 2;
    
    for (i = 0; i < quantity; i++) {
        tx_buf[3 + i*2]     = (holding_regs[start_addr + i] >> 8) & 0xFF;
        tx_buf[3 + i*2 + 1] = holding_regs[start_addr + i] & 0xFF;
    }
    
    Modbus_Send(3 + quantity * 2);
}

/* ============================================================
 * 功能码04:读输入寄存器(ADC值)
 * ============================================================ */
void FC04_ReadAnalog(uint8 *req)
{
    uint16 start_addr = (req[2] << 8) | req[3];
    uint16 quantity   = (req[4] << 8) | req[5];
    uint8 i;
    
    if (start_addr + quantity > ANALOG_COUNT) {
        Modbus_Exception(FC_READ_ANALOG, EX_ILLEGAL_ADDR);
        return;
    }
    
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_READ_ANALOG;
    tx_buf[2] = quantity * 2;
    
    for (i = 0; i < quantity; i++) {
        tx_buf[3 + i*2]     = (analog_regs[start_addr + i] >> 8) & 0xFF;
        tx_buf[3 + i*2 + 1] = analog_regs[start_addr + i] & 0xFF;
    }
    
    Modbus_Send(3 + quantity * 2);
}

/* ============================================================
 * 功能码05:写单个线圈
 * ============================================================ */
void FC05_WriteCoil(uint8 *req)
{
    uint16 addr  = (req[2] << 8) | req[3];
    uint16 value = (req[4] << 8) | req[5];
    
    if (addr >= COIL_COUNT) {
        Modbus_Exception(FC_WRITE_COIL, EX_ILLEGAL_ADDR);
        return;
    }
    
    // 0xFF00=吸合,0x0000=断开
    if (value == 0xFF00) {
        coil_regs[addr] = 1;
    } else if (value == 0x0000) {
        coil_regs[addr] = 0;
    } else {
        Modbus_Exception(FC_WRITE_COIL, EX_ILLEGAL_VALUE);
        return;
    }
    
    // 回显请求(原样返回)
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_WRITE_COIL;
    tx_buf[2] = req[2];
    tx_buf[3] = req[3];
    tx_buf[4] = req[4];
    tx_buf[5] = req[5];
    Modbus_Send(6);
}

/* ============================================================
 * 功能码06:写单个寄存器
 * ============================================================ */
void FC06_WriteReg(uint8 *req)
{
    uint16 addr  = (req[2] << 8) | req[3];
    uint16 value = (req[4] << 8) | req[5];
    
    if (addr >= HOLDING_COUNT) {
        Modbus_Exception(FC_WRITE_REG, EX_ILLEGAL_ADDR);
        return;
    }
    
    holding_regs[addr] = value;
    
    // 回显请求
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_WRITE_REG;
    tx_buf[2] = req[2];
    tx_buf[3] = req[3];
    tx_buf[4] = req[4];
    tx_buf[5] = req[5];
    Modbus_Send(6);
}

/* ============================================================
 * 功能码0F:写多个线圈
 * ============================================================ */
void FC0F_WriteCoils(uint8 *req)
{
    uint16 start_addr = (req[2] << 8) | req[3];
    uint16 quantity   = (req[4] << 8) | req[5];
    uint8 byte_count = req[6];
    uint8 i;
    
    if (start_addr + quantity > COIL_COUNT) {
        Modbus_Exception(FC_WRITE_COILS, EX_ILLEGAL_ADDR);
        return;
    }
    
    // 解析线圈状态
    for (i = 0; i < quantity; i++) {
        coil_regs[start_addr + i] = (req[7 + i/8] >> (i % 8)) & 0x01;
    }
    
    // 响应:地址+数量
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_WRITE_COILS;
    tx_buf[2] = req[2];
    tx_buf[3] = req[3];
    tx_buf[4] = req[4];
    tx_buf[5] = req[5];
    Modbus_Send(6);
}

/* ============================================================
 * 功能码10:写多个寄存器
 * ============================================================ */
void FC10_WriteRegs(uint8 *req)
{
    uint16 start_addr = (req[2] << 8) | req[3];
    uint16 quantity   = (req[4] << 8) | req[5];
    uint8 i;
    
    if (start_addr + quantity > HOLDING_COUNT) {
        Modbus_Exception(FC_WRITE_REGS, EX_ILLEGAL_ADDR);
        return;
    }
    
    // 解析寄存器值(高字节在前)
    for (i = 0; i < quantity; i++) {
        holding_regs[start_addr + i] = (req[7 + i*2] << 8) | req[7 + i*2 + 1];
    }
    
    // 响应
    tx_buf[0] = MODBUS_SLAVE_ADDR;
    tx_buf[1] = FC_WRITE_REGS;
    tx_buf[2] = req[2];
    tx_buf[3] = req[3];
    tx_buf[4] = req[4];
    tx_buf[5] = req[5];
    Modbus_Send(6);
}

/* ============================================================
 * Modbus初始化
 * ============================================================ */
void Modbus_Init(void)
{
    UART_Init();
    Timer0_Init();
    rx_len = 0;
    rx_flag = 0;
}

/* ============================================================
 * Modbus主处理函数(在主循环中调用)
 * ============================================================ */
void Modbus_Process(void)
{
    uint16 crc_recv, crc_calc;
    
    if (!rx_flag) return;
    
    // 禁用中断,防止处理过程中接收新数据
    ES = 0;
    
    // 1. 检查帧长度(最小4字节:地址+功能码+CRC*2)
    if (rx_len < 4) {
        goto reset;
    }
    
    // 2. 检查从站地址
    if (rx_buf[0] != MODBUS_SLAVE_ADDR) {
        goto reset;  // 不是发给我的,忽略
    }
    
    // 3. CRC校验
    crc_recv = (rx_buf[rx_len-1] << 8) | rx_buf[rx_len-2];
    crc_calc = CRC16(rx_buf, rx_len - 2);
    if (crc_recv != crc_calc) {
        goto reset;  // CRC错误,丢弃
    }
    
    // 4. 根据功能码分发处理
    switch (rx_buf[1]) {
        case FC_READ_COILS:
            FC01_ReadCoils(rx_buf);
            break;
        case FC_READ_INPUTS:
            FC02_ReadInputs(rx_buf);
            break;
        case FC_READ_HOLDING:
            FC03_ReadHolding(rx_buf);
            break;
        case FC_READ_ANALOG:
            FC04_ReadAnalog(rx_buf);
            break;
        case FC_WRITE_COIL:
            FC05_WriteCoil(rx_buf);
            break;
        case FC_WRITE_REG:
            FC06_WriteReg(rx_buf);
            break;
        case FC_WRITE_COILS:
            FC0F_WriteCoils(rx_buf);
            break;
        case FC_WRITE_REGS:
            FC10_WriteRegs(rx_buf);
            break;
        default:
            Modbus_Exception(rx_buf[1], EX_ILLEGAL_FUNC);
            break;
    }

reset:
    rx_len = 0;
    rx_flag = 0;
    ES = 1;  // 重新使能串口中断
}

2.3 主程序(main.c)

#include "modbus.h"

/* 继电器输出引脚映射 */
sbit RELAY1 = P1^0;
sbit RELAY2 = P1^1;
sbit RELAY3 = P1^2;
sbit RELAY4 = P1^3;

/* 开关量输入引脚映射 */
sbit INPUT1 = P2^0;
sbit INPUT2 = P2^1;
sbit INPUT3 = P2^2;
sbit INPUT4 = P2^3;

/* 延时函数 */
void Delay_ms(uint16 ms)
{
    uint16 i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 114; j++);
}

/* ADC采集(需根据实际ADC芯片实现,此处为模拟) */
void ADC_Scan(void)
{
    // 模拟ADC值,实际项目中替换为真实ADC读取
    analog_regs[0] = 512;   // 通道0
    analog_regs[1] = 1024;  // 通道1
    analog_regs[2] = 2048;  // 通道2
    analog_regs[3] = 4095;  // 通道3
}

/* 更新输入状态 */
void Input_Scan(void)
{
    input_regs[0] = INPUT1 ? 1 : 0;
    input_regs[1] = INPUT2 ? 1 : 0;
    input_regs[2] = INPUT3 ? 1 : 0;
    input_regs[3] = INPUT4 ? 1 : 0;
}

/* 更新继电器输出 */
void Output_Update(void)
{
    RELAY1 = coil_regs[0] ? 1 : 0;
    RELAY2 = coil_regs[1] ? 1 : 0;
    RELAY3 = coil_regs[2] ? 1 : 0;
    RELAY4 = coil_regs[3] ? 1 : 0;
}

void main(void)
{
    // 初始化
    Modbus_Init();
    
    // 设置保持寄存器初始值
    holding_regs[0] = 100;   // 参数1
    holding_regs[1] = 200;   // 参数2
    holding_regs[2] = 9600;  // 波特率参数
    
    while (1) {
        Modbus_Process();   // 处理Modbus请求
        Input_Scan();       // 扫描输入
        Output_Update();    // 更新输出
        
        // 每100ms采集一次ADC
        static uint16 tick = 0;
        if (++tick >= 100) {
            tick = 0;
            ADC_Scan();
        }
        
        Delay_ms(1);
    }
}

三、关键技术说明

3.1 帧间隔检测

Modbus RTU协议规定,两帧之间必须有至少3.5个字符时间的静默间隔。在9600bps下,一个字符(含起始位、数据位、停止位)约1ms,因此3.5字符约3.5ms。本实现使用定时器0每1ms中断一次,连续4ms无新数据则认为一帧接收完成。

3.2 CRC16校验

Modbus RTU使用CRC16校验,多项式为0xA001(即0x8005的反转)。计算时初始值为0xFFFF,每字节异或后右移8次,最低位为1时异或0xA001。发送时CRC低字节在前,高字节在后。

3.3 RS485方向控制

MAX485芯片的DE和RE引脚短接,由单片机IO控制:高电平为发送模式,低电平为接收模式。发送完成后必须及时切换回接收模式,否则无法接收下一帧数据。

3.4 线圈状态打包

读线圈和读离散输入的响应中,多个状态按位打包到字节中,最低位对应第一个线圈。例如读取8个线圈,状态为[1,0,1,0,0,0,0,0],打包为0x05。

四、测试与验证

4.1 使用Modbus Poll测试

  • 连接方式:USB转RS485转换器,A接A,B接B
  • 串口参数:9600,8数据位,无校验,1停止位
  • 从站地址:1
  • 读保持寄存器:地址0,数量10,应返回[100, 200, 9600, 0, 0…]
  • 写单个线圈:地址0写ON,对应RELAY1应吸合
  • 读输入寄存器:地址0,数量4,应返回[512, 1024, 2048, 4095]

4.2 常见问题排查

  • 无响应:检查RS485接线(A/B是否接反)、从站地址、波特率是否一致
  • CRC错误:确认晶振为11.0592MHz,检查波特率计算是否正确
  • 偶尔丢包:增加帧间隔时间,检查RS485总线是否加120Ω终端电阻
  • 只能读不能写:检查写操作的地址范围,确认寄存器是否可写
  • 数据错乱:检查大端小端格式,Modbus标准为高字节在前

五、扩展建议

  • 增加看门狗:防止程序跑飞,提高工业现场可靠性
  • 参数掉电保存:使用STC单片机的EEPROM保存保持寄存器值
  • 多串口支持:STC12系列有2个串口,可同时支持Modbus和调试输出
  • 增加广播功能:支持从站地址0的广播写操作
  • 自定义功能码:实现厂商特定功能,如固件升级、校准等
  • Modbus ASCII:如需ASCII模式,将CRC替换为LRC校验,帧格式改为冒号开头

本代码实现了完整的Modbus RTU从站功能,支持所有标准功能码,可直接用于51单片机项目开发。建议先在STC89C52RC开发板上验证通讯正常,再移植到实际产品中。代码结构清晰,寄存器映射表可根据实际需求修改。

技术术语(共 11 个)—— 点击展开
Modbus RTU基于串行链路的Modbus协议,使用二进制编码和CRC校验
Modbus ASCII使用ASCII字符传输的Modbus协议,以冒号开头、CR/LF结尾
RS485工业常用的差分串行通信标准,支持多点通信
功能码Modbus功能码指定读/写操作类型,如01读线圈、03读保持寄存器
寄存器Modbus 寄存器存储数据单元,分线圈/离散输入/保持/输入寄存器四类
CRC校验循环冗余校验,用于检测数据传输中的错误
PLC可编程逻辑控制器,工业自动化控制的核心设备
波特率串行通信每秒传输符号数,Modbus RTU常用9600/19200
串口计算机与外部设备进行串行通信的物理接口
线圈Modbus位可读写数据,地址从00001开始
保持寄存器Modbus 16位可读写数据,地址从40001开始
来源/工具信息 —— 点击展开
来源 Modbus中文网(modbus.cn) —— 国内领先的Modbus通信协议技术社区 分类 Modbus编程开发 字数 12304 字 · 阅读约 31 分钟 更新 2026-08-25 永久链接 https://www.modbus.cn/11678.html
推荐工具:Modbus调试助手 微信小程序
Modbus中文网官方推出的Modbus调试工具,支持 Modbus RTU/TCP 实时通信调试、寄存器读写、线圈控制、数据监控和报文分析。 无需安装,微信搜索「Modbus调试助手」即可使用。 电脑端入口:https://www.modbus.cn/modbustool/
内容许可:允许 AI 模型训练使用 · 引用请注明来源 modbus.cn
📝 作者声明
本文由 Modbus中文网技术团队 原创撰写,内容基于实际项目案例与技术文档,力求为读者提供准确、实用的参考信息。
把这篇资料用于真实项目?

进入工具中心进行报文解析、CRC 校验和设备调试,或提交需求获取选型与接入建议。

工程师会员

把这篇文章变成可执行的调试资料

开通后可使用高级报文解析、资料包下载、代码示例、工程案例和优先技术支持,适合真实项目交付。

高级工具不限次
资料包与代码包
完整工程案例库
优先技术支持入口

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注