Apretón de manos Serial XOnXOff

2

Tengo el siguiente código ejecutándose en un atmega328 (ArduinoUno).

#include <stdint.h>
#include <avr/interrupt.h>
#include <stdbool.h>
#include <util/delay.h>

volatile bool receiveQ = true;
volatile bool transmitQ = true;

ISR(USART_RX_vect)
{
    uint8_t byte = UDR0;
    if( !receiveQ && byte != 19)
    {
        return;
    }
    switch ( byte)
    {
        case 19:
            receiveQ = true;
            transmitQ = false;
            break;

        case 17:
            receiveQ = false;
            transmitQ = true;
            break;

        // process incoming data
        default:
            break;
    }
}
void transmitByte(uint8_t byte)
{
    while( !(UCSR0A & 1 << UDRE0));
    UDR0 = byte;
}
void transmitString(char *pstr)
{
    while( *pstr != 0)
    {
        transmitByte(*pstr);
        pstr++;
    }
}
int main(void)
{
    UBRR0H = 0;
    UBRR0L = 103;
    UCSR0C |= 1 << UCSZ01 | 1 << UCSZ00;
    UCSR0B |= 1 << RXEN0 | 1 << TXEN0 | 1 << RXCIE0;
    sei();
    while( 1)
    {
        if( transmitQ)
        {
            transmitByte(19);
            transmitString("data");
            transmitByte(17);
            transmitQ = false;
        };
        _delay_ms(1000);
    }
    return 0;
}

Quiero que implemente XOnXOff handshaking, y mi pregunta es si lo estoy haciendo correctamente.

Cuando configuro la comunicación con PuTTY, primero veo los "datos" que envía el Arduino. Luego envío XOff (Ctrl + S), algunos datos y XOn (Ctrl + Q), después de lo cual el Arduino envía los siguientes "datos". Y puedo seguir haciendo esto una y otra vez.

LarazónporlaquemepreguntosiestoyhaciendoestocorrectamenteesporquetengoqueenviarmanualmentelosbytesXOffyXOndePuTTYcuandotransmitodatos,aunqueheestablecidoelcontroldeflujocomoXOnXOff.

Sin embargo, PuTTY elimina los bytes XOff y XOn y solo proporciona "datos" cuando recibe datos.

Actualizar

El secnario es para control de retroalimentación en tiempo real. Durante cada período de tiempo, la entrada en serie al atmega328 es la señal de referencia. (Si no se reciben datos nuevos, utiliza los datos anteriores). La salida en serie del atmega328 es el valor del sensor (que también utiliza el controlador). Estoy usando los caracteres XOn y XOff para indicar cuándo debo comenzar a enviar los datos. y cuando se complete la transmisión.

    
pregunta Suba Thomas

2 respuestas

2

Como @ pjc50 dice en un comentario, Xon / Xoff es control de flujo, no control de bloque.

Si un búfer de recepción está lleno, el dispositivo con ese búfer envía "Xoff" al otro dispositivo para que deje de hablar por un rato. Así que su masilla enviará "Xon" cuando se inicie, luego solo enviará "Xoff" cuando el búfer del puerto esté lleno, luego de lo cual enviará "Xon" nuevamente cuando haya espacio para nuevos datos. Es probable que su Atmel sea mucho más lento en el manejo de datos que su PC, por lo que, como consecuencia, es poco probable que la PC decida enviar Xon / Xoff al Atmel por sí solo.

Dicho esto, a veces escribo el firmware del registrador que "bombea" los datos a 1MBit + y luego las ventanas específicamente comienzan a gimotear. Nunca he probado si luego envía Xon / Xoff, ya que a menudo luego migro a una comunicación USB directa, porque necesito el flujo, no un símil "cortado". Sin embargo, en Linux, no he tenido problemas con el búfer de hasta 5 Mbit en las interfaces seriales.

EDITAR:

