CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

SIM800L

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

SIM800L
PostPosted: Wed Aug 22, 2018 12:54 pm     Reply with quote

Dear all,

please find included the code for SIM800L module. The hardware uses PIC18f4520, but could be any other 18F. I2C LCD, the cheapest Chinese SIM800L quad band module (3,5$ or so). The module's boot is controlled by a logic level 30N06L MOSFET, connected source to system GND and drain to module's ground. Please be aware that this is a part of a bigger project, so there are some things floating around in the code that this example doesn't use at all. The Init_GSM() tries to initialise GSM and it uses timeouts to try and recover if any of the INIT stages doesn't go as planned. So it doesn't just hang if the module refuses to collaborate. I still need to extensively test it, but the first 50 or so messages came through without a glitch. Please be aware how you put the SIM into the module. The slanted part is on the OUTSIDE. I lost a day with that. Some parts of the code are copied from another threads here, and a long time ago. I don't really remember from who, but it helped a ton. Thank you all.

As always, any comments are more than welcome.

main.h
Code:

#include <18F4520.h>
#device PASS_STRINGS = IN_RAM    //copy all the strings to RAM to allow access with pointers
#device ICD=TRUE
//#include <stdlib.h>
#device adc=10                   //10 bit AD resolution

#FUSES NOWDT                     //No Watch Dog Timer
#FUSES WDT128                    //Watch Dog Timer uses 1:128 Postscale
#FUSES HS                       //High speed Osc, high power 16MHz-25MHz
#FUSES NOBROWNOUT                //No brownout reset
#FUSES NOLVP                     //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                   //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES DEBUG                     //No Watch Dog Timer

#use delay(clock=20000000)       //20Mhz clock


//#use rs232(baud=115200,parity=N,xmit=PIN_C7,rcv=PIN_C6,bits=8,stream=GSM,errors)
#use rs232(baud=57600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GSM,errors)
//#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=GSM,errors)
//#use i2c(Master,slow,sda=PIN_C4,scl=PIN_C3,force_sw)
#use i2c(Master,slow,sda=PIN_C4,scl=PIN_C3, force_hw)


main.c

Code:


#include <main.h>

#include <i2c_Flex_LCD_driver.c>
//#include <defs.h>                //definitions of pins and registers
#define BUFFER_SIZE 250          //create 250 byte large buffer
char buffer[BUFFER_SIZE];
int8 next_in = 0;                //max. next_in =  BUFFER_SIZE -1 !!!!!

// buffer to hold phone number read from EEPROM or SMS message. This is the number SMS is sent to.
#define   GSM_NUMBER_SIZE   16                  // GSM number buffer size
char GSM_NUMBER[GSM_NUMBER_SIZE];               // GSM number buffer   
int8 Next_Number = 0; // pointer to the position in buffer

#define OK_STATUS PIN_E1            // blink LED so you know PIC does something
unsigned int8  SMSCounter = 0;      //number of SMS's sent
unsigned int8  Second = 0;          //sets a flag GO every second
int1           GO;                  //starts the execution of the main loop
int1           BLINK;               //holds the state for the blinking LEDs
int8 gsm_init= 0;
// Set of AT commands
const char AT[] = "AT\r\n";                                    // Every AT command starts with "AT"
const char ATE[] = "ATE1\r\n";                                 // enable command echo
const char CFUN[] = "AT+CFUN=1\r\n";                           // full phone functionality
const char IPR[] = "AT+IPR=57600\r\n";                         // Set COM speed, not used in this program. Change COM settings if you use it
const char TXT[] = "AT+CMGF=1\r\n";                            // set TXT messages
const char GSM_MODE[] = "AT+CSCS=\"GSM\"\r\n";                 // Set GSM_MODE
const char STORE_SIM[] = "AT+CPMS=\"SM\",\"SM\",\"SM\"\r";     // Store on SIM Card
const char READ_SMS[] = "AT+CMGR=1\r\n";                       // Command for reading message from location 1 from inbox
const char ERASE_SMS[] = "AT+CMGD=1,4\r\n";                    // Erasing all messages from inbox
const char CHECK_REGISTERED[] = "AT+CREG?\r\n";                // Commant to check cell network registration. result: +CREG: 0,1 or 0,5 for roaming
const char REGISTER_TO_NET[] = "AT+CREG=0\r\n";                // register to the network

const char SEND_SMS[] = "AT+CMGS=\"+1234567890\"\r\n";        // Send SMS
//
// Responses to parse
const int8  GSM_OK = 10;
const int8  GSM_Ready_To_Receive_Message = 11;
const int8  GSM_ERROR = 12;
const int8  GSM_CONN_OK = 14;
const int8  GSM_REGISTERED = 15;
const int8  SMS_SENT = 16; 

// State machine control variables
//char gsm_state = 0;              // initial state of decoding routine
int16   gsm_state = 0;
char response_received = 0;      // 0-no response, 1-response from module
signed int responseID = -1, response = -1, rsp;

#define     BOOT_GSM   1         // boot state machine states
#define     SEND_AT   2
#define     SEND_ECHO   3
#define     SET_TXT   4
#define     SET_GSM   5
#define     SET_ALERT   6
#define     SET_STORAGE   7
#define     DEL_MSG   8
#define     CFUN 9
#define     CONNECT 10
#define     WAIT_CELL   11
#define     GSM_ERROR   12

#define     BOOT_TIME   10       // time to wait for the module to be ready, in seconds

int8   StartGSM = 1;
int8   Not_Initialized = 1;
int8   NotResponding = 0;                 // timer for GSM response time
#define   MaxResponseTime 100             // GSM timeout = MaxResponseTime * 100ms ie 10s
char tmp;
int8  SMS_Was_Sent = 0;
#define  BOOT   PIN_D2                    // GSM boot pin. A logic level FET 30N06L (source to system GND, drain to  module GND)  is used to turn the module ON or OFF
#define  GSM_RESET   PIN_D0               // sim800l reset pin, not used here. The function would be the same as above.
int8 GSM_Tilt = 0;
int16  Response_Time = 0;
int8   GSM_Doesnt_Respond = 0;
#define Max_Response_Time  200
#define Max_No_Response 200

