AVR USART OUTPUT casi similar a la entrada

1

Mi salida es diferente de mi entrada cuando trato de leerla desde mi terminal Hercules. ¿Podría ser esto de una mala inicialización de UART?

Entradas: | á, 1, 123

Salidas: | a, ±, ± ²³

Código:

#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 1000000 // 1 Mhz
#endif

#define USART_BAUDRATE 9600
#define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 16UL ))) - 1)

int main (void)
{
    char ReceivedByte ;
    UCSRB = (1 << RXEN ) | (1 << TXEN ); // Turn on the transmission and reception circuitry
    UCSRC = (1 << URSEL ) | (1 << UCSZ0 ) | (1 << UCSZ1 ); // Use 8-bit character sizes
    UBRRH = ( BAUD_PRESCALE >> 8) ; // Load upper 8-bits of the baud rate value into the high byte
                                    //of the UBRR register
    UBRRL = BAUD_PRESCALE ; // Load lower 8 -bits of the baud rate value into the low byte of the
    //UBRR register
    for (;;) // Loop forever
    {
    while (( UCSRA & (1 << RXC )) == 0) {}; // Do nothing until data have been received and is
    //ready to be read from UDR
    ReceivedByte = UDR ; // Fetch the received byte value into the variable "ByteReceived"
while (( UCSRA & (1 << UDRE )) == 0) {}; // Do nothing until UDR is ready for more data to
//be written to it
UDR = ReceivedByte ; // Echo back the received byte back to the computer
}
}
    
pregunta Napster

1 respuesta

2

Usando números aproximados para 9600 con un reloj de 1 MHz 1000000/9600/16 = 6.51 que se truncará a 6 y luego se bajará a 5 una vez que se reste 1. Puede ver que pierde mucha precisión cuando los números de los divisores son tan pequeños, ya que se convierten en un entero. Aquí hay una calculadora que puede encontrar útil:

Calculadora de velocidad en baudios AVR de WormFood

Eso muestra un error del 7,5% que es demasiado alto, necesitará un 5% más para una operación confiable si el dispositivo al que está conectado es muy preciso, pero normalmente me gusta apuntar a un error del 2% o inferior. Las alternativas que vienen a la mente son cambiar su frecuencia de cristal (o apagar el fusible CKDIV8 si lo está utilizando) o elegir una velocidad en baudios como 4800 que tenga un margen de error aceptable en esa velocidad de reloj.

Aunque mirando más a fondo la tabla (al hacer clic en la casilla de verificación correspondiente), otra opción sería usar el modo U2X=1 que duplica la frecuencia de reloj de UART efectiva que haría caer el error al 0.2%. En ese caso, su código debe incluir:

#define BAUD_PRESCALE ((( F_CPU / ( USART_BAUDRATE * 8UL ))) - 1)
UCSRA |= (1 << U2X);

Eso hace que el receptor muestre la mitad de la frecuencia con la que puede no ser tan confiable, pero podría ser una opción si existe una razón por la que no desee aumentar la velocidad de reloj.

    
respondido por el PeterJ

Lea otras preguntas en las etiquetas