embedded avr communication-protocol

embedded - Protocolos utilizados para hablar entre una CPU integrada y una PC



avr communication-protocol (8)

Hay mucho que decir sobre la arquitectura cliente-servidor y los protocolos síncronos. Simplicidad y solidez, para comenzar. Si la velocidad no es un problema, puede considerar un protocolo compacto y legible por humanos para ayudar con la depuración. Estoy pensando en las líneas de los comandos AT del módem: una secuencia de "activación" seguida de un comando set / get, seguido de un terminador.

Host --> [V02?] // Request voltage #2 AVR --> [V02=2.34] // Reply with voltage #2 Host --> [V06=3.12] // Set voltage #6 AVR --> [V06=3.15] // Reply with voltage #6

Cada lado podría agotar el tiempo si no ve el corchete de cierre, y se volverían a sincronizar en el siguiente corchete abierto, que no puede aparecer dentro del mensaje en sí.

Dependiendo de los requisitos de velocidad y confiabilidad, puede codificar los comandos en uno o dos bytes y agregar una suma de verificación.

Siempre es una buena idea responder con el voltaje real , en lugar de simplemente hacer eco del comando, ya que guarda una operación de lectura posterior.

También es útil para definir mensajes de error, en caso de que necesite depurar.

Estoy construyendo un pequeño dispositivo con su propia CPU (AVR Mega8) que se supone que se conecta a una PC. Suponiendo que se ha logrado la conexión física y el paso de bytes, ¿cuál sería el mejor protocolo para usar sobre esos bytes? La computadora necesita poder establecer ciertos voltajes en el dispositivo y volver a leer otros voltajes.

Por el momento, estoy pensando en un protocolo síncrono completamente impulsado por el host: las solicitudes de envío de la computadora, la CPU incrustada responde. ¿Alguna otra idea?


El bus USB responderá a todos tus requerimientos. Puede ser un dispositivo usb muy simple con solo un tubo de control para enviar solicitudes a su dispositivo o puede agregar un tubo de interrupción que le permitirá notificar al host sobre los cambios en su dispositivo. Existe una cantidad de controladores usb simples que se pueden usar, por ejemplo, Cypress o Microchip .

El protocolo en la parte superior de la transferencia se trata realmente de sus requisitos. Según su descripción, parece que el simple protocolo síncrono es definitivamente suficiente. ¿Qué te hace vagar y buscar un enfoque adicional? Comparte tus dudas e intentaremos ayudar :).


Adam Liss hace muchos buenos comentarios. La simplicidad y la solidez deberían ser el foco. Las transferencias ASCII legibles por humanos ayudan MUCHO durante la depuración. Grandes sugerencias

Pueden ser excesivos para sus necesidades, pero HDLC y / o PPP agregan el concepto de capa de enlace de datos y todos los beneficios (y costos) que vienen con una capa de enlace de datos. La gestión de enlaces, el encuadre, las sumas de comprobación, los números de secuencia, las retransmisiones, etc., ayudan a garantizar comunicaciones sólidas, pero agregan complejidad, procesamiento y tamaño de código, y pueden no ser necesarios para su aplicación en particular.


Si no esperaba tener que hacer transferencias binarias eficientes, elegiría la interfaz estilo terminal que ya se sugirió.

Si quiero hacer un formato de paquete binario, tiendo a usar algo libremente basado en el formato HDLC byte-asnc de PPP, que es extremadamente simple y fácil de enviar y recibir, básicamente:

Los paquetes comienzan y terminan con 0x7e Usted escapa de un char prefijándolo con 0x7d y alternando el bit 5 (es decir, xor con 0x20) Entonces 0x7e se convierte en 0x7d 0x5e y 0x7d se convierte en 0x7d 0x5d

Cada vez que vea un 0x7e, si tiene datos almacenados, puede procesarlos.

Usualmente hago cosas sincrónicas basadas en el host a menos que tenga una muy buena razón para hacer lo contrario. Es una técnica que se extiende desde el punto de referencia simple RS232 hasta el multipunto RS422 / 485 sin problemas, a menudo una ventaja.


He hecho cosas como esta con un formato binario simple

