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

3

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

Estoy esperando escribir datos en el usart y luego leerlos nuevamente. Solo estoy intentando emitir 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 / register son de iom328p. La velocidad del reloj se configura a 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 usuario (el Registro de datos de usuario vacío (UDRE0) siempre está vacío). Pero el bit de recepción completa (RCX0) en el registro de estado (UCSR0A) tampoco se establece. Como si el bit de estado nunca funcionara.

He intentado cambiar la velocidad del reloj de la CPU sin ninguna 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 de 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 velocidad de transmisión de 9600, no aparece ningún error de advertencia sobre la velocidad de transmisión. Pero si elijo Baud equivocado, por supuesto, tengo este tipo de advertencia.

  

/avr/include/util/setbaud.h:227:4: advertencia: #warning "Velocidad de transmisión   alcanzado es menor que el permitido "[-Wcpp] # advertencia" Velocidad de transmisión   El logro es menor al permitido "

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

* edit *

Renuncié a intentar mostrar algo localmente en mi avr. Entonces, para depurar, he conectado mi chip FT232R al pin rx y tx de mi atmega, para ver si algo podría salir del registro de estado UCSR0A, y funcionó.

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

Según el libro, los datos enviados desde el programa arduino deben funcionar, pero no funcionó conmigo. Pero desde mi FT232, el programa está funcionando bien, como si el USART no se hubiera iniciado realmente cuando llamé la instrucción para enviar datos al art. Pero como todo es sincrónico, 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 se despierta como dice el libro.

    
pregunta Mr Bonjour

1 respuesta

3

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

También tienes que definir la macro BAUD para usar UBRR(L|H)_VALUE , como esto:

#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 valores de UBRRnx con este sitio . Los valores dependen de la velocidad de su reloj y del ajuste del prescaler. En la configuración predeterminada, es simplemente uno, por lo que no se utiliza.

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

Espero que esto ayude.

    
respondido por el Ákos Kovács

Lea otras preguntas en las etiquetas