¿Por qué debo esperar unos momentos antes de enviar datos en serie en mi AVR?

2

Tengo un AVR (ATMega644) conectado a una Raspberry PI a través de una conexión en serie. El AVR se alimenta con 5 V y la línea AVR = > RPI Tx utiliza un divisor de voltaje de 1k8 / 3k3 para obtener un nivel de 3v3.

Si la espera de 10 ms (XXX en el código) no está presente (de acuerdo con la hoja de datos, no tengo que esperar en absoluto) Recibo este disparate (python repr () de los datos recibidos):

 '\x00\xaa\x8a\x8a\xea\n'
 '\xe9\xf5%\xc5E\xd5\xa4\xfcBYE WORLD\r\n'

Cuando hay un retraso de 10 ms, recibo esto:

'\x00HELLO WORLD\r\n'
'BYE WORLD\r\n'

Esto está bastante bien. Sin embargo, me gustaría saber por qué hay un 'H' antes del primer byte de datos real ( %code% ). ¡Nunca envío uno seguro!

Sin embargo, mi pregunta principal es por qué es necesaria la demora entre la inicialización y el envío de datos.

Notas: Mi valor F_CPU es correcto y también lo son los fusibles. También intenté usar una velocidad inferior (4800) y un chip diferente.

Este es el código que estoy usando:

#include <avr/interrupt.h>
#include <util/delay.h>
#include <util/setbaud.h>


inline void uart_putc(char c)
{
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;
}


inline void uart_puts(const char *s)
{
    while (*s) {
        uart_putc(*s++);
    }
}


int main()
{
    // we don't need/use any interrupts
    cli();

    // -DF_CPU=18432000L -DBAUD=19200 used when compiling
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;
    // 8 data bits
    UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);
    // enable transmitter
    UCSR0B |= (1 << TXEN0);

    _delay_ms(10);  // XXX
    uart_puts("HELLO WORLD\r\n");
    _delay_ms(250);
    uart_puts("BYE WORLD\r\n");

    // do nothing
    while (1)
        ;

    return 0;
}
    
pregunta ThiefMaster

2 respuestas

2

Básicamente, lo que haces en

// enable transmitter
UCSR0B |= (1 << TXEN0);

_delay_ms(10);  // XXX

está insertando 10ms de bits de parada ( 1 ). Esto ayuda a que su receptor se sincronice con el flujo de datos (que comienza convenientemente con un bit de inicio 0 ). Hasta entonces, el pin AVR es de alta impedancia y llena su búfer de entrada con basura que su receptor está intentando sincronizar.

Cada vez que el receptor lee 10 bits que se ajustan a la trama (bit de inicio 0 , 8 bits de datos, bit de parada 1 ), los bits de datos se insertan en el búfer de entrada. Solo cuando el marco no coincide, los bits se descartan hasta que encuentra una cadena de 10 bits correspondiente.

Esto también explica la importancia de usar los bits de inicio y parada en la transmisión asíncrona. Esto también explica por qué el uso de 1.5 o 2 bits de parada mejora la velocidad de sincronización; la probabilidad de que los datos recibidos ajusten accidentalmente el marco para un solo byte disminuyó.

    
respondido por el jippie
1

No tengo conocimiento de su hardware específico ni de cómo su software maneja las excepciones, pero si su circuito está pasando de un estado indefinido a uno definido, debe darle tiempo al sistema para tratar los estados que llegan al "límite". 'como las señales parecen ser válidas a medida que se establecen, pero no lo son. El uso de una interfaz de serie USB2 probablemente garantiza que la salida del convertidor siempre se establezca por defecto a un estado legal siempre que se reciba una entrada ilegal, por lo que no hay "hora de activación"; consulte a continuación. .

Más largo: si su línea serie está activa, inactiva y operativa según lo definido, estará en un estado definido: alto para un sistema con lógica positiva y bajo para un sistema con lógica negativa. Los sistemas que se conectan con TTL (nominalmente 0 / + 5V) o niveles de voltaje del sistema (0/3 o 0 / 3.3 o 0/5 o lo que sea) por lo general son una lógica positiva. RS232 invierte esta lógica y un estado inactivo suele ser bajo. Si se está conectando a niveles TTL, el nivel es lo que es el nivel: envíe 3V3 y verá 3V3, etc. Si el remitente cambia a alta impedancia cuando está desactivado, el receptor tiene que "decidir" qué debe hacer con la entrada. Es habitual tirar de la entrada hasta + V con una resistencia o equivalente que sea lo suficientemente grande (es decir, con carga lo suficientemente baja) como para que tenga un efecto cero en el funcionamiento normal. En condiciones deshabilitadas establece la entrada en "inactivo". Si usas interfaces seriales de USB a RS @ 32 o USB a nivel lógico, por lo general se ocupan de tales detalles. Si se conecta directamente, USTED debe decidir qué sucede durante el estado de desactivación y si no lo hace, entonces Murphy lo hará.

Si su software es una prueba semi-murphy y recibe una señal baja durante mucho tiempo (ilegal), el software puede rechazarlo. El software de menos MP (Murphy Proof) puede en cambio gibber.

Si pasa de entrada ilegal a legal (después de una habilitación de envío de datos), los niveles a medida que se estabilice el circuito pueden aparecer como señal.

Si su circuito tiene constantes de tiempo que involucran condensadores que se cargan a un nivel de CC adecuado durante la operación, pueden estar en tierra cuando recibe los datos por primera vez. A medida que cobran al valor correcto, un 1 o un 0 puede ser interpretado incorrectamente. Por lo general, el sesgo será de una manera u otra, por lo que, por ejemplo, 1 puede convertirse en 0, pero 0 está bien. Pero si hay ejecuciones de todos los 1 o todos los 0, durante la estabilización del sistema, estos pueden verse más afectados por los condensadores de carga o lo que sea.

En tu caso el hexágono
AA 8A 8A EA
= 1010 1010, 1000 1010, 1000 1010, 1110 1010 probablemente están destinados a ser "ELLO"
= $ 45 $ 4C $ 4C $ 4F
= 0100 0101, 0100 1100, 0100 1100, 0100 1111 No está claro que una sea causada por una decodificación incorrecta de la otra PERO que probablemente lo sea.

    
respondido por el Russell McMahon

Lea otras preguntas en las etiquetas