embedded - seriales - recibir datos serial arduino
¿Cómo puedo arreglar este código para permitir que mi AVR hable a través del puerto serie? (4)
Me he estado tirando de los pelos últimamente tratando de obtener un ATmega162 en mi STK200 para hablar con mi computadora a través de RS232. Revisé y me aseguré de que el STK200 contenga un chip MAX202CPE.
Configuré el chip para usar su reloj interno de 8MHz y lo dividí por 8.
Intenté copiar el código de la hoja de datos (e hice los cambios en los que se quejaba el compilador), pero fue en vano.
Mi código está debajo, ¿podría alguien ayudarme a solucionar los problemas que estoy teniendo?
Confirmé que mi puerto serie funciona en otros dispositivos y no es defectuoso.
¡Gracias!
#include <avr/io.h>
#include <avr/iom162.h>
#define BAUDRATE 4800
void USART_Init(unsigned int baud)
{
UBRR0H = (unsigned char)(baud >> 8);
UBRR0L = (unsigned char)baud;
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << URSEL0) | (1 << USBS0) | (3 << UCSZ00);
}
void USART_Transmit(unsigned char data)
{
while(!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
unsigned char USART_Receive()
{
while(!(UCSR0A & (1 << RXC0)));
return UDR0;
}
int main()
{
USART_Init(BAUDRATE);
unsigned char data;
// all are 1, all as output
DDRB = 0xFF;
while(1)
{
data = USART_Receive();
PORTB = data;
USART_Transmit(data);
}
}
Después de leer la hoja de datos un poco más a fondo, estaba configurando erróneamente la velocidad en baudios. La hoja de datos de ATmega162 tenía un gráfico de frecuencias de reloj trazado contra las tasas de baudios y el error correspondiente.
Para una velocidad de 4800 baudios y una frecuencia de reloj de 1 MHz, el error fue del 0,2%, lo cual fue aceptable para mí. El truco estaba pasando 12 a la función USART_Init (), en lugar de 4800.
Espero que esto ayude a alguien más a salir!
He comentado la respuesta de Greg, pero me gustaría agregar una cosa más. Para este tipo de problema, el método estándar de depuración es primero entender las comunicaciones seriales asíncronas, luego obtener un osciloscopio y ver qué está sucediendo en la línea. Si se intercambian caracteres y solo se trata de un problema de velocidad de transmisión en baudios, esto será particularmente útil ya que puede calcular la velocidad en baudios que está viendo y luego ajustar el divisor en consecuencia.
Aquí hay una cartilla súper rápida, sin dudas puedes encontrar algo mucho más completo en Wikipedia o en otro lugar.
Supongamos 8 bits, sin paridad, 1 bit de parada (la configuración más común). Entonces, si el personaje que se está transmitiendo es decir 0x3f (= ascii ''?''), Entonces la línea se ve así;
...--+ +---+---+---+---+---+---+ +---+--...
| S | 1 1 1 1 1 1 | 0 0 | E
+---+ +---+---+
El nivel alto (1) es + 5V en el chip y -12V después de la conversión a niveles RS232.
El nivel bajo (0) es 0V en el chip y + 12V después de la conversión a niveles RS232.
S es el bit de inicio.
Entonces tenemos 8 bits de datos, menos significativos primero, así que aquí 00111111 = 0x3f = ''?''.
E es el bit de parada (e para el final).
El tiempo avanza de izquierda a derecha, al igual que una pantalla de osciloscopio. Si la velocidad de transmisión es 4800, cada bit se expande (1/4800) segundos = 0.21 milisegundos (aprox).
El receptor trabaja muestreando la línea y buscando un borde descendente (una línea inactiva es simplemente lógica ''1'' todo el tiempo). El receptor conoce la velocidad en baudios y el número de bits de inicio (1), por lo que mide un tiempo de medio bit desde el flanco descendente para encontrar el medio del bit de inicio, luego muestrea la línea 8 bits veces seguidas para recoger el bits de datos. El receptor luego espera un bit más de tiempo (hasta la mitad del bit de parada) y comienza a buscar otro bit de inicio (es decir, un flanco descendente). Mientras tanto, la lectura del personaje está disponible para el resto del sistema. El transmisor garantiza que el próximo flanco descendente no comenzará hasta que se complete el bit de parada. El transmisor puede programarse para que espere siempre más tiempo (con bits de parada adicionales) pero ese es un problema heredado, solo se requieren bits de parada adicionales con configuraciones de hardware y / o software muy lentas.
No tengo a mano el material de referencia, pero el registro de tasa de baudios UBRR generalmente contiene un valor de divisor, en lugar de la velocidad en baudios deseada. Una búsqueda rápida en Google indica que el valor del divisor correcto para 4800 baudios puede ser 239. Por lo tanto, intente:
divisor = 239;
UBRR0H = (unsigned char)(divisor >> 8);
UBRR0L = (unsigned char)divisor;
Si esto no funciona, verifique con la documentación de referencia de su chip particular la fórmula de cálculo del divisor correcta.
Para depurar la comunicación UART, hay dos cosas útiles que hacer:
1) Haz un loop-back en el conector y asegúrate de leer lo que escribes. Si envía un personaje y lo recupera exactamente, sabe que el hardware está cableado correctamente y que al menos el conjunto básico de configuración de registro UART es correcto.
2) Envíe repetidamente el carácter 0x55 ("U") - el patrón de bits binarios 01010101 le permitirá ver rápidamente el ancho de bits en el osciloscopio, lo que le permitirá verificar que la configuración de velocidad sea correcta.