選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 

9.4 KiB

XDM-60T4-E Modbus RTU 从站项目设计

文档版本:2.1(2026-08-03)。本版本按当前 Core/SrcCore/Modbus 和 IAR 工程配置核对,描述的是现行固件实现。

1. 设计目标与边界

本项目运行在 XDM-60T4-E 的 STM32F407 平台上,作为 Modbus RTU 从站,
通过 USART1 接收 TouchWin 或 Modbus Poll 的请求。目标是提供标准线圈/保持
寄存器读写、项目私有功能码、稳定的 RTU 帧边界识别,以及唯一扩展寄存器的
RTC 掉电保持。

本项目的应用代码位于 Core/SrcCore/ModbusCore/OS/Cfg
Core/Src/main.c 负责启动、任务、UART 接收和 RTU 定时器;Core/Modbus
负责协议解析、响应构造和 RTC 备份;Core/OS/Cfg/app_cfg.h 负责通信时序和任务配置。
Drivers/STM32F4xx_HAL_DriverCore/OS 是 HAL 和 uC/OS-II 依赖,不在本设计中重复解释。

角色 责任
TouchWin / Modbus Poll Modbus RTU 主站,发送请求并处理从站响应。
XDM-60T4-E Modbus RTU 从站,完成帧校验、数据访问、异常响应、GPIO 同步和 RTC 保持。
RTC 备份域 只保存私有地址 0x00010000 对应的 16 位扩展寄存器;需要 VBAT 供电。

2. 总体运行思路

主站 RTU 字节流
    -> USART1 接收完成回调
    -> TIM5 T1.5 / T3.5 单次定时
    -> Modbus 帧就绪信号量
    -> Modbus 任务校验并分发功能码
    -> 数据区 / GPIO / RTC 备份
    -> USART1 异步发送响应

系统入口是 Core/Src/main.cmain。它依次完成 HAL、SysTick、系统时钟、
GPIO、USART1 和 TIM5 初始化,然后启动 uC/OS-II。启动任务创建信号量,并创建
Modbus 工作任务和 RTU/链路状态任务;具体函数为 AppTaskStartAppTaskModbus
AppTaskT35

3. 通信与 RTU 时序设计

3.1 串口参数

USART1 使用 115200 bit/s、1 个停止位和偶校验,代码配置为
UART_WORDLENGTH_9B + UART_PARITY_EVEN。在 STM32 HAL 中,这表示 8 位数据加 1 位
校验,主站应配置为 8E1;从站地址为 1。一个字符按 10 bit 计算,因此
APP_MODBUS_BITS_PER_CHARACTER 为 10,字符时间由 app_cfg.h 中的向上取整公式计算。

波特率高于 19200 bit/s 时,RTU 使用固定时序:T1.5 = 750 us
T3.5 = 1750 us。代码还将接收超时设置为 T1.5 + 一个字符时间,并用第二阶段
补足到 T3.5。TIM5 按 1 MHz 计数,因此超时值可以直接以微秒装载。

3.2 接收、封帧与恢复

  • HAL_UART_RxCpltCallback 每次只接收一个字节,
    保存到接收缓冲区后重启静默计时。
  • AppHandleModbusRtuTimer 先处理 T1.5 字符间隔,再确认 T3.5 帧间静默;
    完整帧通过 ModbusFrameSem 交给任务。
  • AppStartUartReception 清空软件帧状态并挂接一个字节的中断接收;
    AppRecoverUartReception 只在 Modbus 任务上下文中执行 Abort、清错和重挂接。
  • TIM5_IRQHandler 只推进 RTU 状态机,USART1_IRQHandler 只调用 HAL;中断中不解析帧,
    也不执行阻塞发送。
  • HAL_UART_ErrorCallback 只停止定时器、标记当前帧无效并设置恢复请求,之后由任务执行恢复。
  • 完整帧正常处理后调用 AppStartUartReception;只有 UART 错误或 HAL 状态丢失时才走完整恢复流程,
    避免清读 SR/DR 时丢掉重连后的首字节。

4. 数据模型与 IAR 调试

数据对象 位置 用途与保持属性
holdingRegisters Core/Src/main.c 地址 0x0000..0x270F 的普通保持寄存器,可在 IAR Live Watch 查看;不保持。
coilStorage Core/Src/main.c 按位压缩的普通线圈区,可在 IAR Live Watch 查看;不保持。
extendedHoldingRegister Core/Src/main.c 私有地址 0x00010000 的唯一扩展值;仅它可被 RTC 保存。

协议层不再维护请求帧、响应帧或数据镜像副本,调试时应直接查看上表三个真实数据对象,
避免镜像数据与协议数据不同步。为便于断线、插拔和 UART 恢复测试,main.c 仍保留
ModbusUartLastErrorCodeModbusUartLastRxStateModbusUartRecoveryCount
ModbusUartRecoveryFailureCountModbusUartRxArmCount
ModbusUartRxArmFailureCountModbusUartLastRxByte
ModbusLastCompleteFrameLength 等运行时诊断变量;这些变量只记录收发恢复过程,
不参与 Modbus 地址映射,也不会作为额外寄存器对外提供。

