Interrupt driven OneWire bus using USART hardware

The advantage of offloading timing to the USART is CPU utilization and interrupt latency. If you are using a bit-banged OneWire, while each bit is read or written the CPU has to use a busy-wait (ie, delay) to approximate the bit timing. During the busy-wait, your ARM core is tied up doing nothing (CPU utilization). If you want to ensure this timing is always correct, the CPU must lockout interrupts (Interrupt latency, boo!) which could prevent the delay from ending (and therefore the next GPIO operation) at the time its expected.

A more concrete example is the sampling the DS18B20 sensor and running a control algorithm in realtime. Say you have 10 sensors. Each time you sample the temperature it takes 232 OneWire Read+Write slots. At 87usec per slot (not counting the presence pulse), that’s ~20ms per sensor and ~200ms to sample all of your sensors. Now say you need to run the control algorithm at 100Hz. Using a software implementation of OneWire its impossible to run the control algorithm every 10ms AND ensure that each sensor is sampled at the required rate.

Some people also dont like to use delay() :smile:

The external hardware had advantages and disadvantages. Using an external driver is much more robust to harsh conditions, ie, the 2N3904 can withstand up to 40V, while if the onewire bus was connected directly to the STM32 IO pin, voltages over 3.3V will cause damage. If your sending your onewire bus out in the “real world”, ie. not outside of your own PCB, its a good idea to provide some input protection circuitry or you’ll inevitably end up with blown up GPIO ports and a non-functional product.

On the other hand, one of the advantages of the OneWire bus is not needing any more external circuitry than a 4.7K pull-up resistor.

So @timb got me thinking - well, you could probably get the I2C peripheral to do the same thing, but its less suitable because I2C does not perform any clock recovery (ie, there is always a SCL clock toggling and you don’t need it for this application). But all the STM32 uses the same GPIO circuit on each pin, so why cant you use the USART with an open drain driver like with the I2C? Turns out you can - using alternate function open-drain IO instead of AF push-pull. Also, the STM32 USART provides a “half-duplex” mode, where the USART RX is tied internally to the TX pin, enabling a “true” single-pin-only-needs-4.7K-pullup on TX solution.

I’ve pushed updates to my onewirehw branches which adds a drive circuit option to select either the internal STM32 open drain drive on TX, or an external drive circuit solution on TX and RX. If you test this out, be sure to pull my onewirehw branch versions of all core-firmware, core-common-lib and core-communications-lib. Just be sure your onewire voltage does not exceed the core’s 3.3V VCC voltage.

Hers an updated breadboard photo, showing only the 4.7K pullup and TX pin!