// ************************************************************************************// // * 输出数据缓冲区 // // ************************************************************************************// typedef struct { // uint16 Reserve; //00 sint16 UDis; //00 电流 (或电压)(客户指定格式) // Bit15表示符号,0-正、1-负 // Bit0~bit14表示数据(RX)。 // 量程>=300:实际值=RX/10; // 量程<300:实际值=RX/100; uint16 Ver; //01 Va.bb.cc sint16 U; //02 电流 (或电压) // 量程>3000:实际值=RX; // 3000>=量程>300:实际值=RX/10; // 300>=量程>30:实际值=RX/100; // 30>=量程>3:实际值=RX/1000 // 3>=量程>0:实际值=RX/10000 uint16 Null1; //03 uint16 Freq; //04 DC保留 uint16 RS485_Addr; //05 默认为:0 uint16 RS485_BaudRate; //06 1—2400bps/2—4800bps/3—9600bps/4—19200bps/默认:3(9600bps) uint16 RS485_Parity; //07 0—无校验/1—奇校验/2—偶校验/默认:0—无校验 uint16 Null2[7]; //9-14 保留 uint16 Uns; //0F 保留 uint16 Un; //16 变送器量程 sint16 UClibZero; //17 直流零点标定 uint16 UClibFullP; //18 直流正满值标定 sint16 UClibFullN; //19 直流负满值标定 sint16 CustZero; //21 客户零点修正值:默认0,两位小数 uint16 CustGain; //22 客户增益修正值:默认10000 uint16 CustType; //23 协议模式 1:中恒协议,其他:信瑞达内部协议 uint16 Null4[12]; //21-34 保留 uint16 FilterSet; //35 滤波深度0~2,保留 uint16 MeterType; //36 交直流类型,保留 uint16 RS485_StopBits; //37 }SysStruct; extern SysStruct Sys; //系统数据 typedef struct { uint16 Reserve; //00 保留位 sint16 RS485_Addr; //00 从机地址0~255、其中0xFF为广播地址、默认:0 // 初始地址为0 uint32 U; //01 客户读,电流 // 只读(0x03),电流占用 2 个寄存 // 器共 4 个字节,有符号数。0001H // 为高 16 位,0002H 为低 16 位数 // 据。负值用补码格式表示。 // 可能会出现数据对其的问题,到时候需要补一个保留位 uint16 Ver; //03 版本号 Va.bb.cc uint16 Null[3]; //04~05 保留 }CustStruct; extern CustStruct Cust; //客户数据区 typedef struct { sint32 UdcIns; //00 直流低通输出瞬时值 sint32 UdcAvg; //03 直流输出,不分段,实际输出的百分比 sint32 Uout; //04 32位的实际输出值,有符号数,自带4位小数的整型 uint16 Un; //05 量程(寄存器地址:0BH) }OrgiStruct; extern OrgiStruct Orgi; #define SYS_DATA_LEN sizeof(SysStruct) #define CUST_DATA_LEN sizeof(CustStruct) #define ORGI_DATA_LEN sizeof(OrgiStruct) #define CFG_DATA_LEN ((CFG_END_ADDR-CFG_START_ADDR+1)*2) /* 系统数据地址定义 */ #define CFG_START_ADDR ((uint16*)&Sys.RS485_Addr-(uint16*)&Sys) // 标定参数起始地址 #define CFG_END_ADDR ((uint16*)&Sys.RS485_StopBits-(uint16*)&Sys) // 标定参数结束地址 #define ORGI_START_ADDR 0 // 原始数据起始地址 #define ORGI_END_ADDR (ORGI_DATA_LEN / 2 - 1) // 原始数据结束地址 // ************************************************************************************************* // * 数据配置数据保存地址 // ************************************************************************************************* #define FLASH_START_ADDR_SYSCFG (0x8000000+0x400*22) // 系统参数保存起始地址,第22页 #define FLASH_START_ADDR_SYSCFG1 FLASH_START_ADDR_SYSCFG // ************************************************************************************************* // * FLASH常数定义 // ************************************************************************************************* #define FLASH_BASE_ADDR ((uint32)0x08000000UL) // FLASH起始地址 // #define FLASH_PAGE_SIZE ((uint32)0x00000400UL) // FLASH页面大小 #define RAM_BASE_ADDR ((uint32)0x20000000UL) // RAM起始地址 #define RAM_END_ADDR ((uint32)0x20000C00UL) // RAM结束地址 对照6.1读取电流数据(支持功能码:0x03) 备注:产品地址默认为1,广播地址为250。 寄存器地址 详情 数据类型 读写 备注 0x0056 读取电流数据 INT16 只写 bit15为符号位:1-负;0-正 bit0~bit14为电流值,电流值=数值/(10^小数点个数),单位为mA. 6.2读取产品参数(0x03) 寄存器地址 详情 数据 类型 读写 备注 0x0001 软件版本号 UINT16 只读 Va.bb.cc 0x0002 直流漏电流 INT16 只读 补码形式,电流值=数值/(10^小数点个数),单位为mA. 0x0003 保留 UINT16 只读 0x0004 保留 UINT16 只读 0x0005 产品地址 UINT16 只读 0x0006 波特率 INT16 只读 1—2400bps 2—4800bps 3—9600bps 4—19200bps 默认为:3-9600bps 0x0007 校验位 UINT16 只读 0—无校验 1—奇校验 2—偶校验 默认为:0-无校验 0x0008 保留 UINT16 只读 0x0009 小数点个数 UINT16 只读 范围:0~3 备注:ADD产品地址,若地址忘记,可用广播地址0xFA读取,使用广播地址时,仅可链接1台传感器。 6.3产品参数设置(0x06) 寄存器地址 详情 数据类型 读写 备注 0x033E INT16 只写 漏电流零点校零 0x0004 范围:1~200 UINT16 只写 产品地址设置 0x0005 范围:1~4 UINT16 只写 波特率设置 0x0006 范围:0~3 UINT16 只写 校验位设置 0x0008 范围:1~3 UINT16 只写 小数位设置 以下内容不对用户开放 6.4读取 产品参数(支持功能码:0x03、0x06) 寄存器地址 详情 数据类型 读写 备注 0x0000 直流电流 UINT16 只读 0x0001 软件版本号 UINT16 只读 Va.bb.cc 0x0002 直流漏电流 INT16 只读 补码形式,电流值=数值/(10^小数点个数),单位为mA. 0x0003 保留 UINT16 只读 0x0004 保留 UINT16 只读 0x0005 产品地址 UINT16 只读 0x0006 波特率 INT16 只读 5—2400bps 6—4800bps 7—9600bps 8—19200bps 默认为:3-9600bps 0x0007 校验位 UINT16 只读 3—无校验 4—奇校验 5—偶校验 默认为:0-无校验 0x0008 保留 UINT16 只读 0x0009 小数点个数 UINT16 只读 范围:0~3 0x000A 保留 UINT16 只读 0x000B 电压零点CCR UINT16 只读 0x000C 正向电压满值CCR UINT16 只读 0x000D 反向电压满值CCR UINT16 只读 0x000E 2.5V零点AD值 UINT16 只读 0x000F 保留 UINT16 只读 0x0010 产品量程 UINT16 只读 0x0011 直流AD零点 INT16 只读 0x0012 保留 UINT16 只读 0x0013 直流AD正斜率 INT16 只读 0x0014 直流AD负斜率 INT16 只读 0x0015 保留 UINT16 只读 0x0016 保留 UINT16 只读 0x0017 保留 UINT16 只读 0x0018 半周期 UINT16 读写 0x0019 采样时间 UINT16 读写 0x001A 采样起始时间 UINT16 读写 0x001B 共模一次(RC)滤波常数 UINT16 读写 0x001C 共模二次(积分)滤波常数 UINT16 读写 0x001D 差模一次(RC)滤波常数 UINT16 读写 0x001E 差模二次(积分)滤波常数 INT16 读写 0x001F 电阻R29值 ohm UINT16 读写 0x0020 反馈线圈匝数 UINT16 读写 6.5修改产品参数、校正(支持功能码:0x06) 寄存器地址 数据 数据类型 读写 备注 0x0004 范围:1~200 UINT16 只写 地址设置 0x0005 范围:1~4 UINT16 只写 波特率设置 0x0006 范围:0~3 UINT16 只写 校验位设置 0x0008 范围:1~3 UINT16 只写 小数位设置 0x000F UINT16 只写 产品量程设置 0x033E INT16 只写 电流零点校正 0x0340 INT16 只写 电流正向校正 0x0342 INT16 只写 电流反向校正 0x00C8 INT16 只写 电压零点校正 0x00C9 INT16 只写 电压正向校正 0x00CA INT16 只写 电压反向显示 修改代码
时间: 2025-06-01 12:07:02 浏览: 28
### 实现寄存器地址的数据读取和设置功能
以下代码示例展示了如何根据提供的寄存器地址(如 `0x0056`、`0x0001` 等)和功能码(如 `0x03`、`0x06`),实现电流数据读取、产品参数读取与设置的功能。
#### 1. 功能码 `0x03`:读取寄存器数据
```c
#include <stdint.h>
#include <string.h>
#define MODBUS_ADDR 1 // 默认从站地址
#define FUNCTION_CODE_READ_HOLDING_REGISTERS 0x03
void ModbusReadHoldingRegisters(uint8_t *pMbBuf, uint8_t u8MbBufLen) {
uint16_t u16Add = 0; // 起始地址
uint16_t u16Num = 0; // 要读取的寄存器个数
uint16_t u16Cnt = 0; // 数据个数
if (u8MbBufLen != 8) { // 判断接收数组长度是否为8字节
return;
}
// 合并接收到的起始地址
u16Add = pMbBuf[2] << 8 | pMbBuf[3];
// 合并接收到的寄存器数量
u16Num = pMbBuf[4] << 8 | pMbBuf[5];
// 构建响应报文
uint8_t ModbusBuf[256]; // 响应缓冲区
uint8_t MdobusTxCnt = 0;
ModbusBuf[MdobusTxCnt++] = pMbBuf[0]; // 发送接收到的从站地址
ModbusBuf[MdobusTxCnt++] = pMbBuf[1]; // 发送功能码
ModbusBuf[MdobusTxCnt++] = u16Num * 2; // 发送数据字节数
for (u16Cnt = 0; u16Cnt < u16Num; u16Cnt++) {
// 模拟读取寄存器数据
uint16_t regValue = ReadRegister(u16Add + u16Cnt); // 根据地址读取寄存器值
ModbusBuf[MdobusTxCnt++] = (regValue >> 8) & 0xFF; // 高字节
ModbusBuf[MdobusTxCnt++] = regValue & 0xFF; // 低字节
}
// 添加CRC校验
CRCSendBuf(ModbusBuf, MdobusTxCnt);
}
uint16_t ReadRegister(uint16_t address) {
// 模拟读取寄存器值
switch (address) {
case 0x0056: // 读取电流数据
return 0x7FFF; // 示例值
case 0x0001: // 软件版本号
return 0x0102; // 示例值
default:
return 0xFFFF; // 无效地址返回错误值
}
}
```
#### 2. 功能码 `0x06`:设置寄存器数据
```c
#define FUNCTION_CODE_WRITE_SINGLE_REGISTER 0x06
void ModbusWriteSingleRegister(uint8_t *pMbBuf, uint8_t u8MbBufLen) {
uint16_t u16Add = 0; // 寄存器地址
uint16_t u16Value = 0; // 写入值
if (u8MbBufLen != 6) { // 判断接收数组长度是否为6字节
return;
}
// 合并接收到的寄存器地址
u16Add = pMbBuf[2] << 8 | pMbBuf[3];
// 合并接收到的写入值
u16Value = pMbBuf[4] << 8 | pMbBuf[5];
// 写入寄存器
WriteRegister(u16Add, u16Value);
// 构建响应报文
uint8_t ModbusBuf[6];
uint8_t MdobusTxCnt = 0;
ModbusBuf[MdobusTxCnt++] = pMbBuf[0]; // 发送接收到的从站地址
ModbusBuf[MdobusTxCnt++] = pMbBuf[1]; // 发送功能码
ModbusBuf[MdobusTxCnt++] = (u16Add >> 8) & 0xFF; // 发送寄存器地址高字节
ModbusBuf[MdobusTxCnt++] = u16Add & 0xFF; // 发送寄存器地址低字节
ModbusBuf[MdobusTxCnt++] = (u16Value >> 8) & 0xFF; // 发送写入值高字节
ModbusBuf[MdobusTxCnt++] = u16Value & 0xFF; // 发送写入值低字节
// 添加CRC校验
CRCSendBuf(ModbusBuf, MdobusTxCnt);
}
void WriteRegister(uint16_t address, uint16_t value) {
// 模拟写入寄存器值
switch (address) {
case 0x0004: // 设置产品地址
SetProductAddress(value);
break;
case 0x0005: // 设置波特率
SetBaudRate(value);
break;
default:
break;
}
}
void SetProductAddress(uint16_t address) {
// 设置产品地址逻辑
}
void SetBaudRate(uint16_t baudRate) {
// 设置波特率逻辑
}
```
#### 3. 串口接收数据事件处理
```c
void MyCom_DataReceived(uint8_t *bData, uint16_t mReceiveByteCount) {
if (mReceiveByteCount >= 6 && bData[1] == FUNCTION_CODE_READ_HOLDING_REGISTERS) {
ModbusReadHoldingRegisters(bData, mReceiveByteCount);
} else if (mReceiveByteCount >= 6 && bData[1] == FUNCTION_CODE_WRITE_SINGLE_REGISTER) {
ModbusWriteSingleRegister(bData, mReceiveByteCount);
}
}
```
---
###
阅读全文