Electronic – How to use UART rx data from ISR to main loop

interruptspicuart

I am using PIC18F and currently trying to interface it with SIM900. I am using UART Rx interrupt. ISR is working correctly but I wonder how to get data in main loop. Lets say :

#pragma interrupt hi_prioriint
void hi_prioriint(void)
{
   if(PIR1bits.RCIF==1)
   {
      Rx = ReadUSART();  //store the received byte in Rx
   }
 }

Now I want to use Rx in main loop. For example, if I send AT command then I need to check if I received OK or ERROR from SIM900. (For the time being I am just testing it with a single byte and will convert it later into receiving strings because response from the SIM900 is in string form)

Example:

 putrsUSART("AT\r");        //sending AT command
 delay(500)                 //delay of 500ms
 if(strcmp(Rx,"OK")==0)     //checking the response
 {
    //if received OK then proceed further
 }

So how to use RX data of ISR in main loop?

Best Answer

The conventional way to do this is to use a circular buffer (sometimes also referred to as a circular queue). The Rx interrupt routine inserts received data bytes into the queue using its input pointer/index. The mainline code uses the output pointer/index to extract the data from the queue.

The big advantage with this procedure is to allow the Rx data to arrive in spurts that may may come faster than they can be consumed by the mainline loop due to latency in other tasks. As long as the queue depth is enough and the mainline code is able to consume the Rx data at least as fast as the long term data flow rate this is the way to go.

Note that there is a plethora of information online regarding the design, coding and operation of circular queues. One hint is that there can be a performance improvement in the use of circular queues if the depth of the queue is kept to an even power of two bytes. When this is done the queue index wrap from top to bottom of the queue can become a simple mask of the index with a value of (queue depth - 1).