4
\$\begingroup\$

I'm using an ATMEGA328p, running from its internal oscillator (divided by 8 = 1MHz).

I've (roughly) measured the oscillator output, using my Salae logic analyser, as ranging from 960KHz to 1000KHz, so it's not awful. I did this using the "Clock output on PORTB0" fuse.

If I set the baud rate to 9,600, it outputs serial at 10,220 baud. (Is this because I'm not using a crystal, or because of quantisation?)

If I either increase F_CPU or decrease USART_BAUDRATE, gradually, the output serial baud does not decrease, until it jumps to 8,800 baud.

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) 

int main(void) {
        // serial port setup
        UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
        UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);
        UBRR0H = (BAUD_PRESCALE >> 8);
        UBRR0L = BAUD_PRESCALE;
        ...

Is there some form of quantisation affecting the output baud?

P.S. I'm using GCC on Linux to compile code, and I'm not using Arduino code/IDE.

\$\endgroup\$

3 Answers 3

7
\$\begingroup\$

As already mentioned, this quantization is fundamental to the architecture, which can only divide the source clock by an integer.

However, your problem is quite avoidable. The ATmega UART can operate in two modes; one where it needs a clock at 16x the baud rate, and another where the clock need only be 8x.

You are using the 16x mode, which means that you need an integer divisor of 62.5 KHz (1 MHz / 16) which will yield 9600 baud. That would be about 6.5 which, is not usable. If you instead divide by 6, you get a theoretical 10417 baud which is further from 9600 than desirable.

However, if you instead use 8x mode, now you can divide 125 KHz to 9600, something the integer 13 approximates very closely to yield 9615 baud.

So the real solution to your problem is to operate the UART in "doublespeed" mode and use 8 rather than 16 in the formula for calculating the divisor. Since the actual division is the programmed value plus one, you would write 12 into the divisor registers.

\$\endgroup\$
12
\$\begingroup\$

It is a fully digital system. It must operate in discrete steps.

This is the formula from the datasheet: enter image description here

UBRR register is 16 bits wide (UBRRL + UBRRH), so it can only lead to 65536 possible baud settings.

Look also at section "24.11. Examples of Baud Rate Setting" and table 24-4 of the datasheet.

\$\endgroup\$
2
\$\begingroup\$

If you own a precise logic analyzer you might want to calibrate the internal clock frequency via OSCCAL (Oscillator Calibration Register) in order to get further precision. Anyways, a crystal oscillator is almost always needed on a clean asynchronous communication.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ While there may be a slight clock error here, the specific issue being asked about has nothing to do with calibration, but is rather fundamental to integer clock division. In actuality ATmegas typically do fine for asynchronous serial communication using the internal oscillator without any additional calibration measures - the actual problem here is that the chip has been misconfigured in a way that would yield a fairly erroneous baud rate even with a perfect source clock. \$\endgroup\$ Commented Oct 20, 2018 at 15:06
  • \$\begingroup\$ @ChrisStratton Alright, I read your answer and it seems to make sense. It’s a programming related issue. I meant to post this as a comment but I have not enough reputation ☹. \$\endgroup\$ Commented Oct 20, 2018 at 15:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.