// clear UART buffer
void Clear_UART_Buffer() {                // not neccesary, used to see better and easier what is happening with PICKIT3 because the buffer is empty
   next_in=0;
   while (next_in < BUFFER_SIZE){
      buffer[next_in] = '\0';
      next_in++;
   }
   next_in=0;
}

//-----------------------------------------------------------------------------
//------------------------ GET RESPONSE ---------------------------------------
signed int Get_response() {      // Get response from GSM, and return it to the Wait_rsponse function
    if (response_received) {
         response_received = 0;
         return responseID;
    }
    else
         return -1;
}

//------------ WAIT RESPONSE TO COMMAND FROM GSM ------------------------------
void Wait_response(char rspns) {          // Wait for GSM response
   GSM_Tilt = 0;
   Response_Time = 0;
   GSM_Doesnt_Respond = 0;
   while(1){
      delay_ms(30);
      if (Get_response() == rspns){          // everything ok, this is the response we wait
         GSM_Tilt = 0;
         break;
    }
      else if(Get_response() == GSM_ERROR){  // GSM returned  ERROR
         GSM_Tilt = 1;
         break;
    }
      else if(Get_response() == GSM_Ready_To_Receive_Message){  // GSM returned  '> ' unexpectedlly
         GSM_Tilt = 2;
         break;   
      } 
       else if(Get_response() == -1){        // GSM doesn't answer
         GSM_Doesnt_Respond++;
         if(GSM_Doesnt_Respond > Max_No_Response){
            GSM_Tilt = 3;
            break;
         }
      }
      else{                                        // unknown answer too many times, reset module after 6 seconds
         Response_Time++;
         if(Response_Time > Max_Response_Time){
            GSM_Tilt = 4;
            break;
         }
      }
   }
}


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Send command or data to GSM module
void GSM_Send(char *s)
{
// Send command or data string
   while(*s) {                   // as long as you don't encounter NULL
      fputc(*s++);                 // send characters to RS232
   }
}


//*******************************************************************************
//*****************************************************************************
// GSM module init sequence
// ****************************************************************************
void Init_GSM (void){
   
while (Not_Initialized){            // stay here as long as needed. Preset this variable to 1

   switch (StartGSM) {
     
// *************************** BOOT *******************************************
      case BOOT_GSM:{
         Not_Initialized = 1;       
         output_low (BOOT);         // turn the module OFF
         delay_ms(1000);
         output_high (BOOT);        // and back ON
         lcd_putc('\f');            //CLEAR lcd
         delay_ms(100);
         lcd_putc("BOOTING IN:");
         int8 i = 0;
         while(i<BOOT_TIME){
            i++;
            lcd_gotoxy(12,1);
            printf(lcd_putc, "%3u", BOOT_TIME-i);  // display countdown till BOOT
            delay_ms(1000);
         }
         lcd_putc('\f');            //CLEAR lcd   
         delay_ms(1000);
         
         StartGSM = SEND_AT;         // next state is AT
         break;
      }
// ********************** SEND AT COMMAND ********************************     
      case SEND_AT:{
         lcd_gotoxy(1,1);
         lcd_putc("SENDING AT...");
         GSM_Send(AT);                  // AT

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("AT OK...");      // display success
            delay_ms(500);
            StartGSM = SEND_ECHO;      // next state is SEND_ECHO
            NotResponding = 0;
            break;
         }
         else {                        // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = BOOT_GSM;         // boot GSM again if it doesn't even respond to AT
               break;
            }
            else{
               break;               // try sending AT again after 100ms
            }
         }
           
      } // end case
// ************************* SEND ECHO COMMAND ********************************         
      case SEND_ECHO:{
         lcd_gotoxy(1,1);
         lcd_putc("SET ECHO ON");
         GSM_Send(ATE);            //ATE0
         
         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("ECHO ON...");      // display success
            delay_ms(500);
            StartGSM = CFUN;           // next state is CFUN
            NotResponding = 0;
            break;
         }
         else {                        // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending ATE1 again after 100ms
            }
         }
         
      } // end case
     
// ************************** FULL FUNCTIONALITY ******************************
      case CFUN:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("CFUN = 1...");
         GSM_Send(CFUN);            // Set full function

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("OK...");      // display success
            delay_ms(500);
            StartGSM = SET_TXT;      // next state is SET TXT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CFUN=1 again after 100ms
            }
         }         
      }   
             
     
// ********************* SET TXT MODE *****************************************
      case SET_TXT:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("SET TXT MODE");
         GSM_Send(TXT);         // Set message type as TXT

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("TXT MODE SET...");      // display success
            delay_ms(500);
            StartGSM = SET_GSM;      // next state is  GSM MODE!!!!!!
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT+CMGF=1 again
               break;
            }
            else{
               break;               // try sending AT again after 100ms
            }
         }
         
      }
// *************************** SET GSM MODE ***********************************
      case SET_GSM:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("SET GSM MODE");
         GSM_Send(GSM_MODE);            // Set GSM mode

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("GSM MODE SET...");      // display success
            delay_ms(500);
            StartGSM = SET_STORAGE;      // next state is SET ALERT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CSCS="GSM" again after 100ms
            }
         }         
      }

// ********************** SET STORAGE TO SIM CARD *****************************
      case SET_STORAGE:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("SET STORAGE");
         GSM_Send(STORE_SIM);            // Set GSM mode

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("STORE TO SIM...");      // display success
            delay_ms(500);
            StartGSM = DEL_MSG;      // next state is DEL_MESSAGES
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CPMS="SM","SM","SM" again after 100ms
            }
         }         
      }
     
// ************************** DELETE MESSAGES *********************************
      case DEL_MSG:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("DELETE MESSAGES");
         GSM_Send(ERASE_SMS);            // Delete all messages

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("MESSAGES DELETED...");      // display success
            delay_ms(500);
            StartGSM = CONNECT;      // next state is CONNECT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CMGD=1,4 again after 100ms
            }
         }         
      }
     
  // ************************** CONNECT TO NETWORK *********************************
      case CONNECT:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("CONNECT...");
         GSM_Send(REGISTER_TO_NET);            // Set GSM mode

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("OK...");      // display success
            delay_ms(500);
            StartGSM = WAIT_CELL;      // next state is SET ALERT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 5 seconds (50 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CREG=0 again after 100ms
            }
         }         
      }    // case brace   
     
