Configuración de la velocidad en baudios para Atmega328p con setbaud.h

0

Estoy trabajando con un Atmega328p, ejecutando el oscilador interno de 8MHz, dividido por 8 para producir un reloj de 1MHz. Puse los fusibles de acuerdo con la calculadora aquí . Confirmando esto con 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)

El tiempo parece ser correcto: parpadear un LED encendido y apagado cada 1000 ms toma ca. 1 segundo, como se esperaba.

Estoy confundido cuando se trata de configurar la comunicación en serie con mi computadora. No importa lo que intente, la conexión está establecida en 1200. El programa que estoy usando es:

#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);
}

Donde USART es del Elliott Willams '. Incluye lo siguiente:

#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

Mi Makefile genera los siguientes comandos:

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 se establece en el Makefile, en este caso a 9600UL. Si lo pongo a 19200UL, todo funciona igual. En cualquier caso, todo se comporta como debería, pero cuando me conecto a la línea serie de mi computadora (a través de screen /dev/ttyUSB0 ), la salida está distorsionada a menos que especifique BAUD = 1200. (es decir, screen /dev/ttyUSB0 1200 ).

He estado luchando en un montón de páginas web, el libro de Williams y la hoja de datos de atmega, pero todavía no entiendo esto. ¿Se ha fijado la velocidad de transmisión para este chip? Si no, ¿cómo lo configuro a una tasa superior a 1200?

En este punto, en realidad necesito hacerlo más alto, pero me gustaría entender cómo se supone que funciona y en qué me estoy equivocando.

Actualizar

Tenga en cuenta que he establecido explícitamente BAUD y F_CPU con los indicadores avr-gcc: -DF_CPU=1000000UL -DBAUD=9600UL . Incluso si configuro estas macros en el código (como #define BAUD 9600UL y #define F_CPU 1000000UL como las primeras líneas en el archivo, todavía estoy atascado con BAUD de 1200.

Actualización 2

He aislado el problema al archivo setbaud.h. Si configuro la velocidad en baudios 'a mano', es decir, utilizando el siguiente código en lugar de la llamada a initUSART(); anterior, funciona como se esperaba: el BAUD está configurado correctamente en 9600. Esto establece el valor de preescala en 12 (0b00001100 ) y habilita USE_2X. Así que mi problema debe ser que estoy usando setbaud.h de manera incorrecta, pero no puedo ver cómo.

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 */
    
pregunta Tyler

1 respuesta

1

Como sugieren los comentarios, debe definir BAUD en el archivo setbaud.h. Aquí dice que tienes que definir F_CPU antes de incluir setbaud.h expediente. (Esto se debe a que setbaud.h utiliza algunas macros para calcular los valores UBR0 en función de la velocidad de transmisión requerida y la velocidad de la CPU de funcionamiento)

    
respondido por el chamod

Lea otras preguntas en las etiquetas