As the title impplies, I've ATMEGA64a-au and 12mhz crystal, I set the baud rate to 9600 by these codes:
#define F_CPU 12000000UL
#define FOSC 12000000 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
..
void USART0_Init( unsigned int ubrr )
{
UBRR0H = (unsigned char) (ubrr >> 8);
UBRR0L = (unsigned char) ubrr;
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
void USART1_Init( unsigned int ubrr )
{
UBRR1H = (unsigned char) (ubrr >> 8);
UBRR1L = (unsigned char) ubrr;
UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
// Set frame format: 8data, 1stop bit
UCSR1C = (1 << USBS1) | (3 << UCSZ10);
}
..
USART0_Init(MYUBRR);
USART1_Init(MYUBRR);
It is fine when I work with that baud rate but I've recently come a cross a 115200bd device and I need too change it to that, but when I change this line :
#define BAUD 115200
The AVR Micro controller stops communicating, and I've no idea how to fix it. is it too fast for that device or I'm missing something?
#define MYUBRR FOSC/16/BAUD-1
First of all there is an issue with this formula: it rounds always downwards. You need to round it to near integer, e.g. (FOSC / 16 + BAUD / 2) / BAUD-1
By the way why it is FOSC
and not F_CPU
?
Anyway, you can calculate the error when formula FOSC/16/BAUD-1
is used:
MYUBRR = 12000000/16/115200-1 = 5 (5.51 rounded downwards)
Actual UART speed will be:
F_CPU / 16 / (MYUBRR + 1) = 12000000 / 16 / (5 + 1) = 125000
which is 8.5% higher than required. Communication with receiver-transmitter baud rate difference more than 4.5% is not possible.
But you can set Double Speed Operation mode (refer to section 25.3.2 of the datasheet)
It can be done by setting bit U2X
bit in UCSRA
.
In that case UART clock will be 1/8 of the CPU clock, thus allowing higher UBRR settings:
// divide by 8, not 16
#define MYUBRR ((FOSC / 8 + BAUD / 2) / BAUD - 1)
...
void USART0_Init( unsigned int ubrr )
{
// you can just assign the value to UBRR, compiler will handle all the thighs
UBRR0 = ubrr;
UCSR0A = (1 << U2X0); // enable 2x mode
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
In this case MYUBRR
value will be:
(12000000 / 8 + 115200 / 2) / 115200 - 1 = 12
and actual UART speed will be
12000000 / 8 / (12 + 1) = 115384,6
which gives you less than 0.2% error