Uart Baudrate calculation - am I missing something?

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

in fleurys uart lib, there is a makro to calculate the uart baudrate:

UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000)

Ok. The 0x8000 are for the doublespeed parameter and deleted in uart_init befor setting UBRR.
That makes this formula:

Quote:
((xtalCpu)/((baudRate)*8l)-1)

Now let's calculate:
xtalCpu = 1Mhz = 1000000UL
baudrate = 19200
That results in:
Quote:

= 1000000 / (19200*81) -1
= 1000000 / 1555200 -1
= 0.64 -1
= -0.64
or maybe because of unsigned it is:
= 1-1
= 0 which is written into UBRR

From specification The UBRR at 1MHZ and 19200baud should get a value of '6' at double speed.

What am I missing out here?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it's 8l, not eighty-one... a lower L to indicate the number is of the type long (32 bits).

1000000/(19200*8-1)=1000000/(153600-1)=6.51... which gets truncated to 6.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

whoa. sh**. And I was thinking for half an hour with steam coming out of my ears.
Now I see it. The forum uses a good font. Maybe I should use it in my editor. Because it is almost impossible to see in my editor and in avr studio.

Thanks for the fast help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's the difference between a digit one "1" and a lowercase ell "l". In one formula it is "8l" (eight ell) and in the other "81" (eighty one).

Incidentally I think there is a bias introduced bythis calculation anyway, and the following is better:

		if (DblSpdMode) {
			ubrr = (F_CPU + 4UL*NomBaud)/(8UL*NomBaud) - 1UL;
			ucsra() = _BV(U2X0);
		} else {
			ubrr = (F_CPU + 8UL*NomBaud)/(16UL*NomBaud) - 1UL;
			ucsra() = 0;
		}
		ubrrh() = ubrr >> 8;			
		ubrrl() = ubrr & 0xff;	

Christopher Hicks
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Am I the only one who always use 'L' rather than 'l' so it's less likely to be mis-read as one?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
Am I the only one who always use 'L' rather than 'l' so it's less likely to be mis-read as one?
No you're not - look at my code snippet!

CH
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I also use 'L'. That's maybe the reason why I didn't see the difference in fleurys uart lib.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Incidentally I think there is a bias introduced bythis calculation anyway, and the following is better:

And calculating it by hand is best since those macros don't take into account whether or not the resulting value will produce a baud rate that is within 2% of the value that you want.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I also use 'L'.

Quote:

Am I the only one who always use 'L' rather than 'l'

When in doubt, just go to 'L'.

In my USART apps I [almost] always run at a magic frequency crystal anyway. And even in apps with a configurable baudrate I have a table of pre-calculated UBRR values--only need 8 bits per entry for UBRR_L unless going really, really slow--and I never worry about the formula, or whether I'm sure the preprocessor will carry it all out, and the like. But I'm just an old bit pusher.

And all moot anyway since OP's mention of 1MHz implies internal oscillator...

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Whereas the formula does no rounding, I think you will find that the typical 1,2,4,8,16,20MHz crystals will still calculate the value ok. The magic ones will produce an integer anyway.

But you can always add the rounding to the macro for your peace of mind. Once you have written your "uart.h" it is always available.

I have no great inclination to have to egrep through source files to hard-code F_CPU dependent values.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
And calculating it by hand is best since those macros don't take into account whether or not the resulting value will produce a baud rate that is within 2% of the value that you want.

But an extension of those macros for automatic checking is quite easy:

#define BAUD 9600UL

#define UBRR_VALUE ((F_CPU+BAUD*8)/(BAUD*16)-1)
#define BAUD_REAL  (F_CPU/(16*(UBRR_VAL+1)))
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
 
#if ((BAUD_ERROR<980) || (BAUD_ERROR>1020))
  #error baudrate error is bigger than 2%  
#endif

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a long time ago now, but when I taught the students was often amazed when you spotted a bug in a few seconds that they, as noobs, had fought for several days. Of course, when you've seen those a hundred times you could almost tell which of the "standard bugs" it was by the students oral description.

Those included using the wrong thing when eg accessing elements in arrays:

x = a[1];  // Is written "a index one" but should have been "a index ell"

which is very close to your case above. Imagine that sitting in a loop. The program executes without crashing but the same value is gotten for every iteration. The unexperienced programmer might not realise that the cause is trivial to find, but instead looks for a reason why all elements in the array are equal. The starts to play with the size of the array, and the program will still not crash but only continue to show this perceived strange behaviour.

Oh, the joy of pointing to a line on a printout and say "thats a one, not an ell"...

Another thing that perplexed the noobs was when they mixed up O ("big oh") and 0 (zero). Take a look at your keyboard, and study the distance between the "Oh" and the zero...
Example goes like this

int XO;  /Says "X oh" but the intention was "X zero"

// ... and later...

X0 = 42;   // Here (s)he actually wrote "X zero", but gets an error

As they where convinced that the variable was named "X zero" they fought the error at the assignment, which they didn't understand, instead of realising the cause of the error was elsewhere.
[Examples adjusted for you C people - we actually taught programming using Pascal]

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Whereas the formula does no rounding, I think you will find that the typical 1,2,4,8,16,20MHz crystals will still calculate the value ok.

This is not true. If you look at the baud rate examples table in any AVR datasheet, for any entry with a negative error value the equation without rounding will not be calculated correctly.

Regards,
Steve A.

The Board helps those that help themselves.