Search by Tags

How to use GSM Modem

 
Applicable for

Article updated at 28 Oct 2017
Compare with Revision

A GSM modem is a specialized type of modem which accepts a SIM card, and operates over a subscription to a mobile operator, just like a mobile phone.

This tutorial will explain how to interface a GSM modem with Toradex modules. In this tutorial, Telit GL868 GSM modem has been interfaced with Iris Board V1.1A.

  1. GSM Modem works on Serial communication.
  2. Iris Board V1.1A has 3 com port available on Connector X13 and X14 for serial communication, we can use any one, as for GSM Modem we need RXD & TXD Only.
  3. Connect X14 connector to UART Port of GSM Modem with Serial cable.


Header file for GSM Modem

Follow this tutorial up to step 9 to create a new VC++ project. Right click on Header Files > Add > New Item...


Click on Header File (.h) and name it gsmmodem.h


Copy this code in gsmmodem.h

/// @file       gsmmodem.h
/// @copyright  Copyright (c) 2014 Toradex AG
/// @date       $ 2014-03-26 $
/// @brief      Contains function declarations to be used to access GSM Modem
 
#ifndef _GSMMODEM_H_
#define _GSMMODEM_H_
 
#include <windows.h>
 
#define DELIVERY_REPORT_SMS_SENT        0
#define DELIVERY_REPORT_SMS_DELIVERED   1
#define IMEI_NUMBER_MAX_LENGTH          15
#define DATE_MAX_LENGTH                 8
#define TIME_MAX_LENGTH                 11
 
 //******************************************************************************
/// Configure CoM port to communicate with GSM modem
/// @param[out]    port           CoM port for GSM modem 
/// @param[in]     baudRate       Baudrate for communication
/// @retval        TRUE           Success
///                FALSE          Failure
BOOL GsmOpen(HANDLE *port, DWORD baudRate);
 
//******************************************************************************
/// Send SMS to a phone number
/// @param[in]     port              GSM Port Handle returned by call to GsmOpen().
/// @param[in]     phoneNumber       Phone number to which SMS is send
/// @param[in]     message           Message to send in SMS
/// @param[out]    deliveryReport    Message delivery report
/// @retval        TRUE              Success
///                FALSE             See GetLastError()
BOOL GsmSendSms(HANDLE port, char *phoneNumber, char *message, DWORD *deliveryReport);
 
//******************************************************************************
/// Read received SMS
/// @param[in]     port                 GSM Port Handle returned by call to GsmOpen().
/// @param[in]     messageIndex         Index of received SMS
/// @param[out]    senderPhoneNumber    SMS sender phone number
/// @param[out]    dateTimeStamp        Date and time of received SMS
/// @param[out]    message              Message received in SMS
/// @param[in]     messageSize          Message size
/// @retval        TRUE                 Success
///                FALSE                Failure
BOOL GsmRecieveSms(HANDLE port, char *messageIndex, char *senderPhoneNumber, char *dateTimeStamp, char *message, DWORD messageSize);
 
//******************************************************************************
/// Delete SMS 
/// @param[in]     port           GSM Port Handle returned by call to GsmOpen().
/// @param[in]     messageIndex   Index of SMS to be deleted
/// @retval        TRUE           Success
///                FALSE          Failure
BOOL GsmDeleteSms(HANDLE port, char *messageIndex);
 
//******************************************************************************
/// Give miss call on a phone number
/// @param[in]     port              GSM Port Handle returned by call to GsmOpen().
/// @param[in]     phoneNumber       Phone number
/// @param[out]    deliveryReport    delivery report
/// @retval        TRUE              Success
///                FALSE             Failure
BOOL GsmGiveMissCall(HANDLE port, char *phoneNumber, DWORD *deliveryReport);
 
//******************************************************************************
/// Close CoM port used for GSM modem
/// @param[in]     port           GSM Port Handle returned by call to GsmOpen().
/// @retval        TRUE           Success
///                FALSE          Failure
BOOL GsmClose(HANDLE *port);
 
//******************************************************************************
/// Send AT command to GSM modem
/// @param[in]    port             GSM Port Handle returned by call to GsmOpen().
/// @param[in]    commandString    AT command to be send
/// @param[in]    terminate        End of message
/// @param[in]    responseString   Expected AT command response
/// @retval       TRUE             Success
///               FALSE            Failure
BOOL SendATCommand(HANDLE port, char *commandString, BOOL terminate, char *responseString);
 
