Diseño lógico ISR Rx de comunicación en serie

Si no me equivoco, se supone que un ISR debe realizar un procesamiento mínimo cuando recibe datos en serie (a través de UART). Estoy planeando implementar dicho protocolo para la comunicación entre 2 sistemas a través de uart. Esta es una situación aproximada de cómo planeo codificar el ISR. Supongamos 2 sistemas A y B donde A está enviando un mensaje a B: la palabra clave se usa para indicar el inicio del mensaje (los datos/longitud establecidos no pueden ser la palabra clave). ChannelOK, Longitud de datos, RxLength, RxData, Indicador de paquete recibido en el proceso de B son 0 predeterminados. Longitud de datos = no. de (todos los datos) en bytes (por ejemplo, si todos los datos = 1, longitud de los datos = 1)

A's Process                               
 Send Keyword
 Send Length of data
 Send all data                

B's Process
 Rx Interrupt
 enter ISR
 ISR: if(Received Byte == Keyword && !ChannelOK)
      {
        Set ChannelOK 
      }

      if(ChannelOK && RxLength)
      {
       Set Length of data=received byte 
       ChannelOK=0
       RxLength=0
      }

      if(Length of data != 0 && RxData)
      {
        Store Data
        --Length of data
        if(Length of data==0)
        {
         Set Packet received flag
         RxData=0
        }
      } 

      if(ChannelOK)
      {
       Set RxLength
      } 

      if(Length of data)
      {
       Set RxData
      }
     Reset to Interrupt Again

Mi duda es: B tiene tantas cosas que hacer en el ISR mientras que A está enviando continuamente. Suponiendo que A envía datos a 7,5 Mbps (11 bits por transferencia), el ISR tiene que restablecer la interrupción cada (11/7,5 M) segundos. Esto parece muy muy pequeño. ¿Se perderán los datos si no reinicio la interrupción a tiempo o se almacenarán en el FIFO de 16 bytes para que una interrupción pueda activarse inmediatamente en el segundo en que reinicie la interrupción o debo ralentizar un proceso de Tx esperando un ACK? por cada byte (se ralentiza mucho)???

Soy un novato en ISR. Por favor, ayúdeme. Cualquier diseño o protocolo de ISR para la comunicación de datos en serie sería útil.

Gracias

No puedo entender la segunda mitad de tu primer párrafo.
La palabra clave será un valor hexadecimal como 0x5A. Cuando el ISR vea este valor, solo intentará almacenar los datos siguientes. Ejemplo: 1er byte- 0x5A,2do byte-3,3er byte-0x12(cmd),4to byte-algún estado,5to byte-msg checksum. 0x5a nunca puede ser un dato o una longitud. Solo puede indicar el inicio de un mensaje. Una vez que se recibe un mensaje completo, debe verificar si hay 0x5a para recibir nuevamente
Tienes 82,5 us por cada byte... ¿cuánto tiempo tarda tu bucle principal (suponiendo el peor de los casos) en procesar todo? si es de 80 us o menos entonces no debería haber problema. Esto es fácil de estimar en ensamblador ... con lenguajes más avanzados, es posible que deba buscar simular o (¡jadear!) Instrumentar su código y medir realmente el tiempo de ciclo (asegurándose de tomar las rutas más largas a través del código).
¿Cómo 82.5us? Ese es el problema, no quiero llegar al nivel básico de cuánto tiempo toma cada instrucción (aunque es posible). Quiero mantener la ISR lo más simple posible para que el tiempo ahorrado al mantener la ISR simple pueda concentrarse en otra parte.

Respuestas (2)

Propondré un método que puede resultarle útil con algunas modificaciones para adaptarlo a sus necesidades.

En este método, el ISR es tan pequeño que solo guarda datos en una matriz para su posterior decodificación en el programa principal, se utilizan dos contadores para detectar los datos recibidos y los datos decodificados. por supuesto, puede usar el puntero en lugar de los contadores.

   ISR:
 { 
    Receivedbytes[i++]= Rxbuffer;
    dataReceived++;
    }

    main:

    void UARTdecode{

    if (dataDecoded<dataRecived)
    {
    Received byte = Receivedbytes[j++];
    ///// where routine 
    if(Received Byte == Keyword && !ChannelOK)
          {
            Set ChannelOK 
          }
    ..
    ..
    ..
    //// end of routine 

    dataDecoded+=x; (where x is the amount of data decoded or message length)
    }

    }

PD:Es MUY IMPORTANTE que i y j se declaren como variables Estáticas

También puede verificar el código fuente de la biblioteca serial de hardware arduino, es de código abierto y usa ISR para recibir datos "HardwareSerial.h" en el directorio de instalación

Entonces, ¿está diciendo que solo copio los datos en ISR a un búfer y hago todo el procesamiento escrito en mi ISR ​​en el principal ()?
Finalmente, solo compruebo si dataDecoded = Longitud de datos + 2
Sí ! si esta es la respuesta que está buscando, pero aún así le recomiendo que eche un vistazo a la biblioteca serial de hardware de arduino. y tenga en cuenta que los contadores que mencioné son importantes porque debe saber qué caracteres de la matriz ha leído y cuáles no. experimenta con esto y si aún tienes dudas, publícalas.
Sí, estoy de acuerdo en que los valores del contador deben ser estáticos. Gracias :) Echaré un vistazo a la biblioteca. Il Publique aquí si tiene alguna duda.
Esto parece una implementación de búfer de anillo
B tiene tantas cosas que hacer en el ISR

No, al menos no si diseña correctamente el sistema. Mantendría cualquier lógica de decodificación fuera del ISR. Por lo general, mi controlador de interrupciones UART toma el byte del hardware, borra la condición de interrupción y mete el byte en un FIFO. El código de primer plano puede tomarlo desde allí. Haga que el FIFO sea lo suficientemente grande para que el código de primer plano pueda ejecutarse en ráfagas y el FIFO no se desborde entre ráfagas.

Si hay demasiado que hacer por byte, entonces tiene un problema fundamental que el firmware no puede solucionar. Necesita un procesador más rápido o una comunicación más lenta.

Entonces dices que simplemente copio los datos recibidos en el ISR a un búfer global {[RxBuffer[Loc++]} y restablezco la interrupción. En main() voy y verifico si el valor en RxBuffer[0] es la palabra clave. Si es la palabra clave, procese RxBuffer[1]--RxBuffer[FinalLoc]. De lo contrario, borre RxBuffer. Pero, ¿cómo saber cuándo ha llegado el paquete completo? Al usar algo como un algoritmo de verificación de pila donde inicializo todas las locaciones del RxBuffer a un valor constante definido (como palabra clave pero valor diferencial como 0xa5). Si el valor en RxBuffer[Length+1] != valor constante, mensaje recibido. De lo contrario, el mensaje aún no está completo Rxd.