// ************************* WAIT REGISTRATION ********************************     
      case WAIT_CELL:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("WAITING CELL");
         lcd_gotoxy(1,2);
         lcd_putc("REGISTRATION");
         lcd_gotoxy(15,2);
         printf(lcd_putc,"%u", NotResponding);
         GSM_Send(CHECK_REGISTERED);                           // query module for registration status
         if(Get_response() == GSM_REGISTERED){   // GSM returned "GSM_REGISTERED",  meaning +CREG: 0,1 or +CREG: 0,5 for roaming
            delay_ms(500);
            lcd_putc('\f');                  //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("REGISTERED...");      // display success
            delay_ms(2000);
            StartGSM = SEND_AT;              // next state is SEND_AT
            Not_Initialized = 0;             // GSM initialized, exit loop
            break;
         }
         else {                              // GSM didn't return "GSM_REGISTERED"
            delay_ms(200);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't register to network for 20 seconds (100 passes with 200ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CREG? again after 100ms
            }
         }       
         
      }

      case GSM_ERROR:{
         
      }     
     

   }   // switch brace   
}
// while brace
}    // function brace

// *****************************************************************************

#int_TIMER0                      //interrupt every 104ms
void  TIMER0_isr(void) {
//   EmptyDelay++;                 //increment Empty wait timer
   output_toggle(OK_STATUS);
 
   Second++;
   if(Second == 5){
      Second = 0;
      GO = 1;                    //set the GO flag every 520ms
      BLINK = !BLINK;            // toggle alarm led, if any
         lcd_gotoxy (13,2);
   }
   
}
//-----------RS232 data recieve ISR------------------------------------------------------------
#int_RDA
void RDA_isr(void){
  tmp=getc();                      // get received char and thus also clear interrupt flag 

   buffer[next_in]= tmp;            // move received char to the appropriate place in buffer
   ++next_in;                       // increment IN pointer
   
   if(next_in==BUFFER_SIZE) {       // if we have 32, go back to 0         
      next_in=0;
      };

// Process reception through state machine
//Possible data from GSM module that will be handled is:
// r1on   - doesn't matter capital or not ar any mix
// r1off
// r2on
// r2off
// r3on
// r3off
// r4on
// r4off
// OK + CR +LF
// ERROR + CR + LF
// +CREG
// +CMGS
// "< "     arrow-space combo! This is the response from GSM module after you send
// AT+CMGS = "some phone number" command and the module is ready for scratch message from MCU
// ERROR
//
// Commands:
// R1OFFR2ON            for example, any combination works
// status?              command to receive the status from GSM
// ADD: +38267600917    command to add this number to eeprom
// DEL: +38267600917    vommand to remove this number from eeprom
// NUM?                 command to send out currently stored GSM numbers
//
// Flags set by this state machine are:
//
// status_req = 1;            inform MAIN to send status SMS
// numbers_status_req = 1;    inform MAIN to send status of the numbers stored in EEPROM, response to NUM?
// Number_To_Store = 1;       inform MAIN to store a new number to EEPROM, response to ADD
// Number_To_Delete = 1;      inform MAIN to delete a number from EEPROM, response to DEL
 
  switch (gsm_state) {
   
//get initial character, 'r','s', 'O','E' or '> ','A','D', 'N' or '+'
      case 0:{

         if(tmp == 'O' || tmp == 'O')     //we have "O", could be "OK"
            gsm_state = 3;                //expecting 'K'
         else
         if(tmp == '>')                   //have arrow, vould be "> "
            gsm_state = 4;                //expecting space
         else
         if(tmp == 'E')
            gsm_state = 5;                // we have 'E', could be "ERROR"
         
         else
         if(tmp == '+')
            gsm_state = 6;                // we have '+', could be "+CREG" or "+CMGS" or telephone number
         
         break;
         
         
         
            }
           
           
           
       
 //********WE HAVE RECIEVED 'O' AS A FIRST CHARACTER***************************
      case 3:{
         if(tmp == 'K')             //we have 'OK'
            gsm_state = 31;         //expecting CR + LF
         else
            gsm_state = 0;
            break;
      }
      case 31:{
         if(tmp == 13)              //we have OK + CR (binary 13)
            gsm_state = 32;         //expecting LF (binary 10)
         else
            gsm_state = 0;
         break;
      }
      case 32:{
         if(tmp == 10){             //we have OK + CR +LF, OK response is complete
            response_received = 1;  //set reception flag
            response = GSM_OK;
            responseID = response;  // indicate OK recieved from modem       
         }
         gsm_state = 0;             //reset state machine
         break;
           
         }
         
// We received '>' character, could be "> " that indicates that GSM module is ready to accept message from MCU
      case 4:{
         if(tmp == ' '){                               //we have "> ", module ready
            response_received = 1;                    // set reception flag
            response = GSM_Ready_To_Receive_Message;  //set response flag
            ResponseID = response;                    //responseID = 2
         }
         gsm_state = 0;
         break;
      }
     
// We received 'E', could be ERROR
      case 5:{
         if(tmp == 'R')
            gsm_state = 51;
         else
         gsm_state = 0;
         break; 
   }
      case 51:{
         if(tmp == 'R')
            gsm_state = 52;
         else
         gsm_state = 0;
         break; 
   }
      case 52:{
         if(tmp == 'O')
            gsm_state = 53;
         else
         gsm_state = 0;
         break; 
   }
      case 53:{
         if(tmp == 'R')
            gsm_state = 54;
         else
         gsm_state = 0;
         break; 
   }
      case 54:{
         if(tmp == 13)
            gsm_state = 55;
         else
         gsm_state = 0;
         break; 
   }
      case 55:{
         if(tmp == 10){
            response_received = 1;  //set reception flag
            response = GSM_ERROR;
            responseID = response;  // indicate ERROR recieved from modem       
         }
         gsm_state = 0;             //reset state machine
         break; 
   }
   
// We received '+', could be +CREG or +CMGS or telephone number
      case 6:{
         if(tmp == 'C')
            gsm_state = 61;
         else if(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'){   // we might have a phone number
            gsm_state = 69;
            Next_Number = 0;
            GSM_NUMBER[Next_Number] = '+';   // put '+' into first location of buffer
            Next_Number++;
            GSM_NUMBER[Next_Number] = tmp;   // put received number into second location of buffer
            Next_Number++;
         }   
         else
            gsm_state = 0;
         break; 
   }
      case 61:{
         if(tmp == 'R')            // proceed to look for +CREG
            gsm_state = 62;
         else if(tmp == 'M')
            gsm_state = 7;         // look for +CMGS
         else
            gsm_state = 0;
         break; 
   }
      case 62:{
         if(tmp == 'E')
            gsm_state = 63;
         else
            gsm_state = 0;
         break; 
   }
      case 63:{
         if(tmp == 'G')
            gsm_state = 64;
         else
            gsm_state = 0;
         break; 
   }
      case 64:{
         if(tmp == ':')
            gsm_state = 65;
         else
            gsm_state = 0;
         break; 
   }
//////////
     case 65:{
         if(tmp == ' ')
            gsm_state = 66;
         else
            gsm_state = 0;
         break; 
   }
      case 66:{
         if(tmp == '0' || tmp == '1' || tmp == '2')
            gsm_state = 67;
         else
            gsm_state = 0;
         break; 
   }
     case 67:{
         if(tmp == ',')
            gsm_state = 68;
         else
            gsm_state = 0;
         break; 
   }
      case 68:{
         if(tmp == '1' || tmp == '5'){
            response_received = 1;           //set reception flag
            response = GSM_REGISTERED;
            responseID = response;           // indicate "+CREG: X,1" recieved from modem
            disable_interrupts(INT_RDA);      // disable UART receive interrupt for a while because there is also     
         }                                    // an "OK" coming from GSM after +CREG and it fools the state
                                             // machine into reporting the "OK" answer. Be sure to turn it back on.
                                             //
         gsm_state = 0;             //reset state machine
         break; 
   }
//****************RECEIVING PHONE NUMBER***************************************
   case 69:{                                   
         if((tmp != '"')&&(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'|| tmp == '0')){
            GSM_NUMBER[Next_Number] = tmp;
            Next_Number++;
         }                           
         else if(tmp == '"'){
            GSM_NUMBER[Next_Number] = '\0';      // terminate the string with NULL
            Next_Number = 0;
            gsm_state = 0;
            break;
         }
         else {
            Next_Number = 0;
            gsm_state = 0;
         }     
            break;   
   }   


//*****************************************************************************           
//we don't have anything good, ERROR   
      default:{
         gsm_state = 0;
         break;
      }     
   }  // switch brace
 
}
// ****************************************************************************
#int_AD
void AD_isr(void){
}

#int_EXT
void  EXT_isr(void) {

}
//----------------------------------------------------------------------
// end interrupt
//----------------------------------------------------------------------


void main() {
   setup_adc_ports(AN0_TO_AN2);                  //AN1 to AN2 analog input
   setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_4);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);     //104 ms overflow
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //13.1 ms overflow

   output_float (BOOT);
 
   output_float(PIN_C4);
   output_float(PIN_C3);
   lcd_init();
   
   Delay_ms(100);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   output_HIGH (GSM_RESET);
   
   Clear_UART_Buffer();   
   Init_GSM();                   // init module
   
