树莓派4B UART4+TTL/RS485模块Modbus主站通信故障排查
从你的描述来看,核心问题大概率出在**RS485模块的收发控制(RTS驱动DE/RE)**上,以下是具体排查和解决步骤:
确认RTS电平极性与模块匹配
绝大多数廉价TTL-RS485模块的DE/RE引脚是高电平有效(高电平进入发送模式,低电平进入接收模式),但树莓派UART的RTS默认空闲状态可能是低电平,发送时是否会自动拉高?你可以用万用表测GPIO11(RTS引脚)的电平:发送Modbus请求时,电平应该从低变高,发送完成后回落。如果电平没变化,说明硬件流控没生效。检查pyModbus的串口配置
使用UART4(/dev/ttyAMA1)时,必须在pyModbus的SerialClient里明确开启硬件流控:from pymodbus.client import ModbusSerialClient client = ModbusSerialClient( method='rtu', port='/dev/ttyAMA1', baudrate=1200, parity='N', stopbits=1, bytesize=8, timeout=3, rtscts=True # 必须开启这个,才能让UART自动控制RTS )之前用FTDI时没开这个也能工作,是因为FTDI模块自带了自动收发控制,但你的TTL模块需要依赖RTS信号手动切换。
验证UART4的硬件流控是否真的启用
树莓派添加dtoverlay=uart4,ctsrts后,还要确保:- 没有其他进程占用
/dev/ttyAMA1(比如串口控制台),可以用sudo systemctl stop serial-getty@ttyAMA1.service关闭控制台占用 - 检查串口属性:用
stty -F /dev/ttyAMA1 -a查看,输出里应该有crtscts字样,说明硬件流控已启用
- 没有其他进程占用
排查模块供电与电平兼容性
廉价TTL-RS485模块如果是5V供电,树莓派GPIO输出的3.3V电平可能不足以驱动DE/RE引脚(部分模块对高电平阈值要求较高)。可以尝试:- 给模块单独供电(不要用树莓派GPIO的5V,避免压降)
- 加一个3.3V转5V的电平转换模块驱动
DE/RE
手动控制RTS试试(排除硬件流控问题)
如果硬件流控始终不生效,可以放弃自动流控,改用GPIO手动控制RTS:- 把
DE/RE接GPIO11(不要依赖UART的RTS,当作普通GPIO用) - 在pyModbus发送请求前后手动切换电平:
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(11, GPIO.OUT) # 发送前拉高DE/RE,进入发送模式 GPIO.output(11, GPIO.HIGH) response = client.read_holding_registers(address=0, count=1, unit=1) # 发送完成后拉低,回到接收模式 GPIO.output(11, GPIO.LOW)
这种方式更可靠,适合廉价模块的兼容性问题。
- 把
最后排除Modbus参数错误
虽然回环能看到消息,但还是要确认主站和从站的波特率、奇偶校验、停止位、从站地址、寄存器地址完全一致,避免低级错误。
内容的提问来源于stack exchange,提问作者manfre90

