PIC and SIM900A

This program demonstrates how to use the SIM900A to connect and disconnect to the cell network with GPRS. The uart code are in libraries.

Main program

// INCLUDES
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <string.h>
#include "uart_init_header.h"

// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON       // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = ON       // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = ON         // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

// DEFINITIONS
#define _XTAL_FREQ 4000000

// GLOBAL VARIABLES
volatile char gsm_buffer[40];
volatile int gsm_buffer_index;

// FUNCTION PROTOTYPE
void gsm_power_on(void);
void gsm_power_off(void);
void interrupt ISR(void);
void gsm_init(void);
void gsm_response();
void gsm_response_display();


// FUNCTIONS
void interrupt ISR(void) {
    if (RCIF) {
        gsm_buffer[gsm_buffer_index] = RCREG;
        gsm_buffer_index++;
        if(RCSTAbits.OERR) {
            CREN = 1;
            NOP();
            CREN = 1;
        }
    }
}

void gsm_response() {
    unsigned int time_out = 0;
    int crlf_found = 0;
    char crlf_buffer[2];
    int response_length = 0;
    while (1) {
        if (time_out >= 4000)
            return;
        response_length = strlen(gsm_buffer);
        if (response_length) {
            __delay_ms(1);
            time_out++;
            if(response_length == strlen(gsm_buffer)) {
                for (int i=0;i<response_length;i++) {
                    memmove(crlf_buffer[1], crlf_buffer + 1, 1);
                    crlf_buffer[1] = gsm_buffer[i];
                    if(strncmp(crlf_buffer, "\r\n", 2)) {
                        if (crlf_found++==2) {
                            //uart_send_str("Here we are\r\n");
                            gsm_response_display();
                            return;
                        }
                    }
                }
                crlf_found = 0;
            }
        }
        __delay_ms(1);
        time_out++;
    }
}

void gsm_response_display() {
    gsm_buffer_index = 0;
    while (1) {
        if (gsm_buffer[gsm_buffer_index] == 0x0d || gsm_buffer[gsm_buffer_index]==0x0d) {
            gsm_buffer_index++;
        }
        else 
            break;
    }
    while (gsm_buffer[gsm_buffer_index] != 0x0d) {
        uart_tx(gsm_buffer[gsm_buffer_index]);
        gsm_buffer_index++;
    }
    gsm_buffer_index = 0;
    memset(gsm_buffer, 0, strlen(gsm_buffer));
    uart_send_str("\r\n");
}

void gsm_init(void) {
    while (1) {
    uart_send_str("ATE0\r\n");      // Get attention and turn off echo
    __delay_ms(500);                // Wait half a second for it to react
    if (strstr(gsm_buffer, "OK")) {
        gsm_response();
        memset(gsm_buffer,0,40);
        break;
    } else {
        __delay_ms(50);
        uart_send_str("No contact with GSM module!\r\n");
    }    
}
    __delay_ms(2000);
    uart_send_str("AT+CMGF=1\r\n");     // Select message format as text.
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+GMI\r\n");        // Get manufacture name
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+GMM\r\n");        // Get modelnumber
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+GSN\r\n");        // Get IMEI number
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+COPS?\r\n");      // Get the service network
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+CGATT=1\r\n");    // Attach to GPRS service
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+SAPBR=3,1,\"Contype\", \"GPRS\"\r\n"); // Connect
    gsm_response();
    __delay_ms(2000);    
    uart_send_str("AT+SAPBR=1,1\r\n");  
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+SAPBR=2,1\r\n");      // Get bearer info
    gsm_response();
    __delay_ms(2000);    
    uart_send_str("AT+HTTPINIT\r\n");       // Initiate the HTTP service
    gsm_response();
    __delay_ms(2000);
    uart_send_str("AT+HTTPPARA=\"CID\",1\r\n"); // Set the HTTP session
    gsm_response();
    __delay_ms(2000);       
}

// Functio to close all connections
void gsm_close(void) {
    uart_send_str("AT+HTTPTERM\r\n");   // Close the HTTP connection
    gsm_response();
    __delay_ms(2000);    
    uart_send_str("AT+CGATT=0\r\n");   // Detach the GPRS connection
    gsm_response();
    __delay_ms(2000);    
}

// MAIN PROGRAM
void main() {

    CMCON = 0x07;

    TRISA = 0b00000000;     // All output
    PORTB = 0b00000000;     // All low

    TRISB = 0b00000110;     // RB1 & RB2 set as input ref datasheet
    PORTB = 0b00000000;     // All low  

    INTCONbits.GIE = 1;
    INTCONbits.PEIE = 1;

uart_init();

gsm_init();

gsm_close();

while (1) {
    // Do nothing forever
}
}

Uart header file

#ifndef UART_INIT_HEADER_H
#define UART_INIT_HEADER_H

#ifdef  __cplusplus
extern "C" {
#endif

#include <xc.h>
void uart_init();
void uart_tx(char out);
char uart_rx();
void uart_send_str(const char *);

#ifdef  __cplusplus
}
#endif

#endif  /* UART_INIT_HEADER_H */

Uart source file

#include "uart_init_header.h"

// Function to initialize the uart port
void uart_init() {
    TXSTAbits.BRGH = 1; // high baud selection bit, 1=high, 0=low
    TXSTAbits.SYNC = 0; // USART mode selection bit, 1=sync mode, 0=async mode
    TXSTAbits.TX9 = 0;  // 9-bit selection bit, 1=9-bit transmission, 0=8-bit trans
    RCSTAbits.CREN = 1; // continous receive enable bit, 1=Enable continous receive.
    /* 4Mhz -> 9600
     * 4000000 / 16 = 250000
     * 250000 / 9600 = 26.0416
     * 26.0416 - 1 = 25
     */
    SPBRG = 25; // 9600-n-8-1    
    PIE1bits.RCIE = 1;  // USART Receive iterrupt enable bit, 1=enable, 0=disable
    RCSTAbits.SPEN = 1; // serial port enable bit, 1=serial port enable, 0=disable
    TXSTAbits.TXEN = 1; // transmit enable bit, 1=Transmit enable, 0=disable  
    return;
}

// Function to send one char
void uart_tx(char out) {
    while (TXIF == 0);
    TXREG = out;
}

// Function to recieve one char
char uart_rx() {
    while (RCIF == 0);
    if (RCSTAbits.OERR) {
        CREN = 0;
        NOP();
        CREN = 1;
    }
    return (RCREG);
}

// Function to send a string of single chars
void uart_send_str(const char *out) {
    while (*out!='\0') {
        uart_tx(*out);
        out++;
    }
}

The output

The TX/RX pins of the PIC 16F628A is connected to a RS232/TTL to USB converter, and a serial monitor is showing whats going on.

Output