// ******************** send test message  ************************************
   lcd_putc('\f');         //CLEAR lcd
   lcd_gotoxy(1,1);
   lcd_putc("SENDING SMS");   
   GSM_Send(SEND_SMS);        // send a command to send SMS to the module
   Wait_response(GSM_Ready_To_Receive_Message); // wait for "> "
   delay_ms(200);
   fputs("His followers called him Mahasamatman and said he was a god. R. Zelazny, Lord of light");
   delay_cycles(1);
   Delay_ms(100);
   fputc(0x1A);                  // send CTRL+Z to send the message 
   Wait_response(GSM_OK);
   delay_cycles(1);
   lcd_putc('\f');         //CLEAR lcd
   lcd_gotoxy(1,1);
   lcd_putc("SMS SENT. SUCCESS");   
   
   
   while(TRUE){
      //TODO: User Code
   }

}
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Aug 25, 2018 8:36 pm     Reply with quote

Well, 50 or so messages wasn't enough. The first example was very, very buggy. Here is V 2.0, definitely way better. Still some work to do, but better.

main.c

Code:

#include <main.h>

#include <i2c_Flex_LCD_driver.c>
//#include <defs.h>                //definitions of pins and registers
#define BUFFER_SIZE 250          //create 250 byte large buffer
char buffer[BUFFER_SIZE];
int8 next_in = 0;                //max. next_in =  BUFFER_SIZE -1 !!!!!

// buffer to hold phone number read from EEPROM or SMS message. This is the number SMS is sent to.
#define   GSM_NUMBER_SIZE   16                  // GSM number buffer size
char GSM_NUMBER[GSM_NUMBER_SIZE];               // GSM number buffer   
int8 Next_Number = 0; // pointer to the position in buffer

#define OK_STATUS PIN_E1            // blink LED so you know PIC does something
unsigned int8  SMSCounter = 0;      //number of SMS's sent
unsigned int8  Second = 0;          //sets a flag GO every second or whatever
int8 SecondOld = 0;
int1           GO;                  //starts the execution of the main loop
int1           BLINK;               //holds the state for the blinking LEDs
int8 gsm_init= 0;
// Set of AT commands
const char AT[] = "AT\r\n";                                    // Every AT command starts with "AT"
const char ATE[] = "ATE1\r\n";                                 // enable command echo
const char CFUN[] = "AT+CFUN=1\r\n";                           // full phone functionality
const char IPR[] = "AT+IPR=57600\r\n";                         // Set COM speed, not used in this program. Change COM settings if you use it
const char TXT[] = "AT+CMGF=1\r\n";                            // set TXT messages
const char GSM_MODE[] = "AT+CSCS=\"GSM\"\r\n";                 // Set GSM_MODE
const char STORE_SIM[] = "AT+CPMS=\"SM\",\"SM\",\"SM\"\r";     // Store on SIM Card
const char READ_SMS[] = "AT+CMGR=1\r\n";                       // Command for reading message from location 1 from inbox
const char ERASE_SMS[] = "AT+CMGD=1,4\r\n";                    // Erasing all messages from inbox
const char CHECK_REGISTERED[] = "AT+CREG?\r\n";                // Commant to check cell network registration. result: +CREG: 0,1 or 0,5 for roaming
const char REGISTER_TO_NET[] = "AT+CREG=0\r\n";                // register to the network

