Well it certainly has been a long time since I last posted! This however is something I’ve been wanting to try and implement for a long time, I just haven’t got round to it as of yet.
So what is it you ask? How about: The ability to use UART on any pin with edge interrupt detection capability and a free hardware timer! Pretty cool huh?
I’m sure there are more efficient implementations but I’ve tested mine out under a couple of conditions and it seems to able to perform ok so who cares. I’ve managed to get it running at a baud rate up to 57600 and up to 115200 compiling with the O1 flag. Unfortunately, there just ain’t enough processing power using my implementation to work above these baud rates! If I was writing a dedicated UART receiver not using interrupts, I reckon I could get a higher maximum baudrate but my intention here was to be able to write a software UART driver that could receive UART while the CPU was doing other things. I haven’t actually tested it slower than 9600 but I know if I did, I’d need to increase the timer prescaler.
Sending bytes at 9600bps with a 1ms delay/tx. Pulses on channel 2 indicate bit sampling moments.
Moving that up to 57600 shows a few more time constraints though still within spec. The sampling delay after the theoretical bit period is variable in code.
As we get to 115200bps, the sampling periods get much closer together requiring more processing power to grab the bits and store them. O1 optimization is used for this rate.
Finally, at 230400bps, the time between bits is too short, rendering the STM32F0 unable to process the data in time for the next bit.
The software works for continuous bit streams as indicated above at 9600bps.
My code works by detecting the initial falling edge, of which indicates the start bit of a UART transmission. After this start bit, the hardware timer is initialized to fire an interrupt at every bit period and sample the input line. The state of the input line is then shifted into a variable and that variable will eventually be the piece of data received.
In my test implementation, 32 bytes are sent through the USART module and received using my software UART method. I confirmed the correct reception of data with a breakpoint in the infinite loop below the data transmission.
Ensuring the data is correct! Note I’m sending C+10 through my USART TX function, hence why the data starts at 10 and not zero. Why not spice up the test data a bit!
I’ve had a go at doing it using a timer with a period equal to the bit period and using the update interrupt as opposed to moving along the capture compare interrupt and that works too (and probably leads to more efficient code!).
There is a bug which I think is due to generating the USART data on the same chip as I’m receiving it on. For some reason, if I try and receive a byte directly after initialization, it is always perceived as 255. I’ve fixed this by adding a 10ms delay before running my test routine. I don’t have my USB->USART converter to hand at the moment so I can’t fully test this. Adding a 10ms delay however does solve this issue.
Certain features such as parity aren’t included though simple functionality is!
As ever, the code can be found on my github.