0

I m using dspic33f series micro controller to receive SMS from modem SIM800A. I m using interrupt method to receive response from the modem using serial communication . If I send more than one AT command to modem via UART sequentially I'm getting response into the recieve buffer only for 1st command and no response in the receive buffer for the remaining commands though the modem was responding. After debugging I found the reason for this peculiar behavior. The reason was I was clearing the receive buffer after receiving the response into the buffer and printing on the console i.e. before sending next command to modem via UART using memset function in c. But on commenting this memset function i was able receive the response into the receive buffer for the all the AT commands that was sent sequentially, if the memset function is not commented then no response is filled in the receive buffer though the modem was responding so please help out in receiving the response into the buffer.

Code which i have written

#include "p33FJ64GS606.h"

#include <stdio.h>
#define FCY         40000000UL
#include <libpic30.h>
#include <string.h>
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF)
_FWDT(FWDTEN_OFF)
_FPOR(FPWRT_PWR128 )
_FICD(ICS_PGD1 & JTAGEN_OFF) 

char StringLoop[161];
void Init_Uart1(int uart_no)
{   
    U1MODEbits.STSEL = 0; // 1-Stop bit
    U1MODEbits.PDSEL = 0; // No Parity, 8-Data bits
    U1MODEbits.ABAUD = 0; // Auto-Baud disabled
    U1MODEbits.BRGH = 0; // Standard-Speed mode
    U1BRG = UBRG1_VALUE; // Baud Rate setting for 115200
    U1STAbits.UTXISEL0 = 0; // Interrupt after one TX character is transmitted
    U1STAbits.UTXISEL1 = 0;
    U1STAbits.URXISEL0 = 0;
    U1STAbits.URXISEL1 = 0;//jkv
    IEC0bits.U1RXIE = 1;
    IEC0bits.U1TXIE = 0; // Enable UART TX interrupt
    U1MODEbits.UARTEN = 1; // Enable UART
    U1STAbits.UTXEN = 1; // Enable UART TX
    U1MODEbits.USIDL=0;
}

void UART1_puts(unsigned char data)
{   
    while (U1STAbits.TRMT==0);
      U1TXREG = data;


}

void UART1_send(unsigned char *s)
{
    memset(StringLoop,'\0',sizeof(StringLoop)); /* if I comment this line then i can receive the response into the buffer StringLoop continuously else i receive the response only for the 1st AT command and I don't get the response for other AT commands into the StringLoop though the modem is responding*/
    while(*s)
    {   
    UART1_puts(*s);
    s++;


    }
}

void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
{

    if(IFS0bits.U1RXIF)
    {

       StringLoop[rcindex++] = U1RXREG;
       if (rcindex >= (sizeof(StringLoop) - 1))
            rcindex = 0;          
  }  
    IFS0bits.U1RXIF=0;
    }
}
void main()
{
    int i=0,j=0;
    Init_Clocks();
    Init_Uart2(1);
    Init_Uart1(1);
    TRISFbits.TRISF1=0; 
    LATFbits.LATF1=1;
    UART1_send("AT+CMGR=1\r\n");    
    __delay_ms(2000);
    printf("stringloop is %s\n",StringLoop);

   UART1_send("AT+CPMS=?\r\n"); 
    __delay_ms(2000);
    printf("stringloop is %s\n",StringLoop);

    UART1_send("AT+CPMS?\r\n"); 
    __delay_ms(2000);
    printf("stringloop is %s\n",StringLoop);

}
  • Does the modem respond with "Ok" after each AT command? – Gaurav Pathak Jul 31 '17 at 10:09
  • 2
    `char StringLoop;` is declared to store just a single byte!! I wonder why the program is not crashing on `StringLoop[rcindex++] = U1RXREG;` – Gaurav Pathak Jul 31 '17 at 10:18
  • 1
    As @GauravPathak already wrote, this cannot possibly work since `StringLoop` is a single `char`. However, it would be a better idea to skip the array version altogether and go straight for a [ring buffer](https://stackoverflow.com/a/215575/69809) for the rx interrupt. Pretty much any solution which doesn't use a FIFO for receiving data is bound to have some race conditions or implement additional timeouts to work correctly. – vgru Jul 31 '17 at 12:04
  • 1
    The reason why it only works the first time is because `StringLoop` is zero at the beginning, and calling `memset` with a null pointer is UB (which in your case doesn't crash). Next time you call `UART1_send`, `StringLoop` has a character inside, meaning that `memset` writes to who-knows-where since the char is converted to a `void*`. **Configure your compiler to enable all warnings and treat them as errors**. This code should never be allowed to run if your compiler is properly configured. If you still refuse to use a FIFO, at least reset `rcindex` to `0` before sending. – vgru Jul 31 '17 at 12:09
  • sorry there was a typo error StringLoop is a char array of size 160. char StringLoop[160]; – jagadish kumar Aug 01 '17 at 10:53
  • Modem was responding with Ok when checked in the modem logs. The modem was also sending the response for the al command which was was sent via UART. But the StringLoop is not getting filled with the response. i had used one more variable count int count=0;//global variable and added this count in the interrupts below the line StringLoop[rcindex++] = U1RXREG; count++; i could see the count getting incremented after each receive of charcter but still no data was printed when i try to print the StringLoop. – jagadish kumar Aug 01 '17 at 11:02
  • You need to change the logic to store the response from modem till you don't get `ok\r\n`. After that process the response and send another command and do the same thing. Or you have to check the datasheet of respective modem for message or string terminating character. – Gaurav Pathak Aug 01 '17 at 11:21

0 Answers0