# 8051 baud rate calculator using 16-bit timer for software UART timing

I'm making a project in which pulsed laser beam data is sensed through many optical sensors (one sensor per port pin), so essentially, I'm going to be making 4 UARTs to sense this.

Currently I am using an AT89S52 microcontroller with a 22.1184Mhz crystal attached to it, and I used Keil's baud rate calculator and noticed that it couldn't give me a value for low baud rates (like 100bps).

The reason why I'm asking for such low rates is because the data being sent isn't much (maybe 2 bytes every 1/5th of a second), and also, the microcontroller is doing other tasks as well.

I really only need maybe 100bps speed, but I might have to up it to 110bps because that's the next computer standard serial speed?

The question

If I configure the 8051 timer 1 to 16-bit mode, what values do I plug into TH1 and TL1 for 110bps? Remember, I'm doing 4 software UART's here and the one hardware UART is used by other processes, and the timer 1 interrupt needs to be fired at the right time so bits won't be lost.

Details

What I'm trying to do without the need of additional microcontrollers is to implement laser tag. Each player's vest will have different sets of sensors and I'm treating each set of sensors as separate receive-only UARTs and the laser as a transmit-only UART and the wireless remote control is connected to the hardware UART. Since humans don't pull a trigger 1,000x a second, I can get away with making almost every UART at low speed.

• you have no clock divisor mechanisms available to you? – CapnJJ May 23 '18 at 18:18
• "the microcontroller is doing other tasks as well" is actually an argument for higher baud rates, not lower. The sooner you're done transmitting, the better. – Reinderien May 23 '18 at 18:37
• @Reinderien but the software UARTS are apparently being used to receive data - perhaps simultaneously - with other tasks running at the same time. Therefore the lower the baud rate the better. – Bruce Abbott May 23 '18 at 18:45
• @Bruce fair enough. – Reinderien May 23 '18 at 18:51
• @Mike Do you have room/budget for a simple logic IC on your board? – Reinderien May 23 '18 at 20:38

Are you planning to make your UART programmable for both rates, or implement an auto-detect mechanism? 100bps=10ms/bit, 110bps=9.090ms/bit. Does TH1 and TL1 represent the sample clock periods, high and low respectively? Typically, you oversample 16x the bit rate, but, really, as long as you satisfy Nyquist, you can do whatever you want. If oversample 16x and you have a bit period of 9.09ms you need a sample period of 9.09ms/16 = 568.125us, thus assuming 50% duty cycle, 1/2 high and 1/2 low, Th=Tl=284us.

So, not sure if you can do this in SW, but, 22.184MHz = 45.211ns clock period. For 110bps @16x sampling, this translates to 12,566 clock cycles per sample period, and 6,283 clock cycles per Th and Tl. These values are possible with a 16-bit timer

• All rates will be fixed between all devices. I also updated my question to explain why I need low-speed uarts – Mike May 23 '18 at 19:58

Your fosc is 22.1184MHz, or a period of 45.211ns. However, if I read the spec correctly, timer 1 uses fosc/12=1.8432MHz or a period of 542.535ns. 1/110bps = 9.091 ms, but you need to sample at at least 1/220=4.545ms.

4.545ms/542.535ns = 8378. In other words,

$$\frac {22,118,400} {2 \cdot 110 \cdot 12} \approx 8378$$

This is an up counter, so the 16-bit counter must be initialized to -8378, or 0xDF46. So TH=0xDF and TL=0x46.

Accounting for timer management latency is tricky, and depends on how you use the interrupt among other factors, but (a) I won't cover it here, and (b) it doesn't matter since the error would be so small anyway.

• I took a calculator on this, 4.545ms/542.535ns and I got 8377.39. But I am trying to get the best accuracy possible. I also think somehow I need to add the clock cycles to the equation for storing the return address when the timer interrupt is called? – Mike May 23 '18 at 22:03
• Edited. If you care enough to work in fudge factors for timer update latency, the easiest thing is to use a scope. – Reinderien May 23 '18 at 22:23