| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| PrinceNai 
 
 
 Joined: 31 Oct 2016
 Posts: 554
 Location: Montenegro
 
 
			    
 
 | 
			
				| SIM800L |  
				|  Posted: Wed Aug 22, 2018 12:54 pm |   |  
				| 
 |  
				| 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: 554
 Location: Montenegro
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Aug 25, 2018 8:36 pm |   |  
				| 
 |  
				| 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
 
 
			        
 
 | 
			
				| SIM800L Implementation |  
				|  Posted: Tue Jul 30, 2019 11:34 am |   |  
				| 
 |  
				| 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: 554
 Location: Montenegro
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sat Aug 10, 2019 6:35 pm |   |  
				| 
 |  
				| 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
 
 
			        
 
 | 
			
				|  |  
				|  Posted: Mon Aug 12, 2019 11:38 am |   |  
				| 
 |  
				| 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: 554
 Location: Montenegro
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Aug 12, 2019 9:34 pm |   |  
				| 
 |  
				| 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
 
 
			        
 
 | 
			
				|  |  
				|  Posted: Tue Aug 13, 2019 12:40 am |   |  
				| 
 |  
				| 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
 
 
 
			    
 
 | 
			
				| working this code in proteus |  
				|  Posted: Sun Apr 19, 2020 10:45 am |   |  
				| 
 |  
				| 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
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |