Просмотр исходного кода

增加了ccram的配置

deepseek
ywh 1 месяц назад
Родитель
Сommit
cac11d26c2
3 измененных файлов: 114 добавлений и 2 удалений
  1. +4
    -0
      EWARM/stm32f407xx_flash.icf
  2. +110
    -2
      Modbus/Src/modbus_rtu_slave.c
  3. Двоичные данные
      Touchwin/工程11.txp

+ 4
- 0
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
};

+ 110
- 2
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)



}
}

Двоичные данные
Touchwin/工程11.txp Просмотреть файл


Загрузка…
Отмена
Сохранить