cancel
Showing results for 
Search instead for 
Did you mean: 

1-Wire timing using UART different from expected on STM32-476RG.

HTD
Senior III

I made a driver for 1-Wire communication using UART in Single Wire Half Duplex mode.

The communication is started by sending a RESET pulse that should last 480us. I read that to do it using UART I should set it up to 9600 baud, 8N1, then send 0xf0. Long story short - I've done that, all using DMA and interrupts, it works. I communicate with my DS18B20 thermometer with no problems. However - I was curious what goes over the wire and I connected an oscilloscope to the TX line. And I see something weird. My reset pulse lasts exactly 520us instead of 480. Then I see DS18B20 doesn't mind that timing and responds with a presence pulse of 120us, that is read over UART as 0xe0. Then the baud rate is changed to 115200 and everything works. However - that 520us is bothering me. WHY?

BTW, it's stable. The sensor is read continuously, when it finishes the last reading it starts the next one. When the reading differs from the previous one it is sent to another UART as text to show the reading on debugging console. But most of the time - the second UART is not used, since the reading doesn't change. So no other interrupts should interfere, except maybe the timer interrupt used for delay, but the code in the handler only watches the counter and nothing else. Also - the timing difference is constant and stable. It's ALWAYS 520us on each measurement. It seems like it's not the code's fault, at least - not because it lags. Maybe I misunderstood how sending bits via UART with 9600 baud rate translates to the pulse width?

The state machine for UART interrupts works like this:

  • set the baud rate to 9600
  • TX: 0xf0
  • RX: test for 0xe0
  • set the baud rate to 115200

That's only the RESET part, then goes the data part, but I'm curious about the reset timing.

EDIT:

OOPS, I did the math, it came out like 520us is what I get from the perfect 9600. It seems like the recommended baud rates were bent to match "standard" UART speeds, but as I can set just anything for my STM32, I set 10416 for REST pulse, and I get the perfect 480us. I set 142857 for the data bits and I get the perfect 70us for a bit. Good to see nothing lags in my code and the UARTS provide exactly what is requested from them. Of course my test 1-Wire sensor works with that slightly higher speeds but now what I see on the oscilloscope is exactly what I would expect.

3 REPLIES 3
gbm
Lead II
  1. Using DMA for sending single byte doesn't make too much sense.
  2. What's you clock configuration? There is a basic problem with HAL clock configuration routines thrashing the calibration data. This may result in significant clock frequency deviation. The way to go with Nucleo-L4 series is to select PLL fed by MSI, enable the LSE and turn on the MSI callibration using LSE (new CubeMX turns it on by default as soon as you enable LSE and use MSI for PLL feeding).
HTD
Senior III
  1. It's actually a couple of bytes. I've done it more like as an exercise. Is it slower than using just HAL_UART_Transmit_IT()? The communication is triggered with an interrupt like couple of times per second in my application (and the app will run on H7 & TouchGFX, dynamic UI).
  2. My clock configuration is default for Nucleo board:

0693W00000NrA2yQAF.pngNow: I calculated EXACT baud rate for specific time slots as: br = 10M / ts[μs]. So, for 480μs reset pulse its 10416 (TX 0xf0), for 70μs it's 142857 (TX 0xff). Now when I check the times on oscilloscope they are perfectly as expected, below my scope reading resolution. So the clocks seem perfect, also no observable lag from my code. For now I don't need it, but when I add some more peripherals and a real time GUI, I need to be sure nothing will introduce any unnecessary lags. I test my setup on Nucleo board because it's quicker and safer. Also, L4 is a bit slower than my target H7, which is a good thing here.

Digging deeper, MAXIM advertises the 1-wire protocol has great elasticity with the timing, being resilient to lags. However - when I target lower times, I give even more lag resilience to the system, since it's more probable that even in case of lags the timing will still fall within acceptable limits.

I'm not sure why the 10 value works in my formula. Like I had 10 bits instead of 9. It's 8N1 - yet sending 0xf0 gives exactly 50% of the calculated time slot for the baud rate.

AguBarriga
Associate

Hi, I'm writing to you from Argentina! I'm working on a project similar to yours. I need to communicate via OneWire using the UART port. Could you please provide me with the firmware you used and the connection diagram?
Thanks!