# Unable to receive response from SIM900

I am trying to communicate to SIM900 with PIC18F2520. I am able to send AT commands using UART but I also want to receive its response like OK or ERROR.

Following is the code for RX interrupt

#pragma code rx_interrupt = 0x8
void rx_int(void)
{
_asm goto rx_handler _endasm
}
#pragma code
#pragma interrupt rx_handler
void rx_handler(void)
{
for(k=0;k<=20;k++)
{

Rx[k] = getcUSART();    //read a byte from UART

}
UARTSend("We have read everything");   //I have a put a breakpoint here
if(strstr(Rx,"OK") != NULL)
{
}

PIR1bits.RCIF = 0;   //Clear the interrupt flag

}


Above is the code I am using for receiving data from SIM900. In the debug mode, I send UARTSend("AT\r");. I have a put a breakpoint at UARTSend("We have read everything");. At this line, I check for the Rx buffer in variable but it doesnt have OK instead it has few random chars while on the terminal I am getting proper response.

• Why you are assuming that response will be 20 chars? You must buffer the response until "\r\n" 2 char sequence is detected. Then start checking for response content - is it "OK\r\n" or "ERROR\r\n" or something else... there are more to this, in short I suggest to do some google-fu - github.com/search?utf8=%E2%9C%93&q=sim900 – Flanker Jul 30 '16 at 6:37

A number of mistakes here:

• Waiting for a byte to come in inside the RX interrupt; the fact that you're there pretty much tells you a byte has arrived.

• Reading 20 bytes when all you have is notification that one byte has arrived.

• Assuming that a response from the module will be exactly 20 bytes. You can see from your terminal that 'OK' + a bunch of CRLFs is returned when you send 'AT' so why read 20 bytes?

• You appear to be using the same UART lines for talking to the SIM900 and your PC. Way to cause confusion.

• You are sending data within the ISR to the PC. ISRs are meant to run quickly and return.

You need to use carefully chosen timeouts to know when the module is done talking to you. Your handler should look like this:

void rx_handler(void) {
Rx[k++] = getcUSART(); //read a byte from UART
PIR1bits.RCIF = 0; //Clear the interrupt flag
}


I assume k is a file scope variable and is declared volatile. Since you are using a PIC and so dont have the Arduino millis() or ARM SysTicks readily available, you can either implement something similar with a Timer peripheral or use delays as a short-term work-around.

Declare these:

  #define TIMEOUT 100


Your main() should look like this:

  Uart_Send("AT\r");
__delay_ms(1);
}
if (strstr(Rx, "OK") != NULL){
while (1){
LATBbits.RB0 = 0; // blink quickly
__delay_ms(500);
LATBbits.RB0 = 1;
__delay_ms(500);
}
}
else {
while (1) {
LATBbits.RB0 = 0; // blink slowly
__delay_ms(1500);
LATBbits.RB0 = 1;
__delay_ms(1500);
}
}


Set up RB0 as an output pin and connect an LED. I have used LED blink rates to indicate success or failure of your command. If you want to read the actual reply, either get an LCD or set up a Software UART port for talking to the PC; IIRC, the peripheral libraries include a Soft_Uart library.

Understand that this code is only to test if you can talk to the module. For any interesting uses, you'll need to implement a ring/circular buffer and Software UART, if you want to talk to your PC as well. I suggest you find an existing SIM900 library and try porting the relevant functions, used for sending commands and parsing responses, to C18 C.

• You left out sending a message from an ISR, which will probably block for many times longer than the interval until the next character. – Chris Stratton Jul 30 '16 at 18:18
• The downvote, however, is for the unsafe parts of your proposal. Because the increment operation of the lastRead flag is not atomic, you can miss the notification of a character arriving between the time the value is read and the time it is written back. Also you fail to ever reset the reader - it will just keep collection characters, quickly exceed the buffer, and cause a crash. – Chris Stratton Jul 30 '16 at 18:23
• @ChrisStratton I noticed the 'Uart_send()' part but forgot to include it when I got to the end of the list. If you read to the end of the code, you'd have noticed that I placed a while (1); at the end indicating that this is expected to run only once to test that AT works and then stall. I mentioned 'short-term work-around' and asked the OP to check out Software UART and consider implementing a proper ring buffer and something millis()-like. – TisteAndii Jul 30 '16 at 23:40

the main issue is 20 number of characters wont get received at the same time. So you should use while (!DataRdyUSART()); before each read.

while (!DataRdyUSART());   //if data is ready to receive
for(k=0;k<=20;k++)
{