const char SEND_SMS[] = "AT+CMGS=\"+38267600917\"\r\n";        // Send SMS
//
// Responses to parse
const int8  GSM_OK = 10;
const int8  GSM_Ready_To_Receive_Message = 11;
const int8  GSM_ERROR = 12;
const int8  GSM_CONN_OK = 14;
const int8  GSM_REGISTERED = 15;
const int8  SMS_SENT = 16; 

// State machine control variables
//char gsm_state = 0;              // initial state of decoding routine
int16   gsm_state = 0;
char response_received = 0;      // 0-no response, 1-response from module
signed int responseID = -1, response = -1;
int8 rspns = 0;
int8 TMP_Response = 0;

#define     BOOT_GSM   1         // boot state machine states
#define     SEND_AT   2
#define     SEND_ECHO   3
#define     SET_TXT   4
#define     SET_GSM   5
#define     SET_ALERT   6
#define     SET_STORAGE   7
#define     DEL_MSG   8
#define     FULL_FUNCTION 9
#define     CONNECT 10
#define     WAIT_CELL   11
#define     GSM_ERROR   12

#define     BOOT_TIME   10       // time to wait for the module to be ready, in seconds

int8   StartGSM = 1;
int8   Not_Initialized = 1;
int8   NotResponding = 0;                 // timer for GSM response time
#define   MaxResponseTime 100             // GSM timeout = MaxResponseTime * 100ms ie 10s
char tmp;
int8  SMS_Was_Sent = 0;
#define  BOOT   PIN_D2                    // GSM boot pin. A logic level FET 30N06L (source to system GND, drain to  module GND)  is used to turn the module ON or OFF
#define  GSM_RESET   PIN_D0               // sim800l reset pin, not used here. The function would be the same as above.
int8 GSM_Tilt = 0;
int16  Response_Time = 0;
int8   GSM_Doesnt_Respond = 0;
#define Max_Response_Time  200
#define Max_No_Response 200


// ***************************** functions ************************************
void Clear_ResponseID (void){
   responseID = -1;
}

// clear UART buffer
void Clear_UART_Buffer() {                // not neccesary, used to see better and easier what is happening with PICKIT3 because the buffer is empty
   next_in=0;
   while (next_in < BUFFER_SIZE){
      buffer[next_in] = '\0';
      next_in++;
   }
   next_in=0;
}

//-----------------------------------------------------------------------------
//------------------------ GET RESPONSE ---------------------------------------
signed int Get_Response(){
   while (response_received == 0){      // wait for the module to answer
      if(SecondOld != Second){
   
      }
   }  // while
   response_received = 0;                 // GSM responded
      return responseID;                  // report what it answered on UART
}
//------------ WAIT RESPONSE TO COMMAND FROM GSM ------------------------------
void Wait_response(rspns) {          // Wait for GSM response
   GSM_Tilt = 0;
   Response_Time = 0;
   GSM_Doesnt_Respond = 0;
   Get_response();
   TMP_Response = responseID;
   while(1){
 //     delay_ms(30);
      if (TMP_Response == rspns){          // everything ok, this is the response we wait
         GSM_Tilt = 0;
         break;
    }
      else if(TMP_Response == GSM_ERROR){  // GSM returned  ERROR
         GSM_Tilt = 1;
         break;
    }
       else if(TMP_Response == -1){        // GSM doesn't answer
         GSM_Doesnt_Respond++;
         if(GSM_Doesnt_Respond > Max_No_Response){
            GSM_Tilt = 3;
            break;
         }
      }
      else{                                        // unknown answer too many times, reset module after 6 seconds
         Response_Time++;
         if(Response_Time > Max_Response_Time){
            GSM_Tilt = 4;
            break;
         }  // if
      }     // else
   }        // while
}           // function

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Send command or data to GSM module
void GSM_Send(char *s)
{
// Send command or data string
   while(*s) {                   // as long as you don't encounter NULL
      fputc(*s++);                 // send characters to RS232
   }
}
//*****************************************************************************
//*****************************************************************************
// GSM module init sequence
// ****************************************************************************
void Init_GSM (void){
   
while (Not_Initialized){            // stay here as long as needed. Preset this variable to 1 before coming here

   switch (StartGSM) {
     
// *************************** BOOT *******************************************
      case BOOT_GSM:{
         Not_Initialized = 1;       
         output_low (BOOT);         // turn the module OFF
         delay_ms(1000);
         output_high (BOOT);        // and back ON
         lcd_putc('\f');            //CLEAR lcd
         delay_ms(100);
         lcd_putc("BOOTING IN:");
         int8 i = 0;
         while(i<BOOT_TIME){
            i++;
            lcd_gotoxy(12,1);
            printf(lcd_putc, "%3u", BOOT_TIME-i);  // display countdown till BOOT
            delay_ms(1000);
         }
         lcd_putc('\f');            //CLEAR lcd   
         delay_ms(1000);
         
         StartGSM = SEND_AT;         // next state is AT
         break;
      }
// ********************** SEND AT COMMAND ********************************     
      case SEND_AT:{
         lcd_gotoxy(1,1);
         lcd_putc("SENDING AT...");
         GSM_Send(AT);                  // AT

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("AT OK...");      // display success
            delay_ms(500);
            StartGSM = SEND_ECHO;      // next state is SEND_ECHO
            NotResponding = 0;
            break;
         }
         else {                        // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = BOOT_GSM;         // boot GSM again if it doesn't even respond to AT
               break;
            }
            else{
               break;               // try sending AT again after 100ms
            }
         }           
      } // end case
// ************************* SEND ECHO COMMAND ********************************         
      case SEND_ECHO:{
         lcd_gotoxy(1,1);
         lcd_putc("SET ECHO ON");
         GSM_Send(ATE);            //ATE0
         
         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("ECHO ON...");      // display success
            delay_ms(500);
            StartGSM = FULL_FUNCTION;           // next state is CFUN
            NotResponding = 0;
            break;
         }
         else {                        // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending ATE1 again after 100ms
            }
         }
         
      } // end case
     
