PIC 16F628A GSM Demo.

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

blogroll

social