0
\$\begingroup\$

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 */
\$\endgroup\$
1
\$\begingroup\$

As the comments suggest, you have to define BAUD in the setbaud.h file. Here it says you have to define F_CPU before including setbaud.h file. (That's because setbaud.h uses some macros to calculate UBR0 values based on your required baud rate and operating CPU speed)

\$\endgroup\$
  • \$\begingroup\$ Those macros are set via flags to avr-gcc - see my edit above. Adding explicit define statements at the top of my c code doesn't change the baud rate? \$\endgroup\$ – Tyler Mar 16 '16 at 15:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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