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 /* Enable USART transmitter/receiver */ 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 avr-gcc -Wl,-Map,blinkLED.map -Wl,--gc-sections -mmcu=atmega328p blinkLED.o ../../AVR-Programming-Library/USART.o -o blinkLED.elf avr-objcopy -j .text -j .data -O ihex blinkLED.elf blinkLED.hex 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); /* Enable USART transmitter/receiver */ UCSR0B = (1 << TXEN0) | (1 << RXEN0); UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8 data bits, 1 stop bit */