AppSyncCoilsToGpio 将线圈 1 至 7 写入 Q1 至 Q7。
板级输出为低有效,因此逻辑线圈置 1 时写入 GPIO_PIN_RESET。线圈 0 是链路
数据区中的普通线圈,不参与 Q0/Q1 至 Q7 的输出映射;链路状态线圈 100 和物理
Q0 指示灯由 AppUpdateLinkStatus 根据最近一次有效、已寻址的通信刷新。CRC 错误帧、
非本站号帧和广播读不会刷新在线状态。

5. Modbus 协议核心

协议模块入口是 Core/Modbus/modbus.cModbusProcessFrame。固定的处理
顺序为:参数校验、帧长度、CRC、站号、功能码、字段和地址范围校验。CRC 错误或
非本机站号的帧不会修改数据区。

ModbusCrc16 计算 RTU CRC16,发送时 CRC 低字节在前。ModbusSlaveInit 初始化
普通数据模型,ModbusConfigureExtendedHoldingRegister 绑定扩展保持寄存器,
ModbusGet/SetCoilModbusGet/SetHoldingRegister 提供带地址检查的访问接口。

5.1 标准功能码

功能码 行为 分发位置
0x01 读取线圈,按 Modbus 位顺序打包响应。 ModbusBuildReadCoilsResponse
0x03 读取普通保持寄存器,高字节在前。 ModbusBuildReadRegistersResponse
0x05 写单个线圈,只接受 0xFF000x0000,成功时回显请求。 ModbusProcessWriteSingleCoil
0x06 写单个保持寄存器并回显。 ModbusProcessWriteSingleRegister
0x0F 批量写线圈,校验数量、字节数、帧长度和地址范围。 ModbusProcessWriteMultipleCoils
0x10 批量写保持寄存器,校验数量、字节数、帧长度和地址范围。 ModbusProcessWriteMultipleRegisters

5.2 项目私有功能码

功能码 行为 实现位置
0x41 读取固定 32 位地址 0x00010000,数量必须为 1。 ModbusBuildReadExtendedRegistersResponse
0x42 写入 0x00010000 并回显地址和值。协议核心只改 RAM;应用层确认成功后保存 RTC。 ModbusBuildWriteExtendedRegisterResponse + AppProcessFrame
0x43 从不小于起始基准地址的第一个奇数地址开始,每隔 2 读取一个值;数量必须为 1..123 的奇数。 ModbusBuildReadOddAddressRegistersResponse

私有功能码只供当前 TouchWin 与本 PLC 工程配套使用,不应声明为标准 Modbus
功能码。触摸屏侧的 PSW372..PSW494 最多显示 123 个 0x43 返回值;一次请求只读取
本帧指定的数量,不会自动读取整个 0x0000..0x270F 区间。

6. 掉电保持设计

ModbusBackupSave 在应用层确认 0x42
成功后保存扩展值。写入顺序为:先清除魔数、写扩展值、写版本与 CRC、最后写魔数。
这使掉电中断的半写入记录不会被误认为有效数据。

ModbusBackupRestore 只在 RTC 可访问、
魔数匹配、版本匹配和 CRC 正确时恢复。RTC 访问和 LSI 就绪超时控制在
ModbusBackupEnableRtcAccess,CRC 计算由模块内部函数完成。普通寄存器、
线圈和触摸屏本地显示不会通过该模块恢复。

7. 工程构建与文件边界

IAR 工程文件为 EWARM/Modbus.ewp,实际源文件清单以 IAR 工程配置为准。
业务代码应至少包含 Core/Src/main.cCore/Src/stm32f4xx_it.c
Core/Modbus/modbus.cCore/Modbus/modbus_backup.c,并链接 STM32 HAL、
uC/OS-II 和对应的启动文件。modbus_backup.c 使用 RTC 备份寄存器,因此目标硬件
必须具备有效的 RTC/备份域供电条件。

根目录 test/ 只存放主机测试源码、静态检查脚本和测试支持头文件,不在
EWARM/Modbus.ewp 中引用。交付可运行固件时只需保留 IAR 工程、Core 正式源码、
Drivers、启动文件及必要的工程配置;test/ 可以作为开发归档单独保留或从交付包移除。

8. 验证与维护

验证项 源码或命令位置 目的
协议主机测试 test/modbus_test.c 覆盖 CRC、标准/私有功能码、边界和异常响应;不参与目标固件。
RTC 主机测试 test/modbus_backup_test.c 证明只恢复扩展寄存器,并校验版本和 CRC 失效场景。
运行时主机测试 test/app_runtime_test.c 验证 SysTick 优先级、UART 恢复重试、错误延后恢复和并发恢复请求。
运行时静态检查 test/check_rtu_runtime_invariants.ps1 检查 SysTick 的 OS 感知调用和 UART 恢复边界。
通信计数静态检查 test/check_no_communication_counters.ps1 确认接收、发送和错误计数逻辑未重新引入。
目标构建 使用 IAR 对 EWARM/Modbus.ewp 执行 Modbus 配置构建 验证目标工程实际可编译,要求 0 errors、0 warnings。

构建产生的 Obj/.map.out.sim.dep、主机测试 .exe
*.stackdump 都是可重建产物,已通过 .gitignore 排除。可下载的
EWARM/Modbus/Exe/Modbus.hex 保留在工程中。