//******************************************************************************
/// Gets IMEI number of the modem
/// @param[in]    port           GSM Port Handle returned by call to GsmOpen().
/// @param[out]   imeiNumber     IMEI number of the device
/// @retval       TRUE           Success
///               FALSE          Failure
BOOL GsmGetIMEINumber(HANDLE port, char *imeiNumber);
 
//******************************************************************************
/// Gets information about modem manufacturer
/// @param[in]    port           GSM Port Handle returned by call to GsmOpen().
/// @param[out]   manufacturer   Manufacturer information
/// @param[out]   modelNumber    Model number of modem
/// @retval       TRUE           Success
///               FALSE          Failure
BOOL GsmGetManufacturerInfo(HANDLE port, char *manufacturer, char *modelNumber);
 
//******************************************************************************
/// Gets SIM pin status
/// @param[in]    port           GSM Port Handle returned by call to GsmOpen().
/// @param[out]   status         SIM status
/// @retval                      Returns the status of SIM
BOOL GsmGetSIMStaus(HANDLE port, DWORD *status);
 
//******************************************************************************
/// Gets information of SIM registration and network provider 
/// @param[in]    port                GSM Port Handle returned by call to GsmOpen().
/// @param[out]   status              Status of SIM registration 
/// @param[out]   networkProvider     Network provider information
/// @retval       TRUE                Success
/// @retval       FALSE               Failure
BOOL GsmGetNetworkRegistrationSIMStaus(HANDLE port, DWORD *status, char *networkProvider);
 
//******************************************************************************
/// Gets signal strength information
/// @param[in]    port              GSM Port Handle returned by call to GsmOpen().
/// @param[out]   signalStrength    signal strength information
/// @retval       TRUE              Success
///               FALSE             Failure
BOOL GsmGetSignalStength(HANDLE port, char *signalStrength);
 
//******************************************************************************
/// Gets Network Date and Time Information
/// @param[in]   port           GSM Port Handle returned by call to GsmOpen().
/// @param[out]  date           Pointer to date string
/// @param[out]  time           Pointer to time string
/// @retval      TRUE           Success
///              FALSE          Failure
BOOL GsmGetNetworkDateTimeInformation(HANDLE port, char *date, char *time);
 
#endif // _GSMMODEM_H_

Source file for GSM Modem

Right click on Source Files > Add > New Item...


Click on C++ file (.cpp) and name it gsmmodem.c


Copy and paste this code in gsmmodem.c

/// @file       gsmmodem.c
/// @copyright  Copyright (c) 2014 Toradex AG
/// @date       $ 2014-03-26 $
/// @brief      Contains function to be used to access GSM Modem
 
#include <windows.h>
#include "gsmmodem.h"
 
