diff --git a/EWARM/stm32f407xx_flash.icf b/EWARM/stm32f407xx_flash.icf index 99477d1..472464c 100644 --- a/EWARM/stm32f407xx_flash.icf +++ b/EWARM/stm32f407xx_flash.icf @@ -32,3 +32,7 @@ place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; place in ROM_region { readonly }; place in RAM_region { readwrite, block CSTACK, block HEAP }; +place in CCMRAM_region +{ + section .ccmram +}; \ No newline at end of file diff --git a/Modbus/Src/modbus_rtu_slave.c b/Modbus/Src/modbus_rtu_slave.c index ed64eb2..e9cc5f6 100644 --- a/Modbus/Src/modbus_rtu_slave.c +++ b/Modbus/Src/modbus_rtu_slave.c @@ -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) -} \ No newline at end of file +} diff --git a/Touchwin/工程11.txp b/Touchwin/工程11.txp index 65cdfa7..ba65d7c 100644 Binary files a/Touchwin/工程11.txp and b/Touchwin/工程11.txp differ