#pragma once #include #include /** * @brief * * dep: * basic_type.h * * * TODO: * 目前测试通过的功能码 * 0x04 * 0x10 * */ /*定义Modbus的操作功能码,支持01、02、03、04、05、06、15、16功能码*/ typedef enum { // ReadCoilStatus 读线圈状态(读多个输出位的状态) ModbusOrder01 = 0x01, // ReadInputStatus 读输入位状态(读多个输入位的状态) ModbusOrder02 = 0x02, // ReadHoldingRegister 读保持寄存器(读多个保持寄存器的数值) ModbusOrder03 = 0x03, // ReadInputRegister 读输入寄存器(读多个输入寄存器的数值) ModbusOrder04 = 0x04, // WriteSingleCoil 强制单个线圈(强制单个输出位的状态) ModbusOrder05 = 0x05, // WriteSingleRegister 预制单个寄存器(设定一个寄存器的数值) ModbusOrder06 = 0x06, // WriteMultipleCoil 强制多个线圈(强制多个输出位的状态) ModbusOrder0F = 0x0F, // WriteMultipleRegister 预制多个寄存器(设定多个寄存器的数值) ModbusOrder10 = 0x10, // ReadFileRecord 读文件记录 ModbusOrder14 = 0x14, // WriteFileRecord 写文件记录 ModbusOrder15 = 0x15, // MaskWriteRegister 屏蔽写寄存器 ModbusOrder16 = 0x16, // ReadWriteMultiRegister 读写多个寄存器 ModbusOrder17 = 0x17, // ReadDeviceID读设备识别码 ModbusOrder2B = 0x2B, } ModbusFunctionCode; /*定义接收到指令检测错误时的错误码*/ typedef enum { Modbus_OK = 0x00, InvalidFunctionCode = 0x01, // 不合法功能代码 IllegalDataAddress = 0x02, // 非法的数据地址 IllegalDataValues = 0x03, // 非法的数据值或者范围 SlaveFailure = 0x04, // 从站设备故障 Acknowledgement = 0x05, // 确认 SlaveDeviceBusy = 0x06, // 从属设备忙 MemoryParityError = 0x08, // 存储奇偶性差错 GatewayDisabled = 0x0A, // 不可用网关路径 GatewayResponseFailed = 0x0B // 网关目标设备响应失败 } ModbusStatus; typedef struct { uint8_t deviceid; ModbusFunctionCode functionCode; union { /**********read************/ struct { uint16_t startbit; // bit uint16_t numbit; // bit } O01; // ReadCoilStatus struct { uint16_t startbit; // bit uint16_t numbit; // bit } O02; // ReadInputStatus struct { uint16_t startreg; // byte uint16_t numreg; // reg(一个reg==16bit) } O03; // ReadInputStatus struct { uint16_t startreg; // byte uint16_t numreg; // reg(一个reg==16bit) } O04; // ReadInputStatus /**********write************/ struct { uint16_t startbit; // bit uint16_t numbit; // bit uint8_t bytenum; uint8_t *bit; } O0F; // WriteMultipleCoil struct { uint16_t startreg; // byte uint16_t numreg; // byte uint8_t bytenum; // numreg*2 uint8_t *reg; } O10; // WriteMultipleCoil } d; } ModbusMasterData_t; typedef struct { ModbusFunctionCode functionCode; uint8_t deviceId; union { /**********read_receipt************/ struct { uint8_t bytenum; // bit uint8_t *byte_table; } O01; // ReadCoilStatus struct { uint8_t bytenum; // byte_table uint8_t *byte_table; } O02; // ReadInputStatus struct { uint8_t bytenum; // byte uint8_t *reg; } O03; // ReadInputStatus struct { uint8_t bytenum; // byte uint8_t *reg; } O04; // ReadInputStatus /**********write_receipt************/ struct { uint16_t startbit; uint16_t bitnum; // bit } O0F; // WriteMultipleCoil-->对应01 struct { uint16_t startreg; uint16_t regnum; // byte } O10; // --->对应03 } d; } ModbusSlaveData_t; /** * @brief 生成CRC16校验码 * * @param puckMsg 数据指针 * @param usDataLen 数据长度(不包含CRC16) * @return uint16_t */ uint16_t modbus_gen_crc16(uint8_t *puckMsg, uint8_t usDataLen); /** * @brief 将CRC16校验码添加到数据包中 * * @param puckMsg 数据指针,数据中预留两个位置给CRC16 * @param packetlen 数据长度 */ void modbus_pack_crc_to_packet(uint8_t *puckMsg, uint8_t packetlen); /** * @brief 检查CRC16校验码 * * @param message 数据指针 * @param length 数据长度(包含CRC16) * @return true 校验成功 * @return false 校验失败 */ bool modbus_checkcrc16(uint8_t *message, uint8_t length);