//******************************************************************************
BOOL GsmOpen(HANDLE *port, DWORD baudRate)
{
    DCB PortDCB;                                ///< CoM port configuration structure
    BOOL returnValue = 0;
    COMMTIMEOUTS comTimeOut;
    /// Open Interface to reader
    *port = CreateFile(TEXT("CoM2:"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL);
    if (*port == INVALID_HANDLE_VALUE)
    {
        printf("Error Opening CoM Port\n");
        Sleep(1000);
        *port = NULL;
        return FALSE;
    }
    /// CoM Port Configuration
 
    /// Initialize the DCBlength member. 
    PortDCB.DCBlength = sizeof(DCB); 
    /// Get the default port setting information.
    GetCommState(*port, &PortDCB);
    /// Change the DCB structure settings.
    PortDCB.BaudRate = baudRate;                 ///< Current baudrate
    PortDCB.fBinary = TRUE;                      ///< Binary mode; no EOF check 
    PortDCB.fParity = FALSE;                     ///< Disable parity checking 
    PortDCB.fOutxCtsFlow = FALSE;                ///< No CTS output flow control 
    PortDCB.fOutxDsrFlow = FALSE;                ///< No DSR output flow control 
    PortDCB.fDtrControl = DTR_CONTROL_DISABLE;   ///< Disable DTR flow control type 
    PortDCB.fDsrSensitivity = FALSE;             ///< DSR sensitivity 
    PortDCB.fTXContinueOnXoff = TRUE;            ///< XOFF continues Tx 
    PortDCB.fOutX = FALSE;                       ///< No XON/XOFF out flow control 
    PortDCB.fInX = FALSE;                        ///< No XON/XOFF in flow control 
    PortDCB.fErrorChar = FALSE;                  ///< Disable error replacement 
    PortDCB.fNull = FALSE;                       ///< Disable null stripping 
    PortDCB.fRtsControl = RTS_CONTROL_ENABLE;    ///< Disable RTS flow control 
    PortDCB.fAbortOnError = FALSE;               ///< Do not abort reads/writes on error
    PortDCB.ByteSize = 8;                        ///< Number of bits/byte, 4-8 
    PortDCB.Parity = NOPARITY;                   ///< 0 - 4 = no, odd, even, mark, space 
    PortDCB.StopBits = ONESTOPBIT;               ///< 0, 1, 2 = 1, 1.5, 2 
 
    /// Configure the port according to the specifications of the DCB structure.
    if (!SetCommState (*port, &PortDCB))
    {
        /// Could not configure the serial port.
        printf("Error Configuring CoM2 Port\n");
        return FALSE;
    }
 
    /// Get Communication time out values
    returnValue = GetCommTimeouts(*port, &comTimeOut);
    comTimeOut.ReadIntervalTimeout = 10;
    comTimeOut.ReadTotalTimeoutMultiplier = 1;
    comTimeOut.ReadTotalTimeoutConstant = 1;
    /// Set Communication time out values
    returnValue = SetCommTimeouts(*port, &comTimeOut);
    return TRUE;
}
 
//******************************************************************************
BOOL GsmSendSms(HANDLE port, char *phoneNumber, char *message, DWORD *deliveryReport)
{
    DWORD bytesTransmitted = 0;
    DWORD bytesRead = 0;
    BYTE readBuffer[1024] = {0};
    BOOL returnValue = 0;
    BYTE byteTransmit[4] = {0};
 
    /// Input parameter check
    if (port == NULL || phoneNumber == NULL || strlen(phoneNumber) < 13 || message == NULL || strlen(message) > 160)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    returnValue = SendATCommand(port, "AT+CMGS=\"", FALSE, 0);
    returnValue = SendATCommand(port, phoneNumber, FALSE, 0);
    returnValue = SendATCommand(port, "\"", TRUE, ">");
    WriteFile(port, message, strlen(message), &bytesTransmitted, NULL);
    byteTransmit[0] = 26;                                             ///< SMS Termination character
    WriteFile(port, byteTransmit, 1, &bytesTransmitted, NULL);
 
    /// Wait for +CMGS:
    Sleep(1000);
    returnValue = ReadFile(port, readBuffer, 100, &bytesRead, NULL);  ///< False = Failure
 
    /// Set deliveryReport
    if (deliveryReport != NULL)
    {
 
    }
    return TRUE;
}
 
//******************************************************************************
BOOL SendATCommand(HANDLE port, char *commandString, BOOL terminate, char *responseString)
{
    DWORD timeOut = 50;            ///< 2.5 Seconds + ReadFile Delay
    DWORD noOfBytesRead = 0;  
    DWORD bytesTransmitted = 0;
    BYTE readBuffer[100] = {0};
 
    WriteFile(port, commandString, strlen(commandString), &bytesTransmitted, NULL);   ///< Send command to GSM modem 
    if (terminate == 1) WriteFile(port, "\r\n", 2, &bytesTransmitted, NULL);
 
    if (responseString == NULL)
    {
        return TRUE;
    }
    while (timeOut)                ///< If response to command is expected
    {
        // memset(readBuffer, 0, 100);
        ReadFile(port, readBuffer, 100, &noOfBytesRead, NULL);
        if (strstr(readBuffer, responseString))
        {
            return TRUE;
        }
        else
        {
            Sleep(50);
        }
        timeOut--;
    }
    return FALSE;
}
 
//******************************************************************************
BOOL GsmRecieveSms(HANDLE port, char *messageIndex, char *senderPhoneNumber, char *dateTimeStamp, char *message, DWORD messageSize)
{
    BOOL returnValue = 0;
    char readBuffer[256] = {0}; 
    DWORD bytesRead = 0;
 
    returnValue = SendATCommand(port, "AT+CMGR=", FALSE, 0);
    returnValue = SendATCommand(port, messageIndex, TRUE, 0);
 
    ReadFile(port, readBuffer, 256, &bytesRead, NULL); 
    Sleep(1000);
    ReadFile(port, readBuffer, 256, &bytesRead, NULL);
    if (!strstr(readBuffer, "+91"))
    {
        return FALSE;
    }
    strncat_s(senderPhoneNumber, 16, strstr(readBuffer, "+91"), 13);    ///< Phone number string length = 13, +919876543210
    strncat_s(dateTimeStamp, 21, strstr(readBuffer, "/") - 2, 20);      ///< Date time string length = 20, "12/12/24,18:08:44+22" "YY/MM/DD,HH:MM+SS"
    strncat_s(message, 160, strstr(readBuffer, "/") + 18, 160);
    message[strlen(message) - 1] = 0;
    message[strlen(message) - 2] = 0;
    message[strlen(message) - 3] = 0;
    /// Sort out time, date , message, sender's phone number
    return TRUE;
}
 
//******************************************************************************
BOOL GsmDeleteSms(HANDLE port, char *messageIndex)
{
    BOOL returnValue = 0;
 
    returnValue = SendATCommand(port, "AT+CMGD=", FALSE, 0);
    if (returnValue == TRUE)
    {
        returnValue = SendATCommand(port, messageIndex, TRUE, "OK");
        if (returnValue)
        {
            return TRUE;   ///< Command Success
        }
        else 
        {
            return FALSE;  ///< Command Failure
        }
    }
    else
    {
        return FALSE;      ///< Command Failure
    }
 
}
 
//******************************************************************************
BOOL GsmGiveMissCall(HANDLE port, char *phoneNumber, DWORD *deliveryReport)
{
    BOOL returnValue = 0;
 
    returnValue = SendATCommand(port, "ATD", FALSE, 0);
    returnValue = SendATCommand(port, phoneNumber, FALSE, 0);
    returnValue = SendATCommand(port, ";", TRUE, "OK");
    if (returnValue)
    {
        Sleep(7500);
        returnValue = SendATCommand(port, "ATH", TRUE, "OK");
    }
    else
    {
        return FALSE;
    }
    return TRUE;
 
}
 
//******************************************************************************
BOOL GsmClose(HANDLE *port)
{
    if (*port == NULL)
    {
        return FALSE;
    }
 
    CloseHandle(*port);
    *port = NULL;
    return TRUE;
}
 
//******************************************************************************
BOOL GsmGetIMEINumber(HANDLE port, char *imeiNumber)
{
    DWORD noOfBytesTransmitted = 0;
    DWORD noOfBytesRead = 0;
    char readBuffer[32] = {0};
 
    WriteFile(port, "AT+CGSN\r\n", 8, &noOfBytesTransmitted, NULL);
    Sleep(250);
    ReadFile(port, readBuffer, 32, &noOfBytesRead, NULL);   ///< Receive IMEI number in response
    if (noOfBytesRead >= IMEI_NUMBER_MAX_LENGTH + 2)
    {
        strncpy_s(imeiNumber, IMEI_NUMBER_MAX_LENGTH + 1, readBuffer + 2, IMEI_NUMBER_MAX_LENGTH); 
        return TRUE;
    }
    else
    {
        return FALSE; 
    }
}
 
//******************************************************************************
BOOL GsmGetManufacturerInfo(HANDLE port, char *manufacturer, char *modelNumber)
{
    DWORD noOfBytesTransmitted = 0;
    DWORD noOfBytesRead = 0;
    char readBuffer[100] = {0};
 
    while (TRUE)
    {
        ReadFile(port, readBuffer, 100, &noOfBytesRead, NULL);
        memset(readBuffer, 0, 100);
        if (noOfBytesRead == 0)
        {
            break;
        }
    }
 
    WriteFile(port, "AT+CGMI\r\n", 9, &noOfBytesTransmitted, NULL);
    Sleep(250);
    ReadFile(port, readBuffer, 100, &noOfBytesRead, NULL);    ///< Get manufacturer information in response
    if (noOfBytesRead == 0)
    {
        return FALSE;
    }
    else
    {
        strncat_s(manufacturer, 100, readBuffer + 2, strlen(readBuffer)- 10);
    }
 
    WriteFile(port, "AT+CGMM\r\n", 9, &noOfBytesTransmitted, NULL);
    Sleep(250);
    ReadFile(port, readBuffer, 100, &noOfBytesRead, NULL);   ///< Get model identification in response
    if (noOfBytesRead == 0)
    {
        return FALSE;
    }
    else
    {
        strncat_s(modelNumber, 100, readBuffer + 2, strlen(readBuffer)- 10); 
        return TRUE;
    }
}
 
 //******************************************************************************
BOOL GsmGetSIMStaus(HANDLE port, DWORD *status)
{
    if (!SendATCommand(port, "AT+CPIN?", TRUE, "+CPIN"))      ///< Check if SIM is inserted and if PIN required
    {
        return FALSE;
    }
    return TRUE;
}
 
//******************************************************************************
BOOL GsmGetNetworkRegistrationSIMStaus(HANDLE port, DWORD *status, char *networkProvider)
{
    DWORD noOfBytesTransmitted = 0;
    DWORD noOfBytesRead = 0;
    DWORD length = 0;
    DWORD timeout = 100;
    char readBuffer[100] = {0};
    char *start = NULL;
    char *end = NULL;
 
    *status = SendATCommand(port, "AT+CREG?", TRUE, "+CREG: 0,1");   ///< Check registration status
 
    if (*status == 1)
    {
        WriteFile(port, "AT+COPS?\r\n", 10, &noOfBytesTransmitted, NULL);
        Sleep(250);
        ReadFile(port, readBuffer, 100, &noOfBytesRead, NULL);       ///< Get network information 
        if (noOfBytesRead == 0)
        {
            return FALSE;
        }
        else
        {
            start = strstr(readBuffer, "\"");
            end = strstr(start + 1, "\"");
            if (!start || !end)
            {
                return FALSE;
            }
            length = end - start;
            strncat_s(networkProvider, 50, start, length);
            return TRUE;
        }
   }
   else
   {
       return FALSE;
   }
}
 
//******************************************************************************
BOOL GsmGetSignalStength(HANDLE port, char *signalStrength)
{
    DWORD noOfBytesTransmitted = 0;
    DWORD noOfBytesRead = 0;
    DWORD length = 0;
    char readBuffer[100] = {0};
    char *start = NULL;
    char *end = NULL;
 
    WriteFile(port, "AT+CSQ\r\n", 8, &noOfBytesTransmitted, NULL);
    Sleep(250);
    ReadFile(port, readBuffer, 100, &noOfBytesRead, NULL);   ///< Get network signal strength
    if (noOfBytesRead == 0)
    {
        return FALSE;
    }
    else
    {
        start = strstr(readBuffer, ": ");
        end = strstr(start + 1, ",");
        if (!start || !end)
        {
            return FALSE;
        }
        length = end - (start + 2);
        strncat_s(signalStrength, 4, (start + 2), length);
        return TRUE;
    }
}
 
//******************************************************************************
BOOL GsmGetNetworkDateTimeInformation(HANDLE port, char *date, char *time)
{
    DWORD noOfBytesTransmitted = 0;
    DWORD noOfBytesRead = 0;
    char readBuffer[100] = {0};
    char *start = NULL;
    char *end = NULL;
    DWORD length = 0;
 
    WriteFile(port, "AT+CCLK?\r\n", 10, &noOfBytesTransmitted, NULL);
    Sleep(250);
    ReadFile(port, readBuffer, 100, &noOfBytesRead, NULL); 
    if (noOfBytesRead == 0)
    {
        return FALSE;
    }
    else
    {
        start = strstr(readBuffer, "\"");
        end = strstr(start + 1, ",");
        if (!start || !end)
        {
            return FALSE;
        }
        length = end - (start + 1);
        strncat_s(date, DATE_MAX_LENGTH + 1, (start + 1), length);
 
        start = strstr(readBuffer, ",");
        end = strstr(start + 1, "\"");
        if (!start || !end)
        {
            return FALSE;
        }
        length = end - (start + 1);
        strncat_s(time, TIME_MAX_LENGTH + 1,  (start + 1), length);
        return TRUE;
    }
}

Main function code

#include <windows.h>
#include "gsmmodem.h"
 
int wmain(void)
{
    HANDLE gsmHandle = NULL;                 ///< Handle for CoM port 
    BOOL returnValue = 0;                    ///< variable holding return values
    char phoneNumber[16] = {0};
    char messageRecieved[160] = {0};
    char dateTimeStamp[21] = {0};
    char IMEINumber[IMEI_NUMBER_MAX_LENGTH + 1] = {0};
    char manufacturerName[100] = {0};
    char modelNumber[100] = {0};
    char networkProvider[50] = {0};
    char signalStrength[4] = {0};
    char date[DATE_MAX_LENGTH + 1] = {0};
    char time[TIME_MAX_LENGTH + 1] = {0};
    DWORD SimStatus = 0;
    DWORD networkStatus = 0;
 
    /// Configure CoM port for GSM modem
    returnValue = GsmOpen(&gsmHandle, 9600);
    if (returnValue == FALSE)
    {
        printf("cannot open port \n");
        getchar();
        return FALSE;
    }
    returnValue = SendATCommand(gsmHandle, "AT", TRUE, "OK");    ///< Check communication with modem
    if (returnValue == FALSE)
    {
        printf("error \n");
        getchar();
        return FALSE;
    }
    returnValue = SendATCommand(gsmHandle, "ATE0", TRUE, "OK");  ///< Disable echo
    if (returnValue == FALSE)
    {
        printf("cannot disable echo \n");
        getchar();
        return FALSE;
    }
 
    returnValue = GsmGetIMEINumber(gsmHandle, IMEINumber);
    if (returnValue == FALSE)
    {
        printf("error in obtaining IMEI number \n");
        getchar();
        return FALSE;
    }
    printf(" IMEI = %s\n", IMEINumber);
    returnValue = GsmGetManufacturerInfo(gsmHandle, manufacturerName, modelNumber);
    if (returnValue == FALSE)
    {
        printf("error in obtaining manufacturer information \n");
        getchar();
        return FALSE;
    }
    printf(" Manufacturer Name = %s, Model Number = %s\n", manufacturerName, modelNumber);
    returnValue = GsmGetSIMStaus(gsmHandle, &SimStatus); 
    if (returnValue == FALSE)
    {
        printf("error to obtain SIM status\n");
        getchar();
        return FALSE;
    }
    returnValue = GsmGetSignalStength(gsmHandle, signalStrength);
    if (returnValue == FALSE)
    {
        getchar();
        return FALSE;
    }
    printf(" Signal Strength = %s \n", signalStrength);
    returnValue = GsmGetNetworkRegistrationSIMStaus(gsmHandle, &networkStatus, networkProvider); 
    if (returnValue == FALSE)
    {
        getchar();
        return FALSE;
    }
    printf(" Network Status = %d, Network Provider = %s \n", networkStatus, networkProvider);
 
    returnValue = GsmGetNetworkDateTimeInformation(gsmHandle, date, time);
    if (returnValue == FALSE)
    {
        getchar();
        return FALSE;
    }
    printf(" date = %s, time = %s\n", date, time);
    returnValue = SendATCommand(gsmHandle, "AT+CMGF=1", TRUE, "OK");  ///< Set Text Mode
    if (returnValue == FALSE)
    {
        printf("cannot set to text mode \n");
        getchar();
        return FALSE;
    }
    /// Example to send SMS
    returnValue = GsmSendSms(gsmHandle, "+918792792826", "Toradex GSM Modem Test 4", 0);
    Sleep(2000);
 
    /// Example to receive SMS
    //returnValue = GsmRecieveSms(gsmHandle, "1", phoneNumber, dateTimeStamp, messageRecieved, 160); 
 
    /// Example to delete SMS
    //returnValue = GsmDeleteSms(gsmHandle, "1");
 
    /// Example to give a miss call
    //returnValue = GsmGiveMissCall(gsmHandle, "+917204200289", 0);
    printf(" press enter to exit\n");
    getchar();
    GsmClose(&gsmHandle);         ///< Free resources allocated 
    return TRUE;
}

Output


Download project

You can download demo source code from here.