1. Modbus RTU协议基础与硬件准备
Modbus RTU是工业自动化领域最常用的通信协议之一,基于RS485总线实现主从式通信。在实际项目中,我经常遇到需要将STM32作为从站设备接入现有Modbus网络的情况。先来聊聊硬件配置,这是整个项目的基础。
RS485硬件电路需要特别注意电平转换和终端匹配。我习惯使用MAX485或SP3485这类芯片,接线时一定要记得在总线两端加120Ω终端电阻,这个电阻能有效抑制信号反射。STM32的USART外设配置为异步模式,波特率常用9600或19200,数据位8位,停止位1位,无校验位。实际测试中发现,波特率误差最好控制在2%以内,否则通信容易出错。
记得有一次在现场调试,设备总是随机出现通信中断,最后发现是RS485芯片的使能引脚切换时机不对。STM32的USART需要配合GPIO控制收发状态,发送前要将DE引脚拉高,发送完成后立即拉低切换为接收状态。这个时间差很关键,太早切换会导致最后一位数据发送不完整,太晚则可能错过主站的查询帧。
2. Modbus协议栈移植与框架搭建
Modbus协议栈的移植是整个项目的核心。我推荐采用模块化设计,将协议处理与硬件层分离。通常我会创建这几个文件:modbus.c(协议处理核心)、modbus_rtu.c(RTU帧处理)、modbus_reg.c(寄存器映射)。
在modbus.c中需要实现协议状态机处理。Modbus RTU的帧间隔要求很严格,3.5个字符时间的静默期是必须遵守的。我一般用定时器来实现超时检测,当收到第一个字节时启动定时器,如果在3.5个字符时间内没有新数据,就认为一帧接收完成。
// 定时器配置示例
void MODBUS_TIM_Init(void)
{
TIM_HandleTypeDef htim;
htim.Instance = TIM2;
htim.Init.Prescaler = 7200; // 72MHz/7200=10kHz
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = 35; // 3.5ms at 9600bps
HAL_TIM_Base_Init(&htim);
HAL_TIM_Base_Start_IT(&htim);
}
CRC校验是保证数据可靠性的关键。我习惯使用查表法来计算CRC16,比直接计算快很多。下面这个CRC表是我从标准Modbus实现中摘录的,在实际项目中验证过无数次:
const uint16_t crc16_table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
// .
1134



被折叠的 条评论
为什么被折叠?