// ************************** FULL FUNCTIONALITY ******************************
      case FULL_FUNCTION:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("CFUN = 1...");
         GSM_Send(CFUN);            // Set full function

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("OK...");      // display success
            delay_ms(500);
            StartGSM = SET_TXT;      // next state is SET TXT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CFUN=1 again after 100ms
            }
         }         
      }                     
// ********************* SET TXT MODE *****************************************
      case SET_TXT:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("SET TXT MODE");
         GSM_Send(TXT);         // Set message type as TXT

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("TXT MODE SET...");      // display success
            delay_ms(500);
            StartGSM = SET_GSM;      // next state is  GSM MODE!!!!!!
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT+CMGF=1 again
               break;
            }
            else{
               break;               // try sending AT again after 100ms
            }
         }       
      }
// *************************** SET GSM MODE ***********************************
      case SET_GSM:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("SET GSM MODE");
         GSM_Send(GSM_MODE);            // Set GSM mode

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("GSM MODE SET...");      // display success
            delay_ms(500);
            StartGSM = SET_STORAGE;      // next state is SET ALERT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CSCS="GSM" again after 100ms
            }
         }         
      }

// ********************** SET STORAGE TO SIM CARD *****************************
      case SET_STORAGE:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("SET STORAGE");
         GSM_Send(STORE_SIM);            // Set GSM mode

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("STORE TO SIM...");      // display success
            delay_ms(500);
            StartGSM = DEL_MSG;      // next state is DEL_MESSAGES
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CPMS="SM","SM","SM" again after 100ms
            }
         }         
      }
     
// ************************** DELETE MESSAGES *********************************
      case DEL_MSG:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("DELETE MESSAGES");
         GSM_Send(ERASE_SMS);            // Delete all messages

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_cycles(1);
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("MESSAGES DELETED...");      // display success
            delay_ms(500);
            StartGSM = CONNECT;      // next state is CONNECT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 10 seconds (100 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CMGD=1,4 again after 100ms
            }
         }         
      }
     
  // ************************** CONNECT TO NETWORK *********************************
      case CONNECT:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("CONNECT...");
         GSM_Send(REGISTER_TO_NET);            // Set GSM mode

         if(Get_response() == GSM_OK){   // GSM returned "OK"
            Clear_ResponseID();
            delay_ms(500);
            lcd_putc('\f');            //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("OK...");      // display success
            delay_ms(500);
            StartGSM = WAIT_CELL;      // next state is SET ALERT
            NotResponding = 0;
            break;
         }
         else {                     // GSM didn't return "OK"
            delay_ms(100);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't respond correctly for 5 seconds (50 passes with 100ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CREG=0 again after 100ms
            }
         }         
      }    // case brace   
     
// ************************* WAIT REGISTRATION ********************************     
      case WAIT_CELL:{
         lcd_putc('\f');         //CLEAR lcd
         lcd_gotoxy(1,1);
         lcd_putc("WAITING CELL");
         lcd_gotoxy(1,2);
         lcd_putc("REGISTRATION");
         lcd_gotoxy(15,2);
         printf(lcd_putc,"%u", NotResponding);
         GSM_Send(CHECK_REGISTERED);                           // query module for registration status
         if(Get_response() == GSM_REGISTERED){   // GSM returned "GSM_REGISTERED",  meaning +CREG: 0,1 or +CREG: 0,5 for roaming
            Clear_ResponseID();
            delay_ms(500);
            lcd_putc('\f');                  //CLEAR lcd
            lcd_gotoxy(1,1);
            lcd_putc("REGISTERED...");      // display success
            delay_ms(2000);
            StartGSM = SEND_AT;              // next state is SEND_AT
            Not_Initialized = 0;             // GSM initialized, exit loop
            break;
         }
         else {                              // GSM didn't return "GSM_REGISTERED"
            delay_ms(200);
            NotResponding++;         //
            if(NotResponding > MaxResponseTime){ // GSM didn't register to network for 20 seconds (100 passes with 200ms delay)
               NotResponding = 0;
               StartGSM = SEND_AT;         // send AT again
               break;
            }
            else{
               break;               // try sending AT+CREG? again after 100ms
            }
         }               
      }
      case GSM_ERROR:{       
      }         

   }   // switch brace   
}
// while brace
}    // function brace

// ************************* END FUNCTIONS ************************************

