UART en mi atmega328. Registro de datos en el estado USART (UCSR0A) nunca establecido en

Estoy experimentando una pequeña solución de problemas al intentar enviar y recibir datos en el UART de mi atmega. No sé si es porque el ciclo del reloj está mal configurado o si hice una suposición incorrecta de cuál debería ser el código, pero lo tomé de un libro de ejemplo.

Espero escribir datos en el usot y luego simplemente leerlos. Solo estoy tratando de generar un LED por el momento, pero nunca se ilumina, por lo que asumo que mi código nunca sale de usartReadChar().

Estoy trabajando con un atmega328p y la macro pin/registro son de iom328p. La velocidad del reloj está configurada en 1Mh.

La única diferencia con el libro es que usa un atmega168.

Lo que no entiendo es que no estoy bloqueado para enviar datos al usart (el registro de datos de Usart vacío (UDRE0) en realidad siempre está vacío). Pero el bit de recepción completa (RCX0) en el registro de estado (UCSR0A) tampoco se establece nunca. Como si el bit de estado nunca funcionara en absoluto.

He intentado cambiar la velocidad del reloj de la CPU sin suerte. Por cierto, no estoy seguro de cómo calcular la tasa de baudios de mi usart y no estoy seguro de si realmente tiene un impacto en mi código, ya que solo estoy enviando datos desde el AVR localmente. Entonces, ¿necesito sincronizarlo con mi CPU?

Probé muchas variantes de la configuración usartInit(), pero nunca funcionan.

aquí está mi código:

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


  void initUSART(void) {

  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 */
}

char usartReadChar(){
    while(! (UCSR0A & (1 << RXC0))){}

    return UDR0;
}

void usartWriteChar(char data){
    while(! (UCSR0A & (1 << UDRE0))){}

    UDR0 = data;
}

int main(){
    DDRB   = 0xff;

    char data;
    initUSART();
    usartWriteChar('a');

    while(1){
      data = usartReadChar();
// actually, never reach

      PORTB  = (1 << 0);
    }

    return 0;
}

Cuando lo compilo con una tasa de baudios de 9600, no recibo ningún error de advertencia sobre la tasa de baudios. Pero si elijo Baud incorrecto, por supuesto que tengo este tipo de advertencia.

/avr/include/util/setbaud.h:227:4: advertencia: #advertencia "La velocidad en baudios alcanzada es inferior a la permitida" [-Wcpp] # advertencia "La velocidad en baudios alcanzada es inferior a la permitida"

Así que asumo que mi tasa de baudios es correcta. ¿Qué podría estar mal entonces? Su ayuda será muy apreciada. Gracias.

* editar *

Dejé de intentar enviar algo localmente a mi avr. Entonces, para depurar, conecté mi chip FT232R al pin rx y tx de mi atmega, para ver si algo podía salir del registro de estado UCSR0A, y funcionó.

Lo extraño es que en realidad la función de depuración para enviar datos al registro del transmisor no funcionaba en absoluto, incluso si el UCSR0A dice que está ocupado para transmitir datos.

De acuerdo con el libro, los datos enviados desde el programa arduino deben funcionar, pero no funcionó en absoluto conmigo. Pero desde mi FT232, el programa funciona bien, como si el USART no se hubiera inicializado realmente cuando llamé a la instrucción para enviar datos al arte de EE. UU. Pero como todo es sincronizado, sé que esto no es eso.

Encontré muchos temas sobre la configuración de USART en avr, pero nadie dice que pruebe un programa de depuración como en mi libro. Así que me pregunto si en realidad es una característica específica de atmega168. En realidad, no entiendo por qué esto no funciona como dice el libro.

¿Tiene un conector loopback en el puerto serie?
Hola Doxy. No, no he hecho esto. ¿Se trata de colocar dos cables en la línea rx / tx?

Respuestas (1)

No veo dónde pones la F_CPUdefinición correcta, que es obligatoria para setbaud.h.

También tienes que definir la BAUDmacro a usar UBRR(L|H)_VALUE, así:

#define F_CPU 1e6       // 1Mhz clock
#include <avr/io.h>
#include <util/delay.h>

void initUSART(void) {
 #define BAUD 9600
 #include <util/setbaud.h> 
 UBRR0H = UBRRH_VALUE;
 UBRR0L = UBRRL_VALUE;
// ...
}

También puede calcular los UBRRnxvalores con este sitio . Los valores dependen de la velocidad de su reloj y de la configuración del preescalador. En la configuración predeterminada, es simplemente uno, por lo que no se utiliza.

Y no olvide las resistencias pull-up (alrededor de 10K ohmios) en las líneas TX/RX.

Espero que esto ayude.