Enviando cantidades "mayores que 8 bits" a través de un enlace de 8 bits

4

Tengo datos que manipulo lógicamente en cantidades de 12 bits que necesito mover sobre un enlace UART. (en realidad soft-serial desde Mbed a PC a través del cable USB, pero eso es irrelevante)

Estaba pensando en usar la configuración de UART 8N1 común (8 bits de datos, sin paridad, 1 bit de parada), lo que me deja con la pregunta de cómo "cortar" mis valores de 12 bits a dos 8- bit "paquetes".

Por supuesto, yo mismo podría implementar algo trivial, como enviar primero los 8 bits más bajos y luego enviar los 4 bits más altos en el segundo paquete, con los otros 4 bits del segundo paquete no utilizados. O podría cortarlo en dos partes de 6 bits, con los otros 2 bits de cada paquete sin usar o designados para metainformación (por ejemplo, si el paquete actual es la primera o la segunda mitad de una cantidad de 12 bits).

Antes de hacer eso, quería ver si había alguna forma estándar o "práctica estándar de la industria" de recortar datos mayores de 8 bits en cantidades de 8 bits.

La velocidad del enlace no debería ser un problema, ya que mis requisitos son de aproximadamente 3 kbps.

(En ausencia de un "protocolo de comunicaciones de bajo nivel" -Stack-Exchange, creo que esta es la plataforma más adecuada para este tipo de pregunta, según varias discusiones sobre Meta).

EDITAR: Todas las respuestas fueron válidas y buenas. Marqué la respuesta de Olin como correcta, ya que es la forma en que fui con mi proyecto.

    
pregunta GummiV

5 respuestas

5

No, no existe una práctica común estándar o incluso generalmente aceptada.

Si está realmente seguro de que todo lo que enviará a través de este enlace es un flujo de valores de 12 bits, puede poner 6 bits en cada byte y usar los 2 bits restantes para identificar si este byte contiene el valor alto o bajo. bits de la palabra de 12 bits. Eso deja dos códigos más para una pequeña expansión.

Sin embargo, eso no es lo que yo haría, y ciertamente no es lo que normalmente hago. No importa lo mucho que piense lo contrario ahora, es muy probable que tarde o temprano desee que pueda enviar otra cosa a través del enlace, aunque solo sea para la depuración. Ya que dice que el ancho de banda no es un problema, hágalo ahora mismo para que la expansión del protocolo sea fácil.

Lo que normalmente hago es enviar datos en paquetes que comienzan con un byte de opcode, que es seguido por cualquier dato que vaya con ese opcode. He hecho esto muchas veces. Para mayor claridad de la documentación, llamo a los paquetes del host a los micro comandos , y del micro al host respuestas , pero eso no significa que las respuestas deben ser solo una resultado de los comandos.

Este esquema es fácil de implementar en firmware. También es fácil para el anfitrión, pero eso no importa. Con la capacidad de procesamiento y la memoria infinitas de una PC, cualquier protocolo que usted prepare y sea manejable en el micro será fácil para el host. El punto es mantenerlo simple en el pequeño sistema de recursos limitados y hacer que el otro sistema se adapte según sea necesario.

Al recibir, uso una tabla de salto para el byte de opcode. Eso se envía a la rutina única para ese comando, que sabe cuántos bytes de flujo de entrada más leer y qué hacer con ellos. Cuando termina, las rutinas de comando vuelven a un punto de retorno común, que recupera el siguiente código de operación, se despacha a través de la tabla, que ejecuta la siguiente rutina de comando, etc.

Una vez que haya configurado este mecanismo y haya un programa de prueba en el host para leer y escribir este protocolo, es realmente sencillo agregar otro comando o respuesta. Siendo tan simple, comenzarás a utilizar este servicio de maneras que no habías imaginado al principio. Por ejemplo, puede crear un comando que establezca un bit de depuración en el firmware que haga que otro código haga algo especial. O te das cuenta de que hay algunas opciones que te gustaría controlar, tal vez leer de nuevo la memoria de datos, un comando especial que hace algo único para realizar pruebas, etc. Este tipo de cosas es realmente muy útil.

Para resolver el caso particular sobre el que has preguntado, tendrías una respuesta seguida de 2 bytes que contienen el número de 12 bits. En el micro, eso es tan simple como enviar el byte de opcode de respuesta seguido por los dos bytes de datos periódicamente. Mientras tanto, deja abierta la opción de enviar otras cosas sin desordenar el flujo de valores de 12 bits.

    
respondido por el Olin Lathrop
2

Si lo único que va a enviar a través del enlace es su valor de 12 bits, puede ser útil enviarlo como dos bytes que se eligen de tal manera que el código que recibe dos bytes consecutivos pueda para identificarlos como parte de la misma lectura, o partes de dos lecturas consecutivas. Una forma común de hacer esto es usar un bit para identificar si un byte dado representa el inicio de un elemento de datos o una continuación de los mismos. Por ejemplo, podría especificar que una lectura constará de un byte cuyos 3 bits superiores son 100 y los cinco bits inferiores representan los 5 bits superiores de una lectura de 12 bits, seguidos de un byte cuyo bit superior es cero y los 7 inferiores los bits representan los 7 bits inferiores de una lectura de 12 bits. Tenga en cuenta que este enfoque puede funcionar bien si hay varios sensores. Por ejemplo, uno podría especificar que un valor de los 3 bits principales de 100, 101 o 110 representará el inicio de una de las tres lecturas de 12 bits de los sensores de 12 bits, mientras deja espacio para una mayor expansión.

    
respondido por el supercat
1

Cuando la información total a transferir es menor que un número entero de bytes, la idea de reservar un bit para el encuadre es, de hecho, atractiva, que he usado en el pasado.

Por supuesto, hay otros esquemas de marcos en uso, que pueden tener sentido cuando se van a mover más datos. También vale la pena considerar la representación ASCII con un carácter de terminación, ya que además de resolver el problema de encuadre, le proporciona datos legibles por humanos, aunque con una sobrecarga de 2x.

Sin embargo, como menciona USB, puede valer la pena considerar si un transporte serie USB puede darle un encuadre implícito de una clase que no está presente en un enlace serial verdadero. Los datos en los paquetes USB reales tendrán la posición preservada (es decir, ambos extremos pueden identificar cuál es el primer byte en la carga útil de un paquete), por lo que la pregunta real es si los controladores del host en particular aceptan / presentan datos desde / a las aplicaciones con una consistencia que puede ser utilizado para enmarcar. Por supuesto, si el extremo incrustado tiene un traductor que alimenta un UART real, la información de encuadre (más allá de la detección de ralentí ambiguo) se pierde en ese punto.

    
respondido por el Chris Stratton
1

Me encanta usar c UNIONS para cosas como esta. Maneje los datos como int16s y muévalos como int8s sin problemas.

    
respondido por el Scott Seidman
0

Si se enfoca en encontrar una manera estándar de transmitir datos a través de un enlace UART, hay muchos protocolos para hacerlo. Me viene a la mente el modbus que funciona con registros de 16 bits. Habrá algunos gastos generales asociados con la formación de paquetes, pero es un estándar que se usa ampliamente en entornos de automatización industrial. Si el ancho de banda es una preocupación principal, entonces los métodos descritos en otras respuestas aquí funcionarán bien.

    
respondido por el mjh2007

Lea otras preguntas en las etiquetas