# Setting baud rate for Atmega328p with setbaud.h

I'm working with an Atmega328p, running off the internal 8MHz oscillator, divided by 8 to produce a 1MHz clock. I set the fuses according to the calculator here. Confirming this with avrdude:

avrdude -p m328p -c usbasp

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)

avrdude: safemode: Fuses OK (E:FF, H:D9, L:62)


The timing seems to be correct - blinking an led on and off every 1000 ms takes ca. 1 second, as expected.

I am confused when it comes to setting up serial communication to my computer. No matter what I try, the connection is set to 1200. The program I'm using is:

#include <avr/io.h>
#include <util/delay.h>
#include <USART.h>

int main(void) {
DDRB |= 0b0000001;

initUSART();

while (1) {

printString("\n\r==== Looping ====\n\r");

PORTB = 0b00000001;
_delay_ms(750);

PORTB = 0b00000000;
_delay_ms(250);
}
return (0);
}


Where USART is from Elliott Willams' book. It includes the following:

#include <avr/io.h>
#include "USART.h"
#include <util/setbaud.h>

void initUSART(void) {                                /* requires BAUD */
UBRR0H = UBRRH_VALUE;                        /* defined in setbaud.h */
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);   /* 8 data bits, 1 stop bit */
}

// more code follows, not included here


My Makefile generates the following commands:

avr-gcc -Os -g -std=gnu99 -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums  -ffunction-sections -fdata-sections  -DF_CPU=1000000UL   -DBAUD=9600UL -I. -I../../AVR-Programming-Library -mmcu=atmega328p -c -o blinkLED.o blinkLED.c
avrdude -c usbasp -p atmega328p -P /dev/ttyACM0 -U flash:w:blinkLED.hex


Baud is set in the Makefile, in this case to 9600UL. If I set it to 19200UL, everything works the same. In either case, everything behaves as it should, but when I connect to the serial line from my computer (via screen /dev/ttyUSB0), the output is garbled unless I specify BAUD = 1200. (i.e., screen /dev/ttyUSB0 1200).

I've been struggling through a bunch of webpages, the Williams book, and the atmega datasheet, but I'm still not getting this. Is the baud rate fixed for this chip? If not, how do I set it to a rate higher than 1200?

At this point I actually need to set it any higher, but I'd like to understand how this is supposed to work, and what I'm getting wrong.

# Update

Note that I have explicitly set BAUD and F_CPU with the avr-gcc flags: -DF_CPU=1000000UL -DBAUD=9600UL. Even if I set these macros in the code (as #define BAUD 9600UL and #define F_CPU 1000000UL as the first lines in the file, I'm still stuck with BAUD of 1200.

# Update 2

I have isolated the problem to the setbaud.h file. If I set the baud rate 'by hand', that is, using the following code in place of the call to initUSART(); above, it works as expected - the BAUD is correctly set to 9600. This sets the prescaler to 12 (0b00001100) and enables USE_2X. So my problem must be that I'm using setbaud.h improperly, but I can't see how.

UBRR0H = 0;
UBRR0L = 0b00001100;

UCSR0A |= (1 << U2X0);