¿Por qué mi AVR actúa de manera extraña (reinicios, corrupción de datos) cuando recibe algunos bytes en el UART?

Tengo un ATmega644 conectado a otro dispositivo mediante la UART. Después de recibir algunos caracteres en el UART, el dispositivo se reinicia y/o actúa de manera extraña. Algunos ejemplos de este comportamiento:

  • El código antes de que el ciclo principal se ejecute nuevamente pero MCUSR es 0 (es decir, no hay reinicio "real")
  • El código dentro del bucle principal se ejecuta aunque los interruptores conectados a las entradas no se hayan presionado (los pullups están configurados correctamente).
  • A veces, la MCU simplemente se cuelga
  • A veces, los puertos que no estaban configurados como salidas actúan como salidas (por ejemplo, los LED conectados a ellos se encienden aunque la memoria DDR de ese puerto sea 0).

El dispositivo utiliza un cristal externo de 18,432 MHz y el UART está configurado en 19200 baudios. Se alimenta con 5V; el pin RX está conectado a un 3V3 RPi.

Respuestas (4)

Incluso si el problema con esta configuración en particular fuera otra cosa (como se señala en otra respuesta), otra razón común es que el controlador se está operando fuera del "área de operación segura" con respecto a la velocidad del reloj Vcc VS.

atmega644 Vcc VS velocidad de reloj

Con una velocidad de reloj de 18,432 MHz, el dispositivo requeriría al menos unos 4,2 V para funcionar correctamente.

El comportamiento intermitente es a menudo el resultado de tapas de desacoplamiento de energía faltantes o insuficientes cerca de su controlador. Como regla general, 100 nF para cada pin etiquetado como Vcc, lo más cerca posible de los pines de alimentación del controlador. Mientras lo hace, siempre es bueno verificar dos veces sus rieles de alimentación con un voltímetro (y un osciloscopio cuando esté disponible).

Esto generalmente es causado por fusibles CKSEL incorrectos . El ATmega644 debe configurarse para impulsar el cristal en el modo "Oscilador de oscilación completa" para frecuencias de reloj superiores a 16 MHz; para algunas otras MCU, esta opción parece ser un bit de fusible separado llamado CKOPT o CLKOPT

En mi caso, el uso de CKSEL = 0111 lo solucionó, pero la mejor manera de averiguar los fusibles adecuados es usar una calculadora de fusibles y luego verificar los resultados con la hoja de datos antes de escribirlos.

¿Es posible que haya conectado el puerto RS232 de la computadora directamente a los pines UART de la MCU ATmega?

Las oscilaciones de voltaje + y - del puerto RS232 causarían estragos en el funcionamiento adecuado del silicio MCU. Ese caos podría resultar en cualquiera de los síntomas de falla que ha descrito.

Normalmente, el puerto RS232 de una computadora PC tiene sus líneas protegidas a través de una parte traductora de nivel de voltaje que las convierte a niveles de voltaje compatibles con la MCU. Si no tiene esto en su lugar, entonces se requiere un cambio en su configuración.

El otro dispositivo es un raspberry pi que usa 3.3v, así que no, ese no era el problema. ¿Pero los ~15V no freirían el AVR en lugar de hacer que actúe de manera extraña? De todos modos, publiqué esta pregunta principalmente en caso de que alguien más tenga el mismo problema para que no pierda horas tratando de depurarlo (por eso también publiqué la respuesta de inmediato).
@ThiefMaster: jeje, no me di cuenta de que eras tanto el que preguntaba como el que respondía. Los puertos RS232 rara vez usan 15V. En cambio, el original usó +/- 12V. La tecnología actual utiliza principalmente transceptores de bomba de carga que producen señales en el rango de +/-5V a +/-9V. Nunca se sabe si una señal de mayor voltaje freirá por completo un circuito integrado o si simplemente puede crear un comportamiento aberrante. A menudo, los síntomas extraños pueden persistir durante un tiempo y luego la pieza se fríe después de un período de tortura continua por el alto voltaje.