#int_TIMER0                         //interrupt every 104ms
void  TIMER0_isr(void) {
//   EmptyDelay++;                  //increment Empty wait timer
   output_toggle(OK_STATUS);        // blink LED
 
   Second++;
   if(Second == 5){                 // wrong name :-)
      Second = 0;
      GO = 1;                       //set the GO flag every 520ms
      BLINK = !BLINK;               // toggle alarm led, if any every x*104ms
         lcd_gotoxy (13,2);
   }   
}
//---------------------- RS232 data recieve ISR -------------------------------
#int_RDA
void RDA_isr(void){
  tmp=getc();                       // get received char and thus also clear interrupt flag 

   buffer[next_in]= tmp;            // move received char to the appropriate place in buffer
   ++next_in;                       // increment IN pointer
   
   if(next_in==BUFFER_SIZE) {       // if we have 32, go back to 0         
      next_in=0;
      };

// Process received data from GSM through state machine
// Possible data from GSM module that will be handled is:
// r1on   - doesn't matter capital or not ar any mix
// r1off
// r2on
// r2off
// r3on
// r3off
// r4on
// r4off
// OK + CR +LF
// ERROR + CR + LF
// +CREG
// +CMGS
// "> "     arrow-space combo! This is the response from GSM module after you send
// AT+CMGS = "some phone number" command and the module is ready for scratch message from MCU
// ERROR
//
// Commands:
// R1OFFR2ON            for example, any combination works
// status?              command to receive the status from GSM
// ADD: +38267600917    command to add this number to eeprom
// DEL: +38267600917    vommand to remove this number from eeprom
// NUM?                 command to send out currently stored GSM numbers
//
// Flags set by this state machine are:
//
// status_req = 1;            inform MAIN to send status SMS
// numbers_status_req = 1;    inform MAIN to send status of the numbers stored in EEPROM, response to NUM?
// Number_To_Store = 1;       inform MAIN to store a new number to EEPROM, response to ADD
// Number_To_Delete = 1;      inform MAIN to delete a number from EEPROM, response to DEL
// response_received = 1;     got some kind of a response from GSM
 
  switch (gsm_state) {
   
//get initial character, 'r','s', 'O','E' or '> ','A','D', 'N' or '+'
      case 0:{

         if(tmp == 'O' || tmp == 'O')     //we have "O", could be "OK"
            gsm_state = 3;                //expecting 'K'
         else
         if(tmp == '>')                   //have arrow, vould be "> "
            gsm_state = 4;                //expecting space
         else
         if(tmp == 'E')
            gsm_state = 5;                // we have 'E', could be "ERROR"
         
         else
         if(tmp == '+')
            gsm_state = 6;                // we have '+', could be "+CREG" or "+CMGS" or telephone number
         
         break;     
            }       
 //********WE HAVE RECIEVED 'O' AS A FIRST CHARACTER***************************
      case 3:{
         if(tmp == 'K')             //we have 'OK'
            gsm_state = 31;         //expecting CR + LF
         else
            gsm_state = 0;
            break;
      }
      case 31:{
         if(tmp == 13)              //we have OK + CR (binary 13)
            gsm_state = 32;         //expecting LF (binary 10)
         else
            gsm_state = 0;
         break;
      }
      case 32:{
         if(tmp == 10){             //we have OK + CR +LF, OK response is complete
            response_received = 1;  //set reception flag
            response = GSM_OK;
            responseID = response;  // indicate OK recieved from modem       
         }
         gsm_state = 0;             //reset state machine
         break;
           
         }
         
// We received '>' character, could be "> " that indicates that GSM module is ready to accept message from MCU
      case 4:{
         if(tmp == ' '){                                 //we have "> ", module ready
            response_received = 1;                       // set reception flag
            response = GSM_Ready_To_Receive_Message;     //set response flag
            ResponseID = response;                       //
         }
         gsm_state = 0;
         break;
      }
     
// We received 'E', could be ERROR
      case 5:{
         if(tmp == 'R')
            gsm_state = 51;
         else
         gsm_state = 0;
         break; 
   }
      case 51:{
         if(tmp == 'R')
            gsm_state = 52;
         else
         gsm_state = 0;
         break; 
   }
      case 52:{
         if(tmp == 'O')
            gsm_state = 53;
         else
         gsm_state = 0;
         break; 
   }
      case 53:{
         if(tmp == 'R')
            gsm_state = 54;
         else
         gsm_state = 0;
         break; 
   }
      case 54:{
         if(tmp == 13)
            gsm_state = 55;
         else
         gsm_state = 0;
         break; 
   }
      case 55:{
         if(tmp == 10){
            response_received = 1;  //set reception flag
            response = GSM_ERROR;
            responseID = response;  // indicate ERROR recieved from modem       
         }
         gsm_state = 0;             //reset state machine
         break; 
   }
   
// We received '+', could be +CREG or +CMGS or telephone number
      case 6:{
         if(tmp == 'C')
            gsm_state = 61;
         else if(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'){   // we might have a phone number
            gsm_state = 69;
            Next_Number = 0;
            GSM_NUMBER[Next_Number] = '+';   // put '+' into first location of buffer
            Next_Number++;
            GSM_NUMBER[Next_Number] = tmp;   // put received number into second location of buffer
            Next_Number++;
         }   
         else
            gsm_state = 0;
         break; 
   }
      case 61:{
         if(tmp == 'R')            // proceed to look for +CREG
            gsm_state = 62;
         else if(tmp == 'M')
            gsm_state = 7;         // look for +CMGS
         else
            gsm_state = 0;
         break; 
   }
      case 62:{
         if(tmp == 'E')
            gsm_state = 63;
         else
            gsm_state = 0;
         break; 
   }
      case 63:{
         if(tmp == 'G')
            gsm_state = 64;
         else
            gsm_state = 0;
         break; 
   }
      case 64:{
         if(tmp == ':')
            gsm_state = 65;
         else
            gsm_state = 0;
         break; 
   }
//////////
     case 65:{
         if(tmp == ' ')
            gsm_state = 66;
         else
            gsm_state = 0;
         break; 
   }
      case 66:{
         if(tmp == '0' || tmp == '1' || tmp == '2')
            gsm_state = 67;
         else
            gsm_state = 0;
         break; 
   }
     case 67:{
         if(tmp == ',')
            gsm_state = 68;
         else
            gsm_state = 0;
         break; 
   }
      case 68:{
         if(tmp == '1' || tmp == '5'){       // we are registered, handle also the OK that is comming from the module after this
            gsm_state = 681;
         }                                   
         else                                    //
         gsm_state = 0;                      //reset state machine
         break; 
   }
      case 681:{
         if(tmp != 'K'){
            gsm_state = 681;
         }
         else{
            response_received = 1;           //set reception flag
            response = GSM_REGISTERED;
            responseID = response;           // indicate "+CREG: 0,1" or "+CREG: 0,5" recieved from modem, followed by "K" for "OK"                         
            gsm_state = 0;                   //reset state machine       
         }
         break; 
   }   
   
//**************** RECEIVING PHONE NUMBER *************************************
   case 69:{                                   
         if((tmp != '"')&&(tmp =='1'||tmp =='2'||tmp =='3'||tmp =='4'||tmp =='5'||tmp =='6'||tmp =='7'||tmp =='8'||tmp =='9'|| tmp == '0')){
            GSM_NUMBER[Next_Number] = tmp;
            Next_Number++;
         }                           
         else if(tmp == '"'){
            GSM_NUMBER[Next_Number] = '\0';      // got NULL, end of string
            Next_Number = 0;
            gsm_state = 0;
            break;
         }
         else {
            Next_Number = 0;
            gsm_state = 0;
         }     
            break;   
   }
// ****************************************************************************
     case 7:{                             // catch "+CMGS: XXXX" followed by "OK"
         if(tmp == 'G')                   // that tells that an SMS was actually sent
            gsm_state = 71;
         else
            gsm_state = 0;
         break; 
   }
      case 71:{
         if(tmp == 'S'){
            gsm_state = 72;
         }                                    //
         else
            gsm_state = 0;
         break;
      }
      case 72:{
         if(tmp == ':'){                     // this one is to escape "AT+CMGS=...." command
            gsm_state = 73;
         }                                    //
         else
            gsm_state = 0;
         break;
      }           
      case 73:{
         if(tmp != 'K'){                     // hang here until "K" comes as the end of the required sequence
             gsm_state = 73;       
         }
         else{
            response_received = 1;           //set reception flag
            response = SMS_SENT;
            responseID = response;           // indicate "+CMGS: XXXX" recieved from modem, followed by an "OK" XXX is the number of SMS-ses sent
            gsm_state = 0;
         }
      break;   
     
      }

//*****************************************************************************           
//we don't have anything good, ERROR   
      default:{
         gsm_state = 0;
         break;
      }     
   }  // switch brace
 
}
// ****************************************************************************
#int_AD
void AD_isr(void){
}

#int_EXT
void  EXT_isr(void) {

}
//----------------------------------------------------------------------
// end interrupt
//----------------------------------------------------------------------


void main() {
   setup_adc_ports(AN0_TO_AN2);                  //AN1 to AN2 analog input
   setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_4);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);     //104 ms overflow
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);      //13.1 ms overflow

   output_float (BOOT);
 
   output_float(PIN_C4);
   output_float(PIN_C3);
   lcd_init();
   
   Delay_ms(100);
   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   output_HIGH (GSM_RESET);
   
   Clear_UART_Buffer();   
   Init_GSM();                   // init module
   
   while(TRUE){

// ******************** send test message  ************************************
   lcd_putc('\f');         //CLEAR lcd
   lcd_gotoxy(1,1);
   lcd_putc("SENDING SMS");   
   GSM_Send(SEND_SMS);        // send a command to send SMS to the module
   Delay_ms(10);
   delay_cycles(1);
   Wait_response(GSM_Ready_To_Receive_Message); // wait for "> "
   if(GSM_Tilt == 0){                           // everything ok so far
      delay_cycles(1);
      delay_ms(200);
      fputs("His followers called him Mahasamatman and said he was a god. R. Zelazny, Lord of light");
      delay_cycles(1);
      Delay_ms(100);
      fputc(0x1A);                              // send CTRL+Z to send the message
   }
   else{
      lcd_putc('\f');                           //CLEAR lcd
      lcd_gotoxy(1,1);
      lcd_putc("ready to rec tilt");            // wromg answer from GSM
      while(1){
         delay_cycles(1);                       // stay here
      }
   }
   Wait_response(GSM_Ready_To_Receive_Message);       // module returns "> " first after message was sent
   Wait_response (SMS_SENT);                          // and then " +CMGS: XX" ,  followed by "OK"
   if(GSM_Tilt == 0){
      delay_cycles(1);
      lcd_putc('\f');         //CLEAR lcd
      lcd_gotoxy(1,1);
      lcd_putc("SMS SENT. SUCCESS");     
   }
   else{
      lcd_putc('\f');         //CLEAR lcd
      lcd_gotoxy(1,1);
      lcd_putc("sent tilt");                          // wromg answer from GSM
     
      while(1){
         delay_cycles(1);     // stay here
      }
   }
     
   
   Delay_ms(10000);           // send an SMS every 10s



   }

}

jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

SIM800L Implementation
PostPosted: Tue Jul 30, 2019 11:34 am     Reply with quote

Hi,
Thank you for all your work on this. I'm getting ready to use this on my own project. Have you made any improvements on this since your last posting?

Thanks
_________________
Jürgen
www.jgscraft.com
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Sat Aug 10, 2019 6:35 pm     Reply with quote

I have abandoned SIM800 module since I found it to be very unreliable. You have to change the firmware to work in Europe and even with that they seem to drop the connection all the time. I moved to an A6 based module (5€), which by my experience works much better. The same project, though. Tweaked for their AT set and their answers. The project works 99% of the time, currently I'm working on error recovery, if the modem looses connection or fails to send an SMS. So yes, there are improvements. On the hardware side, I'm also moving to a different PIC (18f46k22), different battery charger and different step-up regulators, because I need 3 different voltages for this to work. I can send you the code and the schematics for the current thing.

Regards
jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Mon Aug 12, 2019 11:38 am     Reply with quote

Thanks for the reply. I did get some code working for my SIM800 module, using ideas from your post and Gabriel's. I haven't run it very long so I don't know about reliability yet. I'm in the US.
I also use the 18F46K22 family for most of my projects and I also have some A6 modules. Agreed, the multiple voltages is a nuisance. Yes, I am interested in the code and schematics.

Cheers.
_________________
Jürgen
www.jgscraft.com
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Mon Aug 12, 2019 9:34 pm     Reply with quote

The code is in the topics A6 GSM, posted two days ago. Schematics is made in Proteus, if you can open that. Else I'll post images. If you are interested in PCB to avoid breadboard, I can send it to you for the price of postage, along with the specific parts used there (charger, step-up, battery holder and FET. And 4520 PIC, if you need it), so you just plug in USB charger and you are good to go.

Regards,
Samo
jgschmidt



Joined: 03 Dec 2008
Posts: 184
Location: Gresham, OR USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Aug 13, 2019 12:40 am     Reply with quote

Thanks, Samo, I will look at your code in the library. I don't have Proteus, but I would appreciate a picture of your circuit. I don't know if you can post it here but you can send direct to me at jurgen(at)jgscraft.com
Thank you for offer of PCB and parts. Let me know the cost and how to pay you. For me paypal would be easiest. I am in USA.
Kind regards, Jurgen
_________________
Jürgen
www.jgscraft.com
microjack64



Joined: 10 Apr 2020
Posts: 7

View user's profile Send private message

working this code in proteus
PostPosted: Sun Apr 19, 2020 10:45 am     Reply with quote

Hi,
Thank you for all your work on this code. I'm getting ready to use in Proteus.
I am working on the same project in Arduino Proteus, but i am trying same code in my project. I also connect rtc in this project. I am intern engineer.
Thanks.
_________________
mini engineer at https://projectiot123.com
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group