struct PacketHdr { char syncByte1; char syncByte2; char packetType; char bytesToFollow; //-or- totalPacketSize }; struct VoltageSet { struct PacketHdr; int16 channelId; int16 voltageLevel; uint16 crc; }; struct VoltageResponse { struct PacketHdr; int16 data[N]; //Num channels are fixed uint16 crc; }

Los bytes de sincronización son menos críticos en un protocolo síncrono que en uno asíncrono, pero aún así ayudan, especialmente cuando el sistema integrado se está encendiendo por primera vez, y usted no sabe si el primer byte que recibe es el medio de un mensaje o no.

El tipo debe ser una enumeración que indique cómo interpretar el paquete. El tamaño se puede deducir del tipo, pero si lo envía explícitamente, el receptor puede manejar tipos desconocidos sin ahogarse. Puede usar ''tamaño total del paquete'' o ''bytes a seguir''; este último puede hacer que el código del receptor sea un poco más limpio.

El CRC al final agrega más seguridad de que tiene datos válidos. A veces he visto el CRC en el encabezado, lo que hace que declarar las estructuras sea más fácil, pero ponerlo al final le permite evitar un pase adicional sobre los datos al enviar el mensaje.

El emisor y el receptor deben tener tiempos de espera que comienzan después de que se recibe el primer byte de un paquete, en caso de que se elimine un byte. El lado de la PC también necesita un tiempo de espera para manejar el caso cuando el sistema integrado no está conectado y no hay respuesta en absoluto.

Si está seguro de que ambas plataformas usan flotadores IEEE-754 (las PC lo hacen) y tienen el mismo endianness, entonces puede usar flotantes como el tipo de datos. De lo contrario, es más seguro usar números enteros, bits de A / D en bruto o una escala preestablecida (es decir, 1 bit = .001V da un rango de +/- 32.267 V)


Mi voto es para el humano legible.

Pero si vas binario, intenta poner un byte de encabezado al principio para marcar el comienzo de un paquete. Siempre he tenido mala suerte con los protocolos serie que no están sincronizados. El byte del encabezado permite que el sistema integrado se vuelva a sincronizar con la PC. Además, agregue una suma de verificación al final.


Como es posible que ya haya determinado a partir de todas las respuestas que no lo dirigen directamente a un protocolo, que su propio enfoque sea su mejor elección.

Entonces, esto me hizo pensar y bueno, aquí están algunos de mis pensamientos:

Dado que este chip tiene 6 canales ADC, lo más probable es que esté utilizando el comm serial Rs-232 (una suposición), y por supuesto el espacio de código limitado, la definición de una estructura de comando simple ayudará, como señala Adam: Usted puede desear mantener el procesamiento de entrada al mínimo en el chip, por lo que el binario suena atractivo, pero el intercambio es fácil de desarrollar Y reparar (es posible que tengas que solucionar el problema de una entrada muerta dentro de 6 meses) - hyperterminal es un poderoso herramienta de depuración - entonces, eso me hizo pensar en cómo implementar una estructura de comando simple con buena confiabilidad.

Algunas consideraciones generales

mantenga los comandos del mismo tamaño, facilita la decodificación.

Enmarcar los comandos y la suma de verificación opcional, como señala Adam, se puede ajustar fácilmente a sus comandos. (con comandos pequeños, una suma de comprobación XOR / ADD simple es rápida e indolora)

Recomendaría un anuncio de inicio al host con la versión de firmware en el momento del reinicio, por ejemplo, "HELLO; Versión de firmware 1.00z" - le diría al host que el objetivo recién se inició y qué se está ejecutando.

Si está monitoreando principalmente, puede considerar un modo de "ejecución libre" donde el objetivo simplemente recorre las lecturas analógica y digital, por supuesto, esto no tiene que ser continuo, se puede espaciar a 1, 5, 10 segundos, o simplemente al comando. Tu micro siempre está escuchando, por lo que enviar un valor actualizado es una tarea independiente.

Terminar cada línea de salida con un CR (u otro carácter) hace que la sincronización en el host sea directa.

por ejemplo, su micro podría simplemente generar las cadenas;

V0=3.20 V1=3.21 V2= ... D1=0 D2=1 D3=... and then start over --

Además, los comandos podrían ser realmente simples

? - Lee todos los valores - no hay muchos, así que entiéndelos.

X = 12.34 - Para establecer un valor, el primer byte es el puerto, luego el voltaje y yo recomendaríamos mantener el "=" y el "." como encuadre para garantizar un paquete válido si renuncia a la suma de comprobación.

Otra posibilidad, si sus salidas están dentro de un rango establecido, puede preescalarlas. Por ejemplo, si el resultado no tiene que ser exacto, podría enviar algo como

5=0 6=9 2=5

que establecería el puerto 5 apagado, el puerto 6 al máximo, y el puerto 2 a la mitad de valor - Con este enfoque, los datos ascii y binarios están casi en pie de igualdad con respecto a los recursos de computación / descodificación en el micro. O para mayor precisión, haga que la salida sea de 2 bytes, por ejemplo, 2 = 54 - O, agregue una tabla xref y los valores ni siquiera tienen que ser lineales donde el byte de datos es un índice en una tabla de búsqueda. .

Como me gusta decir; Simple es usualmente mejor, a menos que no lo sea.

Espero que esto ayude un poco.

Tenía otro pensamiento mientras releía; agregar un comando "*" podría solicitar los datos envueltos con etiquetas html y ahora su aplicación host podría simplemente redirigir la salida de su micro a un navegador y wala, listo para el navegador -

:)


Modbus puede ser lo que estás buscando. Fue diseñado exactamente para el tipo de problema que tienes. Hay muchos códigos / herramientas y el cumplimiento de un estándar podría significar una fácil reutilización posterior. También es compatible con ASCII legible por humanos, por lo que aún es fácil de entender / probar.

Ver FreeModBus para Windows y fuente incrustada.