I've been working tirelessly for the last several weeks on creating a Serial connection (UART) between an Arduino Uno and another device at 375k baud. The other device is established and custom-created and has been solid and reliable for years. Basically, the system as it currently stands has two different components running at clock speed 6MHz. They are connected by a UART Serial connection, using baud 375k (0% error). This connection is reliable and works without fail.
I am trying to insert a Arduino Uno in between the two components: so the first component sends data to my Uno, which then passes this data along to the second component. Because both components are running at 375k, my Uno must also run at 375k to be able to interface with these components.
My first goal was to receive data from the first component and display it on an LCD shield. So far, I was able to do so with a Leonardo at 16MHz with relative success, but the bits sent latest in the transmission would often become jumbled. Based on another forum post, I determined that my Leonardo's error rate at 16MHz with a 375k baud rate was just barely beyond what the original system could handle. The Leonardo was handling the first few bits in the transmission correctly, but the later ones would get mixed.
To test this theory, I finally got access to an oscilloscope and I decided to read signals from both the first component and my Leonardo to see how long each bit was held. I repeatedly sent 0x55, because this would alternate bits and make it easier to read and calculate. From the first component, I got a bit-width of 2.67usec (nearly exactly the expected value). I checked my Leonardo at 16MHz and got 2.48usec (3.7% error). According to documentation for the first device, 1.5% error is the maximum error that the system can handle without data being corrupted. So this seemed to prove my theory.
For there, I grabbed an Arduino Uno using an external oscillator of 12MHz. According to the formulas provided in the datasheet for the Atmega328p, I confirmed that a 12MHz should work with a 0% error for a baud rate 375k. This was also fair to assume because the 6MHz device I was using had a 0% error and 12 is simply a multiple of 6, so the process of dividing the clock signal should be nearly identical.
Here are my calculations that suggests that there should be a 0% error for the Atmega at 12MHz:
UBRRn = (fosc/(BAUD16)) - 1
UBBRn = (12M/375k16) - 1
UBBRn = 2 - 1 = 1 (A whole number is a good sign!)
error = ((BaudRateclosest match/BaudRate) - 1)2 * 100%
error = ((375k/375k) - 1)2 * 100%
error = (1-1)2* 100%
error = 0% 0% Error!
From here, I checked my Arduino Uno using the oscilloscope and determined each bit was held for 2.0usec. This is nearly 25% error (when I expected 0%)! This does not make sense to me. Out of curiosity, I tried some alternative baud rates on the Arduino side to see what the Uno outputs. A baud rate of 280,900 yielded a bit width of 2.48usec (better but not good enough). A baud rate of 275,000 yielded a bit width of 2.98usec (this is too large). I could not get anything better in between these two values (as I expected with a clock speed like this).
So in summary, this doesn't make a whole lot of sense to me because the Atmega328p should be able to perfectly handle this baud rate when run at 12MHz. Does anyone have any idea why this is failing? I feel like the Arduino libraries that sit above the Atmega328p's Hardware Serial should have no bearing on this because it is a hardware defined protocol, but I could be wrong.
Any ideas or insights?
Thank you all in advance!