obtener paquete de longitud dinámica de UART?

1

Escribo un programa para recibir datos de Uart ISI, mi paquete de datos es algo así como:

El primer byte de 2 bytes contiene el ID del dispositivo y el tipo de comando. Los datos contienen algunos bytes que pueden tener una longitud diferente, de 1 byte a 15 bytes como máximo, y el último byte que representa el paquete está terminado.

El código ISI de Uart es:

volatile char UartFlag=Fulse;
volatile unsigned char count=0;
unsigned char coder[13];

ISR     (USART_RX_vect)
{
    coder[count]=UDR0;
    if (coder[count] == 20)
        UartFlag=True;
    else
        count++;
}

Que reciba cada byte y guarde en coder . Como ve cuando recibe el número 20 , deje de recibir el proceso por UartFlag=True; y en main llame a una función DoSomthing(); para hacer algo con coder como se muestra a continuación:

while (1)
    {
        if (UartFlag)
        {
            DoSomthing();
            count=0;
            UartFlag=Fulse;
        }
    }

Pero tengo el problema de que en algún momento la sección de Datos tiene 20 en sus bytes y su ventaja es que no obtengo el paquete Correcto . Intento poner Data (el último byte = 0 en lugar de 20) pero tal vez tenga el mismo error.

Estoy buscando la mejor manera de encontrar la longitud dinámica del paquete. ¿Cuál es la mejor manera de encontrar la longitud dinámica del paquete?

Una forma en que tal vez se trabaje es poner la longitud de datos en el primer byte de la sección %code% , pero agrega un proceso adicional en el dispositivo remitente.

    
pregunta combo_ci

3 respuestas

2

En mi opinión, para estar al 100% de que funcionará en todos los casos, tienes que hacer lo que piensas de ti mismo:

Incluya la longitud de los datos (el número de bytes que está enviando) como un campo de encabezado adicional, por ejemplo, después del campo Type .

Esto es realmente lo que hacen los protocolos de Ethernet.

Acerca del proceso adicional en el remitente No sé cómo se implementa el remitente. Pero no parece requerir mucho esfuerzo de procesamiento . Quiero decir que el remitente ya sabe cuántos paquetes se enviarán, ¿no? Por lo tanto, a medida que complete los otros dos campos (Id. De dispositivo y Tipo), también puede completar este campo adicional.

    
respondido por el nickagian
2

Las dos formas comunes de resolver esto son las que mencionó.

  • Utilice un campo de longitud dedicado al principio del paquete
  • Use un marcador final no ambiguo al final del paquete.

Si no desea utilizar campos de longitud, debe usar un marcador final.
Si desea poder utilizar cualquiera de los valores de 256 bytes en la carga útil, debe ampliar su código introduciendo secuencias de escape para codificar más de 256 valores distintos.

Por ejemplo,

  • Utilice 0x20 0x00 para codificar el original 0x20 en la carga útil (es decir, reemplace cualquier 0x20 por 0x20 0x00 en la carga útil)
  • Use 0x20 0x01 como marcador final.

Dado que el escape aumenta el tamaño de la carga útil codificada, es recomendable utilizar un valor de carácter de escape que probablemente no aparezca en los datos de la carga útil original (por lo que 0x20 no sería una buena opción si la carga útil es un texto ASCII normal).

    
respondido por el Curd
1

Otra cosa a considerar es cómo se codifica el campo de datos. Puede evitar un especificador de longitud en el paquete asegurándose de que el marcador final nunca se espera en el campo de datos. (Tenga en cuenta que en las aplicaciones que creo también uso un marcador de inicio que es único y no puede ocurrir en la región de datos. Esto permite una sincronización más rápida de la secuencia de comandos sin perder un paquete adicional). si una región de datos es solo números, por ejemplo, codifíquelos en formato de caracteres en lugar de en formato binario. Luego, también seleccione su ID de dispositivo y Tipo de paquete como un carácter legible. Este esquema puede dejarle una serie de bytes para que se utilicen como "caracteres de control", dos de los cuales se utilizan como marcador inicial y marcador final. El conjunto de caracteres ASCII reserva claramente las codificaciones de 0x00 a 0x1F como caracteres de control. Esto tiene MUCHOS años y puede ver que este problema se resolvió hace mucho tiempo. Incluso hay nombres que se les dan a algunos de ellos que se pueden aprovechar directamente, como SOH (inicio de encabezado) y EOT (final de texto).

    
respondido por el Michael Karas

Lea otras preguntas en las etiquetas