Programming GM862 in C

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • LyTseu
    New Member
    • Aug 2010
    • 14

    Programming GM862 in C

    Hello I'm having trouble, BIG trouble programing a GM862 from telit.
    First of all I'm using pic18f45k20, using development kit pickit3.
    I've been trying to communicate with the pickit to the GM862 using UART (connecting TX and RX), I read online that it is fairly simple etc.. but it doesn't work for me..
    I think the problem is my UART, I'm not sure how it works and I dont get any thing....
    Below is the code I'm using deriving from the sample given from the vendor...
    If someone can really help me on that! This is my final project to graduate! thank youuu...

    Code:
    #include <p18f45k20.h>
    #include <usart.h>
    #include <delays.h>
    #include <string.h>
    #include <stdio.h>
    #define in usart.h
    #define in usart.h
    
    
    // set of AT commands
    const char atc1[] = "ATE0";                      // disable command echo
    const char atc2[] = "AT# CAP= 1";                // enables handsfree external mic/ear audio path
    const char atc3[] = "ATD19168214521;";             // place a call to phone number 123456789
                                                     // instead of 123456789 insert your phone number
    const char atc4[] = "ATH";                       // hang up
    const char atc5[] = "ATA";                       // answer a call
    const char atc6[] = "AT#HFMICG=4";               // handsfree microphone gain
    const char atc7[] = "AT#SHFEC=1";                // handsfree echo canceller
    const char atc8[] = "AT+CLVL=12";                // loudspeaker volume level
    const char atc9[] = "AT#SRS= 3,0";               // select ringer sound
    const char atc10[] = "ATS0=0";                   // number of rings to auto answer (auto answer disabled)
    
    
    
    int GSM_OK    = 0;
    int GSM_RING  = 1;
    
    char gsm_state = 0;
    char response_rcvd = 0;
    short responseID = -1, response = -1;
    
    
    // copy const to ram string
    char * CopyConst2Ram(char * dest, const char * src){
    char * d ;
     d = dest;
     for(;*dest++ = *src++;)
      ;
     return d;
    }
    
    void interrupt() {
    char tmp;
    if (PIR1bits.RCIF == 1) {
    
    tmp = ReadUSART();
        switch (gsm_state) {
          case  0: {
                    response = -1;                   // clear response
                    if (tmp == 'O')                  // we have 'O', it could be "OK"
                      gsm_state = 1;                 // expecting 'K'
                    if (tmp == 'R')                  // we have 'R', it could be "RING"
                      gsm_state = 10;                // expecting 'I'
                    break;
                   }
          case  1: {
                    if (tmp == 'K') {                // we have 'K' ->
                      response = GSM_OK;             // we have "OK" response
                      gsm_state = 50;                // expecting CR+LF
                    }
                    else
                      gsm_state = 0;                 // reset state machine
                    break;
                   }
          case 10: {
                    if (tmp == 'I')                  // we have 'I', it could be "RING"
                      gsm_state = 11;                // expecting 'N'
                    else
                      gsm_state = 0;                 // reset state machine
                    break;
                   }
          case 11: {
                    if (tmp == 'N')                  // we have 'N', it could be "RING"
                      gsm_state = 12;                // expecting 'G'
                    else
                      gsm_state = 0;                 // reset state machine
                    break;
                   }
          case 12: {
                    if (tmp == 'G') {                // we have 'G' ->
                      response = GSM_RING;           // we have "RING" response
                      gsm_state = 50;                // expecting CR+LF
                    }
                    else
                      gsm_state = 0;                 // reset state machine
                    break;
                   }
          case 50: {
                    if (tmp == 13)                   // we have 13, it could be CR+LF
                      gsm_state = 51;                // expecting LF
                    else
                      gsm_state = 0;                 // reset state machine
                    break;
                   }
          case 51: {
                    if (tmp == 10) {                 // we have LF, response is complete
                      response_rcvd = 1;             // set reception flag
                      responseID = response;         // set response ID
                    }
                    gsm_state = 0;                   // reset state machine
                    break;
                   }
          default: {                                 // unwanted character
                    gsm_state = 0;                   // reset state machine
                    break;
                   }
        }
    
    }
    }
    
    // send ATC command
    
    void send_atc(const char *s)
    {
    // send command string
    while(*s) {
        WriteUSART(*s++);
    } 
    // terminate command with CR
       WriteUSART(0x0D);
    }
    
    // get GSM response, if there is any
    short get_response() {
      if (response_rcvd) {
        response_rcvd = 0;
        return responseID;
      }
      else
        return -1;
    }
    
    // wait for GSM response
    void wait_response(char rspns) {
      while (get_response() != rspns)
        ;
    }
    
    // pause
    void wait() {
       Delay1KTCYx(1000);
    }
    
    
    void main(){
    /*************199********************************************************************************************************************/
    // all pins as digital I/Os
      ANSEL  = 0;
      ANSELH = 0;
    
    // set PORTD inputs
      TRISDbits.TRISD0 = 1;                                // place a call input
      TRISDbits.TRISD1 = 1;                                // hang up input
      TRISDbits.TRISD2 = 1;                                // answer a call input
      TRISDbits.TRISD3 = 1;                                // continue with PIC program
    
    // set RTS pin to zero, we will use only RX i TX
      TRISCbits.TRISC3 = 0;
      PORTCbits.RC3 = 0;
    
    // enable uart rx interrupt
    	PIE1bits.RCIE = 1;
      INTCONbits.PEIE = 1;
      INTCONbits.GIE  = 1;
    /*215********************************************************************************************************************************/
    
    
                                // initialize USART module
    putrsUSART ((const far rom char *)"AT+IPR=19200\r");
    
    
    
      Delay1KTCYx(5000);                                // wait for the GSM module to initialize it self
    
    // negotiate baud rate
      while(1) {
        send_atc("AT");                              // send "AT" string until gsm sets up its baud rade
         Delay1KTCYx(100);                               // and gets it correctly
        if (get_response() == GSM_OK)                // if gsm says "OK" on our baud rate we got it
          break;
      }
    
    
    
    
    // disable command echo
      send_atc(atc1);
      wait_response(GSM_OK);
    
    send_atc(atc3);
    wait_response(GSM_OK);
    
    // change audio path (enables handsfree external mic/ear audio path)
      send_atc(atc2);
      wait_response(GSM_OK);
    
    // handsfree microphone gain
       send_atc(atc6);
       wait_response(GSM_OK);
    
    // handsfree echo canceller
       send_atc(atc7);
       wait_response(GSM_OK);
    
    // loudspeaker volume level
       send_atc(atc8);
       wait_response(GSM_OK);
    
    // select ringer sound
       send_atc(atc9);
       wait_response(GSM_OK);
    
    // number of rings to auto answer (auto answer disabled)
       send_atc(atc10);
       wait_response(GSM_OK);
    
    
    
          }
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    Firstly I would like to say I have used both these products without a problem. Admittedly not together I used a PIC with a Semiens GSM module and a Telit GSM module with a Cyan microprocessor.

    You have a number of issues in you code that are not good. They may or may not be causing a problem.

    Firstly I assume that you have actually connected the TX pin of the PIC to the RX pin of the Tellit and vice versa.


    • In the state machine use an enum to name your states, it will make reading the code a lot easier and eliminate magic numbers that are always a maintenance issue.
    • State 50 and 51 (at least), you are expecting a CR or LF but if it doesn't arrive you through the character away. What if there was a data error and the CR or LF was lost? What if the Telit is configured to not send either CR or LF (which is possible). That character you are throwing away could be the 'O' of OK or 'R' of RING. The state machine is not very resilient to the unexpected.
    • You have no error handling, most UARTS throw error interrupts.
    • You do not transmit a CR or CRLF at the end of any of your AT commands, the AT command protocol uses the CR or CRLF as the delimiter for the end of the command. Without the CR or CRLF you have not finished the command and the Telit command processor will not parse it and action it.
    • Line 176. Sending "AT" to auto baud. That is fine but you do not know the state of the Telits command processor when you send it. Better to clear it down with a few CR (or CRLF) first, something like
      1. Send CR
      2. Short Pause
      3. Send CR
      4. Short Pause
      5. Send CR
      6. Short Pause
      7. Send "AT\r"
      8. Long Pause
      9. If you don't get an OK then goto 1

      The Telit can auto baud off any character so hopefully the CR sequence will allow it to auto-baud and the first AT will work. It will also reset the Telits command processor so it will definitely be expecting an AT
    • Your program code has no resilience to commands not working.

    Comment

    • LyTseu
      New Member
      • Aug 2010
      • 14

      #3
      Thank you very much for your answer.
      Yes I did connected TX to RX and vis versa.
      I'm new at using MPLAB, when I compiled the program it builds it with no error.

      I have a couple question, this code was taken from the vendor but was originally for another board but still using a pic.

      @ line 46:
      tmp = ReadUSART();

      On the vendor example he was using Read1Usart() but when I try to compile with read1usart it doesn't work, so I changed it to readUSART.
      Mplab tells me that I did not define it in the USART.H
      Am I allow to do so? Or is it why I do not read anything? (since I'm using write1, purts1 etc.. but readUsart)

      Thank you...

      Comment

      • LyTseu
        New Member
        • Aug 2010
        • 14

        #4
        Hello,
        Ok so I think I got a little bit further
        when testing my the program below my progam is stuck in the loop to find the baudrate.. Can you help me debug this?

        I tried several method (forcing the baudrate to be 9600) but did not work either...

        Also to try my pgm maybe I'm doing it wrong, I'm inserting a sim card and check the status led (pin 22 on GM862) but the led keeps blinking fast as it doesnt find a network.. so I know (or I think) my pgm is not working

        Reading your post, you said something about handling error, but I'm pretty new to this and I dont know what to write. Would you have a code for it by any change? and where to implement it?



        Code:
                                              
        
        /** I N C L U D E S **************************************************/
        
        #include <p18f45k20.h>
        #include <usart.h>
        #include <delays.h>
        #include <string.h>
        #include <stdio.h>
        #define in usart.h
        #define in usart.h
        
        #pragma config FOSC = INTIO67
        #pragma config WDTEN = OFF, LVP = OFF, MCLRE = OFF
        
        
        // set of AT commands
        const char atc0[] = "AT\r";                      // disable command echo
        const char atc1[] = "ATE0\r";                      // disable command echo
        const char atc2[] = "AT# CAP= 1\r";                // enables handsfree external mic/ear audio path
        const char atc3[] = "ATD19168214521;\r";             // place a call to phone number 123456789
                                                         // instead of 123456789 insert your phone number
        const char atc4[] = "ATH\r";                       // hang up
        const char atc5[] = "ATA\r";                       // answer a call
        const char atc6[] = "AT#HFMICG=4\r";               // handsfree microphone gain
        const char atc7[] = "AT#SHFEC=1\r";                // handsfree echo canceller
        const char atc8[] = "AT+CLVL=12\r";                // loudspeaker volume level
        const char atc9[] = "AT#SRS= 3,0\r";               // select ringer sound
        const char atc10[] = "ATS0=0\r";                   // number of rings to auto answer (auto answer disabled)
        
        
        
        
        short GSM_OK    = 0;
        short GSM_RING  = 1;
        
        char gsm_state = 0;
        short response_rcvd = 0;
        short responseID = -1, response = -1;
        
        
        // copy const to ram string
        char * CopyConst2Ram(char * dest, const char * src){
        char * d ;
         d = dest;
         for(;*dest++ = *src++;)
          ;
         return d;
        }
        
        void interrupt() {
        char tmp;
        if (PIR1bits.RCIF == 1) {
        
        //State Machine, only parsing OK and RING machine
        tmp = ReadUSART();
            switch (gsm_state) {
              case  0: {
                        response = -1;                   // clear response
                        if (tmp == 'O')                  // we have 'O', it could be "OK"
                          gsm_state = 1;                 // expecting 'K'
                        if (tmp == 'R')                  // we have 'R', it could be "RING"
                          gsm_state = 10;                // expecting 'I'
                        break;
                       }
              case  1: {
                        if (tmp == 'K') {                // we have 'K' ->
                          response = GSM_OK;             // we have "OK" response
                          gsm_state = 50;                // expecting CR+LF
                        }
                        else
                          gsm_state = 0;                 // reset state machine
                        break;
                       }
              case 10: {
                        if (tmp == 'I')                  // we have 'I', it could be "RING"
                          gsm_state = 11;                // expecting 'N'
                        else
                          gsm_state = 0;                 // reset state machine
                        break;
                       }
              case 11: {
                        if (tmp == 'N')                  // we have 'N', it could be "RING"
                          gsm_state = 12;                // expecting 'G'
                        else
                          gsm_state = 0;                 // reset state machine
                        break;
                       }
              case 12: {
                        if (tmp == 'G') {                // we have 'G' ->
                          response = GSM_RING;           // we have "RING" response
                          gsm_state = 50;                // expecting CR+LF
                        }
                        else
                          gsm_state = 0;                 // reset state machine
                        break;
                       }
              case 50: {
                        if (tmp == 13)                   // we have 13, it could be CR+LF
                          gsm_state = 51;                // expecting LF
                        else
                          gsm_state = 0;                 // reset state machine
                        break;
                       }
              case 51: {
                        if (tmp == 10) {                 // we have LF, response is complete
                          response_rcvd = 1;             // set reception flag
                          responseID = response;         // set response ID
                        }
                        gsm_state = 0;                   // reset state machine
                        break;
                       }
              default: {                                 // unwanted character
                        gsm_state = 0;                   // reset state machine
                        break;
                       }
            }
        
        }
        }
        
        // send ATC command
        
        void send_atc(const char *s)
        {
        // send command string
        while(*s) {
            WriteUSART(*s++);
        } 
        // terminate command with CR
           WriteUSART(0x0D);
        }
        
        // get GSM response, if there is any
        short get_response(void) {
          if (response_rcvd) {
            response_rcvd = 0;
            return responseID;
          }
          else
            return -1;
        }
        
        // wait for GSM response
        void wait_response(char rspns) {
          while (get_response() != rspns)
            ;
        }
        
        // pause
        void wait() {
           Delay1KTCYx(1000);
        }
        
        
        void main(){
        
        // all pins as digital I/Os
          ANSEL  = 0;
          ANSELH = 0;
        
        // set PORTD inputs
          TRISDbits.TRISD0 = 1;                                // place a call input
          TRISDbits.TRISD1 = 1;                                // hang up input
          TRISDbits.TRISD2 = 1;                                // answer a call input
          TRISDbits.TRISD3 = 1;                                // continue with PIC program
        
        TRISDbits.TRISD7 = 0; // led test
        
        // set RTS pin to zero, we will use only RX i TX
         TRISCbits.TRISC3= 0;
          PORTCbits.RC3 = 0;
        
        // enable uart rx interrupt
        //PIE1bits.RCIE = 1;
          //INTCONbits.PEIE = 1;
          //INTCONbits.GIE  = 1;
        
        TRISCbits.TRISC7=1;
        TRISCbits.TRISC6=1;
        
        SPBRGH=0x00;
        SPBRG=0x19;
        RCSTAbits.SPEN=1;
        BAUDCONbits.BRG16=1;
        TXSTAbits.BRGH=1;
        TXSTAbits.SYNC=0;
        TXSTAbits.TXEN=1;
        
        LATDbits.LATD7 = 0;
        
        while(!PORTD){
        LATDbits.LATD7 = 1;
        Delay1KTCYx(1000);
        };
        
        LATDbits.LATD7 = 0; // led stage test
        
        Delay1KTCYx(5000);                                
        // wait for the GSM module to initialize it self
        
        
        // negotiate baud rate
          while(1) {
        LATDbits.LATD7 = 1; // LED stage test
         WriteUSART(0x0D); // send cr
        send_atc(atc0);                              // send "AT"
        /*I also tried putrsUSART ((const far rom char *)"AT+IPR=9600\r"); instead of send_atc(atc0)*/
         string until gsm sets up its baud rade
             Delay1KTCYx(1000);                             // and gets it correctly
            if (get_response() == GSM_OK)                // if gsm says "OK" on our baud rate we got it
              break;
          }
        
        
        
        LATDbits.LATD7 = 0; //led stage test
        
        
        
        // disable command echo
          send_atc(atc1);
          Delay1KTCYx(100); 
         WriteUSART(0x0D);
        
        
        send_atc(atc3);
          Delay1KTCYx(100); 
         WriteUSART(0x0D);
        
        // change audio path (enables handsfree external mic/ear audio path)
          send_atc(atc2);
        
         WriteUSART(0x0D);
        
        
        
              }
        Thanks a lot for the help

        Comment

        • Banfa
          Recognized Expert Expert
          • Feb 2006
          • 9067

          #5
          You need to sort out sending the AT and auto-bauding before anything else. The

          AT
          OK

          is the biggest hurdle to get over.

          Checking the LED for network status is a bad way to tell, there are AT commands you can send to get the current SIM state

          I trust you have downloaded Telits "AT Commands Reference Guide" (doc number 80000ST10025a Rev. 2 - 16/03/07, there might be a newer revision by now).

          See AT+CREG section 3.5.4.3.3 on page 77 and AT+CPIN is good for checkjing if the SIM requres a PIN.

          Are you trying to do voice call control?

          In the code we used went something like this

          Code:
          for 5 times
             Send "AT/r"
             Wait for up to 1 second for a reply
             Is the reply OK? 
             If Yes break loop
          endfor
          You are only waiting Delay1KTCYx(100 ); or 1000000 clock ticks. On a multi MHz processor that is a fraction of a second. Comms is slow, particularly setting it up.

          If you are having trouble then you should output everything you are receiving and everything you are sending to some debug device (I typically use a second UART if there is one to transmit data to a PC).

          At the very least store everything in a buffer so you can halt the debugger and look at what has been received.

          Comment

          • LyTseu
            New Member
            • Aug 2010
            • 14

            #6
            Hi,
            Got it I will implement the CREG commands to the code.
            This might seem like a stupid question, but in the manual on their example they always have an example of the run of commands.

            How do I get a display of the run?

            Thanks =)

            Comment

            • LyTseu
              New Member
              • Aug 2010
              • 14

              #7
              Hi Banfa!

              My loop is still stuck I changed my loop to
              Code:
              while(1)
              {
              char tmp;
              WriteUSART(0x0D); // send CR
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              WriteUSART(0x0D); // send CR
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              putrsUSART ((const far rom char *)"AT\r"); // sim
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              tmp = ReadUSART();
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              Delay10KTCYx(100);
              if (ReadUSART())
              	break;
              }
              I doesnt work yet... As for debuging Im using the output window UART I/O I can see my commands being sent out but no answer.

              Can you please take a look at my diagram I suspect it might be a hardware issue?
              Attached Files

              Comment

              • Banfa
                Recognized Expert Expert
                • Feb 2006
                • 9067

                #8
                Sorry I've been busy for a couple of days.

                The manuals examples are almost certainly created either in theory (i.e. written by hand) or by connecting the Telit to a PC and using a terminal program to send commands and receive answers (like Hyperterminal on Windows or better still an other terminal program, I like TeraTerm). The terminal Window output can be copied.

                Can you debug the program, try setting a breakpoint in you interrupt routine. Break points in interrupt routines often (always?) break the program entirely and stop it continuing but can provide instantaneous information on what is going on. For instance are you getting any interrupts at all.

                The diagram you have posted does not have enough resolution for me to read it. Make it bigger please.

                Comment

                • LyTseu
                  New Member
                  • Aug 2010
                  • 14

                  #9
                  Hey Banfa!
                  Please don't apologize I feel very thankful that you are helping me.
                  I will try the hyperterminal, I've never done it before.

                  As far as breakpoint, I don't know how to use it yet in MPLAB. I know double-clicking will place a breakpoint, but how do I watch (follow) where my program is like you were telling me?

                  Thank you

                  Comment

                  • Banfa
                    Recognized Expert Expert
                    • Feb 2006
                    • 9067

                    #10
                    Once you have set the break point you run the program in debugger. The program should stop when execution reaches the place where you set the break point.

                    Unfortunately it is too long since I used MPLAB for me to remember which menu item you need to select but looker for "Start Debugging" or "Run in Debugger" or something like that.

                    Comment

                    • LyTseu
                      New Member
                      • Aug 2010
                      • 14

                      #11
                      Great! It works,
                      I added more delays and it found the network and I was able to make a call.
                      One problem I have right now though is I tried to send a SMS
                      and when I put back my sim card to my phone I can not send text anymore but only receive...

                      Did I do something wrong with the setting?

                      Delay10KTCYx(50 );
                      putrsUSART ((const far rom char *)"AT+CMGF=1\r" ); // txt msg
                      Delay10KTCYx(50 );
                      putrsUSART ((const far rom char *)"AT+CSCA=1916 8214521,129"); // txt msg
                      Delay10KTCYx(10 0);

                      Comment

                      Working...