Pregunta

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

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

¿Fue útil?

Solución

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

Consulte FreeModBus para Windows y fuente incrustada.

Otros consejos

Hay mucho que decir sobre la arquitectura cliente-servidor y los protocolos síncronos. Sencillez y robustez, para empezar. Si la velocidad no es un problema, puede considerar un protocolo compacto y legible para ayudar con la depuración. Estoy pensando en la línea de los comandos AT modernos: un "despertar". secuencia 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 puede exceder el tiempo de espera si no ve el corchete de cierre, y se sincronizarán nuevamente 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 repetir el 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.

Mi voto es por la lectura humana.

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

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 ayudan, especialmente cuando el sistema embebido se está encendiendo por primera vez, y no sabes si el primer byte que obtiene es la mitad de Un mensaje o no.

El tipo debe ser una enumeración que indique cómo interpretar el paquete. El tamaño se puede inferir del tipo, pero si lo envía explícitamente, el receptor puede manejar tipos desconocidos sin asfixia. Puede usar 'tamaño de paquete total' 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 facilita la declaración de estructuras, pero ponerlo al final le permite evitar un paso adicional sobre los datos al enviar el mensaje.

El remitente y el receptor deben tener tiempos de espera que comiencen después de que se reciba 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 la misma capacidad, entonces puede usar flotadores como tipo de datos. De lo contrario, es más seguro usar enteros, ya sean bits A / D sin procesar o una escala preestablecida (es decir, 1 bit = .001V proporciona un rango de +/- 32.267 V)

Adam Liss hace muchos puntos geniales. La simplicidad y la robustez deben ser el foco. Las transferencias ASCII de lectura humana ayudan MUCHO durante la depuración. Grandes sugerencias.

Pueden ser excesivos para sus necesidades, pero HDLC y / o PPP agregan el concepto de una 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 verificació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.

bus USB responderá a todos sus requisitos. Puede ser un dispositivo USB muy simple con solo una tubería de control para enviar una solicitud a su dispositivo o puede agregar una tubería de interrupción que le permitirá notificar al host sobre los cambios en su dispositivo. Hay una serie de controladores usb simples que se pueden utilizar, 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 protocolo síncrono simple es definitivamente suficiente. ¿Qué te hace deambular y buscar un enfoque adicional? Comparte tus dudas e intentaremos ayudarte :).

Si no esperaba tener que hacer transferencias binarias eficientes, optaría por la interfaz de estilo terminal ya sugerida.

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

Los paquetes comienzan y terminan con 0x7e Para escapar de un carácter, se le agrega el prefijo 0x7d y se alterna 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 ve un 0x7e, si tiene datos almacenados, puede procesarlos.

Normalmente hago cosas sincrónicas controladas por el host a menos que tenga una muy buena razón para hacerlo de otra manera. Es una técnica que se extiende desde un simple punto de punto RS232 a multipunto RS422 / 485 sin problemas, a menudo una ventaja.

Como ya puede haber determinado a partir de todas las respuestas que no lo dirigen directamente a un protocolo, elija su propio enfoque para que sea su mejor opció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 la comunicación serie Rs-232 (una suposición de su pregunta) y, por supuesto, el espacio de código limitado, la definición de una estructura de comando simple ayudará, como señala Adam - Es posible que desee mantener el procesamiento de entrada al mínimo en el chip, por lo que el binario suena atractivo, pero la compensación es fácil de desarrollar Y reparar (es posible que tenga que solucionar problemas de una entrada muerta dentro de 6 meses) - hyperterminal es una poderosa herramienta de depuración, así que eso me hizo pensar en cómo implementar una estructura de comando simple con buena confiabilidad.

Algunas consideraciones generales:

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

Enmarcar los comandos y la suma de verificación opcional, como señala Adam, puede envolverse fácilmente alrededor de 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 al reiniciar, por ejemplo, " HOLA; Versión de firmware 1.00z " - le diría al host que el objetivo acaba de comenzar y qué se está ejecutando.

Si está monitoreando principalmente, es posible que desee considerar una "ejecución libre" modo en el que el objetivo simplemente pasaría por las lecturas analógicas y digitales; por supuesto, esto no tiene que ser continuo, puede espaciarse a 1, 5, 10 segundos o simplemente por orden. Su 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 sencilla.

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:

? - Lea todos los valores: no hay tantos, así que consígalos todos.

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

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

5=0 
6=9
2=5  

que establecería el puerto 5 desactivado, el puerto 6 en su totalidad y el puerto 2 en la mitad del valor: con este enfoque, los datos ascii y binarios son casi iguales en lo que respecta a la computación / decodificación de recursos 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 generalmente mejor, a menos que no lo sea.

Espero que esto ayude un poco.


Tuve otro pensamiento mientras releía; agregando un " * " el 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 -

:)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top