MAX485 RS-485 transceiver
A half-duplex RS-485 transceiver between a UART and a shared A/B pair. The simulated part decides which bytes cross between the MCU and the bus, from the levels on DE and /RE at the moment of each byte.
Status at a glance
| Aspect | Status |
|---|---|
| Catalog id | max485 |
| Bus | UART (DI = MCU TX, RO = MCU RX) plus two GPIO pins (DE, /RE) |
| Descriptor | configs/devices/max485.yaml on the uart_transceiver primitive |
| Kit | crates/core/src/peripherals/components/declarative_transceiver.rs |
| Gate model | crates/core/src/peripherals/rs485.rs, hosted by the UART it is wired to |
| Example | examples/arduino-uno-modbus-rtu |
| Tier | modeled (byte level). No line-level analog behaviour. |
Attachment
external_devices:
- id: "rs485"
type: "max485"
connection: "usart0" # the UART DI and RO are wired to
config:
de: "PD2" # pad on DE, or high / low when tied to a rail
re: "PD2" # pad on /RE (active low); same pad as DE is common
Every slave on the A/B pair is one more uart_device attached to the same
UART. Several slaves on one pair is a multi-drop segment: each hears every
frame and answers only its own address.
What it does
| Situation | Result |
|---|---|
| MCU sends, DE low | The byte leaves the MCU pin; no slave hears it. |
| MCU sends, DE high | The byte is on the bus; every slave hears it. |
| DE high and /RE low | Half-duplex echo: the MCU receives its own byte. |
| DE high and /RE high | Driver on, receiver off: no echo. |
| Slave sends, /RE low | The MCU receives the byte. |
| Slave sends, /RE high | The byte is on the bus (see the log) but the MCU does not hear it. |
| Slave sends while DE is high | Collision. The byte is not delivered. |
| Two slaves send in the same interval | Collision. Neither byte is delivered. |
Collisions are counted in the fidelity census as rs485_contention.
The level of DE and /RE is the one at the moment of the UART access. This needs
a GPIO model that can publish a pad level on every write
(Peripheral::watch_pad_level); the AVR ports and the generic GpioPort
(STM32 families, nRF52, Kinetis, EFR32 Series 2, SAM, RA, i.MX RT) do. On a
chip whose GPIO model cannot, the attach fails with an error that names the
pad, instead of sampling late.
The bus log
The UART records every frame that crossed the pair, as rs485:
A test script asserts on it:
Bytes the driver puts on the bus are frames, not console text, so they are in this log and not in the UART console capture.
Limits
- No line-level model: termination, bias, reflections and driver slew are not simulated. Termination resistors in a diagram are parts, but they do not change what the byte-level model delivers.
- Transmission is instant, so firmware drops DE right after
flush(). A master that releases DE too late (while a slave answers) gets a collision, as it would on a real bus; one that releases it too early does not lose its own last character, which hardware would. - A/B across several MCUs, each with its own transceiver, is not joined into one segment in this model. Slaves attach to the UART behind a transceiver.