Respuesta inesperada de Atmega16 sobre UART
Breve resumen del problema
He flasheado un Atmega16 con un código que debería dar como resultado que el Atmega16 devuelva cualquier carácter que le envíe a través de un terminal. Recibo una respuesta, pero rara vez es el personaje que envié. Puedo ver la salida correcta cambiando la velocidad en baudios pero no entiendo por qué funciona la velocidad en baudios correcta.
Más detalles
Estoy intentando aprender más sobre la programación de firmware en mi propio tiempo porque lo disfruto bastante. Hasta ahora, en la programación de firmware que he hecho en la universidad, nos han proporcionado archivos de código de esqueleto que hacen una gran parte de la interfaz periférica y se configuran para nosotros, pero me gustaría aprender esto por mí mismo. Tengo algunas preguntas sobre lo que estoy haciendo aquí repartidas a lo largo del post, pero las detallaré al final. Si se entera de cualquier malentendido o posible brecha en mi conocimiento, agradecería enormemente cualquier información que pueda tener.
El código
El código que he flasheado en mi Atmega16 se toma casi línea por línea del tutorial 'Usando el USART en AVR-GCC' encontrado en esta página . Todo lo que he añadido es el #define para F_CPU. El código original no tenía un #define para F_CPU por lo que mi código no se compilaría en AtmelStudio 7. ¿Alguien podría explicar por qué el autor no habría definido F_CPU en su archivo original? Supongo que es posible que hayan estado utilizando alguna otra herramienta o compilador que Atmel Studio 7, pero no puedo decir con certeza.
#include <avr/io.h>
#define F_CPU 7372800 //this was chosen because the tutorial states this is the frequency we want to operate at
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((( F_CPU / 16) + ( USART_BAUDRATE / 2)) / ( USART_BAUDRATE )) - 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 theUBRR 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
}
}
La configuración del hardware
- MCU:Atmega16;
- Cadenadeherramientas:AtmelStudio7,parpadeandoconAVRdragon;
- Fuentedealimentación:rielde5Vtomadodeunaplacadedesarrolloprovistaporlauniversidad(quesetomadesdeunacomputadoraUSB).Condensadordediscocerámicode100nFutilizadoparadesviarlaslíneaseléctricasdelaplacadepruebas
- convertidordeUSBaserie:
Éste . TXD en el convertidor de USB a serie conectado a RXD Atmega (Pin 15). RXD en el convertidor conectado a RXD en Atmega (Pin 14). -
Software de terminal: PuTTY (con una velocidad en baudios de 9600).
Evidencia de las respuestas incorrectas
Para reiterar, el Atmega debería devolver lo que se le envió, es decir, que OUTPUT debería ser exactamente igual a INPUT.
salida PuTTY
\ begin {array} \ hline \ text {ENTRADA} & \ text {SALIDA} \\ \ hline \ text {f} & \ text {&} \\ \ hline \ text {f} & \ text {6} \\ \ hline \ text {z} & \ text {>} \\ \ hline \ text {d} & \ text {0} \\ \ hline \ text {espacio} & \ text {0} \\ \ hline \ text {x} & \ text {8} \\ \ hline \ end {array}
Capturas de osciloscopios
He usado mi Picoscope con decodificación en serie para verificar que el Atmega esté recibiendo la entrada correcta, que parece ser. Por ejemplo, cuando presiono la tecla 'f', se recibe correctamente. La salida sigue siendo un '6' (o un símbolo '&' en ocasiones).
Una solución que encontré y que no entiendo
Si cambio la velocidad en baudios a 2500 en PuTTY, todo se muestra correctamente. Elegí este valor al azar y no sé por qué funciona (me hace creer que he cometido un error en algún lugar relacionado con la velocidad en baudios, pero no veo dónde dado copié el tutorial casi exactamente ... pensamiento).
Preguntas
- ¿Qué he hecho mal / qué está pasando aquí?
- ¿Por qué el tutorial original no # define F_CPU?
- ¿Por qué establecer la velocidad en baudios en 2500 soluciona el problema? (Sospecho que esto será respondido si se responde la pregunta 1)