|
|
|
@@ -44,7 +44,12 @@ static volatile uint8_t ModbusHasReceivedValidFrame; |
|
|
|
* 10000 个保持寄存器占用 20000 字节;10000 个线圈按位存储, |
|
|
|
* 占用 1250 字节 |
|
|
|
*/ |
|
|
|
static uint16_t ModbusHoldingRegisters[MODBUS_MAP_ITEM_COUNT]; |
|
|
|
static uint16_t ModbusHoldingRegisters[40000]; |
|
|
|
|
|
|
|
|
|
|
|
#pragma location = ".ccmram" |
|
|
|
#pragma data_alignment = 4 |
|
|
|
__root static uint16_t ModbusRegistersCcm[29999]; |
|
|
|
|
|
|
|
static uint8_t ModbusCoils[(MODBUS_MAP_ITEM_COUNT + 7U) / 8U]; |
|
|
|
|
|
|
|
@@ -92,6 +97,16 @@ static uint16_t ModbusGetU16Be(const uint8_t *data) |
|
|
|
return (uint16_t)(((uint16_t)data[0] << 8U) | data[1]); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 提取一个 24 位无符号整数 |
|
|
|
* @param[in] data 两个字节的数据地址 |
|
|
|
* @return 转换后的 24 位无符号整数 |
|
|
|
*/ |
|
|
|
static uint32_t ModbusGetU24Be(const uint8_t *data) |
|
|
|
{ |
|
|
|
return (uint32_t)((uint32_t)data[0] << 16U|((uint16_t)data[1] << 8U) | data[2]); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 检查连续数据地址范围是否合法。 |
|
|
|
* @param[in] start 起始地址。 |
|
|
|
@@ -542,6 +557,96 @@ static uint16_t ModbusProcessWriteMultipleRegisters( |
|
|
|
return 8U; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 处理读取扩展地址保持寄存器功能码0x48 |
|
|
|
* @param[in] request RTU请求帧 |
|
|
|
* @param[in] requestLength 请求帧长度 |
|
|
|
* @return 待发送响应长度,异常请求返回异常响应长度 |
|
|
|
*/ |
|
|
|
static uint16_t ModbusProcessReadBigHolding( |
|
|
|
const uint8_t *request, |
|
|
|
uint16_t requestLength) |
|
|
|
{ |
|
|
|
uint32_t start; |
|
|
|
uint32_t currentAddress; |
|
|
|
uint16_t quantity; |
|
|
|
uint16_t index; |
|
|
|
uint16_t value; |
|
|
|
|
|
|
|
/* 请求帧:站号1 + 功能码1 + 地址3 + 数量2 + CRC2。 */ |
|
|
|
if (requestLength != 9U) |
|
|
|
{ |
|
|
|
ModbusSlaveStatistics.illegalValueCount++; |
|
|
|
|
|
|
|
return ModbusBuildException( |
|
|
|
request[1], |
|
|
|
MODBUS_EX_ILLEGAL_VALUE); |
|
|
|
} |
|
|
|
|
|
|
|
/* 提取24位起始地址和16位寄存器数量。 */ |
|
|
|
start = ModbusGetU24Be(&request[2]); |
|
|
|
quantity = ModbusGetU16Be(&request[5]); |
|
|
|
|
|
|
|
/* 一次最多读取125个寄存器。 */ |
|
|
|
if ((quantity == 0U) || |
|
|
|
(quantity > MODBUS_READ_REGS_MAX)) |
|
|
|
{ |
|
|
|
ModbusSlaveStatistics.illegalValueCount++; |
|
|
|
|
|
|
|
return ModbusBuildException(request[1],MODBUS_EX_ILLEGAL_VALUE); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* 普通SRAM有40000个寄存器,CCMRAM有29999个寄存器, |
|
|
|
* 总地址范围为0~69998。 |
|
|
|
*/ |
|
|
|
if ((start >= 69999UL) || ((uint32_t)quantity > (69999UL - start))) |
|
|
|
|
|
|
|
{ |
|
|
|
ModbusSlaveStatistics.illegalAddressCount++; |
|
|
|
|
|
|
|
return ModbusBuildException(request[1],MODBUS_EX_ILLEGAL_ADDRESS); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* 组成正常响应帧头。 */ |
|
|
|
ModbusTxFrame[0] = ModbusSlaveAddress; |
|
|
|
ModbusTxFrame[1] = 0x48U; |
|
|
|
ModbusTxFrame[2] = (uint8_t)(quantity * 2U); |
|
|
|
|
|
|
|
for (index = 0U; index < quantity; index++) |
|
|
|
{ |
|
|
|
currentAddress = start + (uint32_t)index; |
|
|
|
|
|
|
|
/* |
|
|
|
* 地址0~39999位于普通SRAM; |
|
|
|
* 地址40000~69998位于CCMRAM。 |
|
|
|
*/ |
|
|
|
if (currentAddress < 40000UL) |
|
|
|
{ |
|
|
|
value = ModbusHoldingRegisters[currentAddress]; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
value = ModbusRegistersCcm[currentAddress - 40000UL]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/* 每个寄存器按照高字节、低字节装入响应帧。 */ |
|
|
|
ModbusTxFrame[3U + index * 2U] = (uint8_t)(value >> 8U); |
|
|
|
ModbusTxFrame[4U + index * 2U] = (uint8_t)(value & 0x00FFU); |
|
|
|
|
|
|
|
} |
|
|
|
/* 添加CRC。 */ |
|
|
|
ModbusAppendCrc( ModbusTxFrame, (uint16_t)(3U + quantity * 2U)); |
|
|
|
|
|
|
|
return (uint16_t)(5U + quantity * 2U); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @brief 校验并分发一帧 Modbus RTU 请求。 |
|
|
|
* @param[in] request RTU 请求帧。 |
|
|
|
@@ -612,6 +717,9 @@ static uint16_t ModbusProcessRequest(const uint8_t *request,uint16_t requestLeng |
|
|
|
return ModbusProcessWriteMultipleRegisters(request, |
|
|
|
requestLength, |
|
|
|
isBroadcast); |
|
|
|
|
|
|
|
case 0x48U://读大地址保持寄存器 |
|
|
|
return ModbusProcessReadBigHolding(request, requestLength); |
|
|
|
|
|
|
|
default://未知功能码 |
|
|
|
ModbusSlaveStatistics.illegalFunctionCount++; |
|
|
|
@@ -832,4 +940,4 @@ void ModbusRetainedRegistersPoll(void) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |