3
\$\begingroup\$

Most 2-wire RS485 implementations I have seen use both UART RX and TX pins which works of course. And I have done so.

But I was wondering whether using UART in half-duplex mode is a good alternative that maybe(?) has benefit of cleaner code and reducing pin count.

The application is Modbus ASCII and timing is so clear (3.5 characters) that the switchover (that I do for DataEnable anyway) could be joined with a TransmitEnable.

(Some context: I have had RS485 transmitters with local echo’s on the UART RX line)

\$\endgroup\$
3
  • \$\begingroup\$ What's the question? \$\endgroup\$ Commented Aug 7, 2021 at 11:24
  • \$\begingroup\$ It's a good idea to use HDX for ease of control and EMI. \$\endgroup\$
    – D.A.S.
    Commented Aug 7, 2021 at 12:03
  • \$\begingroup\$ Question: good idea or not. Already finding that it is harder to debug \$\endgroup\$ Commented Aug 7, 2021 at 12:19

3 Answers 3

3
\$\begingroup\$

It might be a good idea if you are in a situation where you need to preserve pins.

But it also then makes some things harder.

You need to switch single MCU pin between RX and TX modes for the single UART wire, in addition of controlling the transmitter/receiver enable pins.

It might also need a pull-up to the data lines so it floats idle between changing direction of MCU pin - some MCUs have internal pull-ups that can stay enabled all the time instead of turning on just when input.

It also makes it impossible to read back what is transmitted by the MCU, so detecting glitches, collisions or errors is not possible.

\$\endgroup\$
12
  • \$\begingroup\$ Actually, the last statement is not quite correct for all MCUs. For example, in STM32, the USART reads back its own data in half-duplex mode provided RX is enabled of course. On the other hand, in STM8, there's no need to disable RX while transmitting in half-duplex mode because own data is not read back automatically. \$\endgroup\$
    – neoxic
    Commented Nov 16, 2021 at 23:02
  • 1
    \$\begingroup\$ @neoxic You misunderstood what I wrote. You say the MCU will receive exactly what it transmits so it can't detect glitches, collisions or errors on the RS-485 bus. I meant the MCU will transmit onto RS-485 bus and receive back what is on RS-485 bus, so it can see if it receives back same thing it sent, or has there been errors because two devices wants to transmit simultaneously on the same bus. And therefore, those errors can't be detected using one MCU pin only for RX and TX. \$\endgroup\$
    – Justme
    Commented Nov 16, 2021 at 23:15
  • \$\begingroup\$ No, I didn't say the MCU will receive exactly what it transmits so it can't detect glitches. I did say it depends on an MCU whether it receives back what it transmits or not in half-duplex mode. In the former case, it WILL be able to check for errors on one-wire bus. In the latter case, it will NOT. \$\endgroup\$
    – neoxic
    Commented Nov 17, 2021 at 3:18
  • \$\begingroup\$ So now you say exactly what I originally said which you claimed was not true? I don't follow. It does not matter what the MCU does in half-duplex mode, whether it receives own transmissions or not, because when using one UART RX/TX wire, the MCU side still does not know if there is a short circuit on RS485 side, as it can't monitor what is on the RS485 side. So using one wire, in neither case, MCU won't be able to detect errors as it won't be listening the actual data on RS485. \$\endgroup\$
    – Justme
    Commented Nov 17, 2021 at 7:52
  • \$\begingroup\$ The ability to receive what is being sent is designed to make it possible for an MCU to detect errors and collisions on the line. If there's a collision (the line is being driven by another TX) or error (short circuit, instability), the receiver will likely receive NOT what the TX has just sent. By comparing the last byte sent with what has been received, the MCU can act accordingly - abort transmission, mute the receiver, wait for a random interval, and resume. But this ability (to receive what is being sent) is MCU dependant. \$\endgroup\$
    – neoxic
    Commented Nov 18, 2021 at 8:08
2
\$\begingroup\$

RS485 already is half-duplex. So, why not introduce a little more to the PHY interface.
It is a good idea if you can find a reliable method to arbitrate RX & TX at local nodes, and arbitration of the bus. Becoming even more proactive, you may introduce a way to detect the contention on the bus. On software side, link layer can happily lose some serious part of the code.
While writing this, it indeed feels like a very interesting idea; something like Ethernet on RS485 PHY, or there must be something already out there.

\$\endgroup\$
11
  • \$\begingroup\$ RS-485 is NOT half duplex. It can operate in half (one direction) or full (bi-directional) duplex at the discretion of the designer. In fact, one of the changes made with '485 from '422 is that an RS-485 driver can drive a diff pair that is double terminated, with 120 ohm resistors at each end of the line. \$\endgroup\$
    – SteveSh
    Commented Aug 7, 2021 at 14:46
  • \$\begingroup\$ @SteveSh: See electronics.stackexchange.com/q/69887/11683 \$\endgroup\$
    – Dave Tweed
    Commented Aug 7, 2021 at 14:49
  • \$\begingroup\$ Thanks @SteveSh! That sounds like a good argument that I may agree. Indeed, standard may state only the electrical spec of RS-485 & RS-422, no need to limit the duplex or protocols, I guess. \$\endgroup\$
    – jay
    Commented Aug 7, 2021 at 15:10
  • \$\begingroup\$ Listening to yourself talk is not a reliable way to detect contention on an RS485 bus. \$\endgroup\$
    – brhans
    Commented Aug 7, 2021 at 15:22
  • 2
    \$\begingroup\$ @JeromeBu1982 About " just combine RX/TX" and "pull-up to the data lines so it floats idle": If UART TX pin cannot be configured as open-drain, then it would need an external buffer. The transceiver device will need a similar consideration. The initial implementation wouldn't be as simple as "just put together", though if the concept gets implemented into devices design, it would be an attractive option, as simple as RS485 and answers those Ethernet may not, I think. \$\endgroup\$
    – jay
    Commented Aug 7, 2021 at 17:31
2
\$\begingroup\$

Hmm... standard Modbus/ASCII does not use a frame break timeout of 3.5 characters worth. That timeout is characteristic of Modbus/RTU. Obviously if you own the implementation of all the nodes, this does not mean much. If your frame RX routine can detect end of frame based on frame contents (variable length frames have the length encoded early in the frame), you probably don't even need to honor the 3.5 characters worth in terms of RX/TX "turning time".

Once upon a time I've written a Modbus library for the PC, and I also happen to know a bit about the 16C550A and compatible UART's - but that knowledge is getting rusty. And I certainly know nothing about UART's occurring in MCU's. Being spoilt by the wasteful approach to pin counts in PC hardware, and having but a rusty fond memory of coding around the 16C550A UART hardware, I don't see what "using the UART in half-duplex mode" could save me in terms of code size or complexity.

That said - if I may suggest something to facilitate half-duplex RS485 operation, it would be using an UART that can steer the RX/TX automatically, by exporting the internal flag called "Transmitter Shift Register Empty" as an external discrete signal, which can be plugged directly into the RS485 level shifter (transceiver).

Note: do not confuse the desired "Transmitter Shift Register Empty" with the "Transmitter Holding Register Empty" = a different status flag in the UART. The former means the byte being currently shifted bitwise onto the line. The latter refers to the FIFO - and the THRE flag becomes active as soon as the FIFO is empty, i.e. while the shift register is still busy shifting out the last byte, i.e. too early for the RS485 transceiver to get disengaged into high Z / listening state.

Some UART implementations can send this signal as an alternative function of the RTS or DTR pins, others have dedicated output pins or can map this to some GPIO. The standard 16C550A only has the TSRE aka TEMT as an internal status flag, but lacks the capability to export this on any output pin. I.e. the 16C550A is not a stellar choice for RS485. As a shiny example of this function done right, I'd like to mention the late OX16C950 UART by Oxford Semiconductor, nowadays no longer manufactured (technical progress has its underside, and there was a string of acquisitions, roughly OX Semi -> PLX -> Avago -> Broadcom). If memory serves, modern UART's by EXAR can do it too, and some LPC SuperIO chips can also support this on some or all UART channels (Fintek, SMSC, maybe some recent ITE and Nuvoton nee Winbond). I don't have a clue about UART's in the various MCU's.

I seem to recall some UART's where this function is flawed - namely I recall an addon PCI board for the PC, with RS485 ports and HW steering, where the UART would switch the transceiver to high-Z (RX) one bit too early, effectively cutting off the stop bit. Which apparently worked fine against other UART's... I don't remember the brand of the UART chip on that board.

I've also seen a board-level design bug (thinko) in some asian industrial PC, where RS485 mode was implemented by driving the transceiver's RX/TX steering pin by the UART's TTL Data TX - so that the transceiver was switching between log.1 and high Z...

This feature, i.e. "TSRE=TEMT for RS485 RX/TX steering" can save you some headache with precise timing in software. It sure is a headache on the PC, especially under some modern OS... whether timing is a headache or not on your particular MCU, that's obviously your own business, YMMV.

\$\endgroup\$
1
  • \$\begingroup\$ You are right: RTU \$\endgroup\$ Commented Aug 8, 2021 at 9:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.