Mi salida es diferente de mi entrada cuando trato de leerla desde mi terminal Hercules. ¿Podría deberse a una mala inicialización de UART?
Entradas : | a, 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
}
}
Usando números aproximados para 9600 con un reloj de 1MHz 1000000 / 9600 / 16 = 6.51 que se truncará a 6 y luego se reducirá a 5 una vez que se reste 1. Puede ver que pierde mucha precisión cuando los números divisores son tan pequeños que se convierten en un número entero. Aquí hay una calculadora que puede resultarle útil:
Calculadora de tasa de baudios AVR de WormFood
Eso muestra un error del 7,5% que es demasiado alto, necesitará más del 5% para un funcionamiento confiable si el dispositivo al que está conectado es muy preciso, pero normalmente me gusta apuntar a un error del 2% o menos. Las alternativas que vienen a la mente son cambiar la frecuencia de cristal (o apagar el CKDIV8
fusible si lo está usando) o elegir una tasa de baudios como 4800 que tenga un margen de error aceptable a esa tasa de reloj.
Aunque mirando la tabla más a fondo (haciendo clic en la casilla de verificación correspondiente), otra opción sería usar el U2X=1
modo que duplica la frecuencia de reloj UART efectiva que reduciría 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 muestree la mitad de la frecuencia, por lo que puede que no sea tan confiable, pero podría ser una opción si hay una razón por la que no desea aumentar la frecuencia del reloj.
Napster
PedroJ