Como nota al margen: he visto muchas cosas peores en el mundo que usar Xon / Xoff para apretar las manos en lugar del control de flujo, por lo que comparativamente no sería tan malo. Pero semánticamente, debe usar otros caracteres especiales para los procedimientos de intercambio de manos. Como SOH, STX, ETX, EOT, ENQ, ACK, NAK, SO, SI, CAN, EM.

También está permitido en Ascii usar DC1 a DC4 para lo que quieras.

Vea la Tabla de control de Ascii para obtener más nombres y números divertidos.

    
respondido por el Asmyldof
1

Cuando se inventaron los teletipos, su propósito principal era generar datos que se almacenaron en el otro extremo en forma de una cinta de papel. Los códigos XON y XOFF se definieron para permitir la posibilidad de que alguien que, por ejemplo, se dio cuenta de que un teletipo estaba casi sin papel y que debía pedirle al otro extremo que se detuviera mientras se reparaba. Cuando un teletipo ASR33 recibe un código XON, encenderá el lector de cinta de papel y comenzará a enviar el contenido del mismo; cuando reciba un código XOFF, apagará el lector de cinta de papel, dejándolo en posición para reanudarlo la próxima vez que reciba un XON.

Cuando los teletipos empezaron a conectarse a las computadoras, las computadoras aceptaron XON / XOFF suspendiendo la transmisión cuando se recibió una XOFF y reanudándola cuando se recibió XON.

Cuando las velocidades en baudios aumentaron hasta el punto en que los teletipos no podían mantenerse al día con los datos entrantes (muchos mecanismos de impresión tomarán una cantidad de tiempo variable para imprimir cada carácter, con el peor de los casos el doble del tiempo promedio ) algunos de ellos comenzaron a generar y enviar automáticamente códigos de control xon / xoff. Sin embargo, a pesar de estar automatizados, el XON / XOFF conserva algunas limitaciones como consecuencia de su diseño para iniciar y detener equipos remotos en respuesta a la interacción humana. Si un dispositivo remoto no recibe un XON por algún motivo, puede esperar para siempre. Si el XON fue emitido por un ser humano que no plantea un problema (el humano notará que no se está transmitiendo nada y enviará otro XON). Si el equipo automatizado simplemente envía un XON y no envía otro hasta que haya tenido motivos para enviar otro XOFF, sin embargo, el equipo remoto puede esperar por siempre un XON que nunca recibirá.

Para lidiar con esa posibilidad, puede ser útil tener un dispositivo que espere que los datos envíen periódicamente un XON cada vez que su búfer esté vacío (1-4x / segundo aproximadamente). Desafortunadamente, no conozco ninguna biblioteca de comunicaciones pre-construida que haga eso automáticamente. Sin embargo, si al menos un extremo de la conexión genera "manualmente" el xon / xoff en al menos un extremo de la conexión, ese extremo de la conexión puede generar caracteres XON cuando está inactivo, siempre que siempre pueda alcanzar una inactividad Estado incluso mientras se ha suspendido la transmisión en nombre del otro extremo. Si el dispositivo podría entrar en una situación en la que no puede recibir más datos hasta que transmita datos, y no puede transmitir datos hasta que reciba un XON, puede ser necesario agregar una lógica de tiempo de espera para resolver dicho interbloqueo.

Por cierto, si uno controla ambos extremos de la comunicación y desea que la línea permanezca tranquila cuando está inactiva (en lugar de enviar varios caracteres XON por segundo), puede ser útil que un sistema envíe caracteres ENQ periódicamente cuando está esperando. para un XON, y haga que el extremo remoto responda a una ENQ con XON o XOFF dependiendo de si está listo para los datos. Esto evitaría la posibilidad de que se produzca un interbloqueo accidental cuando un lado no ve un XON enviado por el otro, y también permitiría detectar un interbloqueo "sistémico" en los casos en que cada lado querrá transmitir los datos que tiene antes. recibe más.

    
respondido por el supercat

Lea otras preguntas en las etiquetas