Graduation project - Tutorial: single chip microcomputer sends short message (GMS module)

1 Introduction

Hi, everyone, this is senior Dan Cheng. Today, I'd like to introduce how to use GMS module to achieve the effect of sending SMS by single chip microcomputer. The application scenarios are very wide

**Single chip microcomputer sends short message (GMS module)**

It can be used in curriculum design or graduation design

Technical solutions, design help and problem opening guidance
print("Q 746876041") 

2 GMS module


The GSM module uses SIM900 high-precision wireless GSM/GPRS full Quad Band chip of Shanghai SIMcom company, SMT package and high-performance ARM926EJ-S core. Cost effective solutions for small devices.

The module adopts standard industrial interface, and SIM900 is equipped with voice, SMS, data and fax supporting GSM/GPRS 850/900/1800/1900MHz, with high cohesion and low power consumption.

The instantaneous current of the module can reach 2A during communication, so it is necessary to connect external power supply to the control board, generally 7.5V 2000mA DC power supply. DC 7.5V power supply or battery box can also be purchased separately.

3 technical specifications

  • Full Quad frequency 850/ 900/ 1800/ 1900 MHz
  • GPRS multi hotspot type 10 / 8
  • GPRS complies with type B base station
  • GSM 2/2 + standard
  • Type 4 (2 W @850/ 900 MHz)
  • Type 1 (1 W @ 1800/1900MHz)
  • Support SAIC (Single Antenna Interference Cancellation)
  • Control with compatible AT commands (GSM 07.07, 07.05 and SIMCOM enhanced commands)
  • 0.1mA at low power operation
  • Operating temperature - 40 ° C to +85 ° C

3.1 adaptability

Compatible with cellular AT instruction

AT instruction introduction

  • If you use any serial port to debug the terminal, you need to check "add new line" or similar. If you use the serial port window of Arduino IDE version 1.0 or above, you need to select "both NL & CR". This function is not supported by the IDE of lower version.

  • The so-called AT instruction is an instruction used by the communication module for communication, starting with the letter "AT". After sending the AT instruction, the execution result starting with "+" will be returned. If there is an ERROR, the "ERROR" message will be returned. If it is normal, the word "OK" will be sent AT the end of the message.

The following is only an example of common functions. For complex functions, please refer to SIM900_ATC documents.

Test the signal quality and send the following command through the serial port:

 AT+CSQ

You will receive the following reply message:

+CSQ: 11,0
OK

Call (the semicolon after this instruction cannot be less), you can replace 10086 in the following instruction with another number.

 ATD10086;

Answer the phone

 ATA

Send SMS

First set to text mode:
 AT+CMGF=1
 Set to send SMS using the module's default international standard alphabetic character set
 AT+CSCS?
Send target number
 AT+CMGS="10086"
The system will appear“>"Prompt, enter the SMS content directly
> YE
 The purpose of this message is to send it to 10086 to query the balance. After sending it successfully, you will receive the following prompt, and the number behind it indicates the number of the message sent.
+CMGS: 115 
OK

4 arduino + GMS sample code

//
//            SIM900 GSM/GPRS module driver
//The module uses 7.5V power supply, and the SIM card must be inserted during the test
// Author: Dan Cheng, senior student Q746876041, Bi shebang
//

#include <Wire.h>

#Define gprspwr 37 / / the power switch signal of the module. The processor outputs a high level, which will cause the module to pull down the PWRKEY to turn on and off the module. The user can turn on and off the module by pulling down the PWRKEY for at least 1 second and then releasing it.
#Define gprsnrst 2 / / when the control pin is externally reset, the processor sends a control signal to the high level, causing the module pin to reset and the low level to reset.
#Define gprsstatus 10 / / module STATUS output pin, low level: the module is powered down, high level: the module is in working STATUS. After the module power switch or module is reset, you need to wait at least 2.5 seconds to check the STATUS pin STATUS.


//Function prototype: void GprsPWRkey(void)                                       
//Parameter Description: None                                        
//Return value: None                                                               
//Description: GPRS module on-off timing
///
void GprsPWRkey(void)
{
  digitalWrite(GprsPWR,HIGH);
  delay(1500);  //Hold for at least 1 second
  digitalWrite(GprsPWR,LOW);
  delay(2500);  //After waiting for 2.5 seconds, detect the STATUS pin. STATUS low level: the module is powered off, and high level: the module is in working state
}


//Function prototype: void GprsReset(void)                                    
//Parameter Description: None                                        
//Return value: None                                                               
//Description: GPRS module reset timing
///
void GprsReset(void)
{
  digitalWrite(GprsNRST,HIGH);
  delayMicroseconds(50);  //At least 50US reset signal
  digitalWrite(GprsNRST,LOW);
  delay(2500);  //After waiting for 2.5 seconds, detect the STATUS pin. STATUS low level: the module is powered off, and high level: the module is in working state
}


//Function prototype: void GprsInit(void)                                         
//Parameter Description: None                                        
//Return value: power on state, 0: module power down, 1: module in working state                                                          
//Description: GPRS initialization
///
int GprsInit(void)
{
  int temp = 0;
  pinMode(GprsPWR,OUTPUT); //Set each control IO to output
  pinMode(GprsNRST,OUTPUT);  
  pinMode(GprsSTATUS,INPUT); 
  Serial.begin(9600);      //Communication using serial 2 and GPRS
  Serial2.begin(9600);      //Communication using serial 2 and GPRS

  GprsReset();  //Module reset
  
  return temp;
}


//Function prototype: void GprsInit(void)                                         
//Parameter Description: None                                        
//Return value: None                                                          
//Note: for GPRS module test, make a call, input atdxxxx13800138000 at the serial port debugging terminal; enter to make a call
//           Send AT+CSQ carriage return and line feed query signal strength. Various AT commands can be tested here 
///
void GprsTest(void)
{
   Serial2.print("A");  //Send a capital letter A to synchronize the baud rate of the GPRS module  
  
          //Send SMS
     Serial2.println("AT+CMGF=1");
     Serial.println("AT+CMGF=1");
     delay(1000);
     Serial2.println("AT+CMGS=\"13800138000\"");//xxx is the telephone number
     Serial.println("AT+CMGS=\"13800138000\"");//xxx is the telephone number
     delay(1000);
     Serial2.print("TEST");
     Serial.print("TEST");
     delay(1000);
     Serial2.write(26);
      Serial2.write(26);
      Serial2.println();
     delay(5000);

   // SMS to 10086 for Queky
     Serial2.println("AT+CMGS=\"10086\"");//xxx is the telephone number
     Serial.println("AT+CMGS=\"10086\"");//xxx is the telephone number
     delay(1000);
     Serial2.print("YE");
     Serial.print("YE");
     delay(1000);
     Serial2.write(26);
      Serial2.write(26);
      Serial2.println();

     while(1){
        if(Serial.available())  //Read the USB serial port data and send the data to the GPRS module
       {
         char input = Serial.read();
        Serial2.print(input); 
       }
       if( Serial2.available())  //Receive the data returned by GPRS module and display the data to USB serial port terminal
      { 
        char input2 = Serial2.read();
        Serial.print(input2);
      }
     }
}


void setup()
{
    GprsPWRkey();
    GprsInit();
    delay(2000);
    //GprsReset();
   GprsTest();
}

void loop()
{
    
}

//
//            SIM900 GSM/GPRS module driver
//The module uses 7.5V power supply, and the SIM card must be inserted during the test
// Author: Dan Cheng, senior student Q746876041, Bi shebang
//

5. Implementation effect

Combined with GPS module, send GPS data to your mobile phone

Part of the core code (using STM32 single chip microcomputer)

// Author: Dan Cheng, senior student Q746876041, Bi shebang

#include "gps_config.h"
#include "bsp_usart3.h"
#include "nmea/nmea.h"


/* DMA Receive buffer  */
uint8_t gps_rbuff[GPS_RBUFF_SIZE];

/* DMA Transmission end flag */
__IO uint8_t GPS_TransferEnd = 0, GPS_HalfTransferEnd = 0;



/**
  * @brief  GPS_Interrupt_Config Configure DMA interrupt used by GPS 
  * @param  None.
  * @retval None.
  */
static void GPS_Interrupt_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    // DMA2 Channel Interrupt ENABLE
    NVIC_InitStructure.NVIC_IRQChannel = GPS_DMA_IRQn;//RX is used for interrupt, not TX fuxx!!
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

}


/**
  * @brief  GPS_ProcessDMAIRQ GPS DMA Interrupt service function
  * @param  None.
  * @retval None.
  */
void GPS_ProcessDMAIRQ(void)
{
  
  if(DMA_GetITStatus(GPS_DMA_IT_HT) )         /* DMA Half transmission complete */
  {
    GPS_HalfTransferEnd = 1;                //Set the half transmission completion flag bit
    DMA_ClearFlag(GPS_DMA_FLAG_HT);
        
  }
  else if(DMA_GetITStatus(GPS_DMA_IT_TC))     /* DMA Transmission complete */
  {
    GPS_TransferEnd = 1;                    //Set the transmission completion flag bit
    DMA_ClearFlag(GPS_DMA_FLAG_TC);

   }
}


/**
  * @brief  GPS_DMA_Config gps dma Receive configuration
  * @param  nothing
  * @retval nothing
  */
static void GPS_DMA_Config(void) //It is a function
{
        DMA_InitTypeDef DMA_InitStructure; //Define a structure of DMA_InitTypeDef type named DMA_InitStructure
    
        /*Turn on DMA clock*/
        RCC_AHBPeriphClockCmd(GPS_DMA_CLK, ENABLE);

        /*Set DMA source: serial port data register address*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = GPS_DATA_ADDR;       //A member with a point number in the structure can be assigned directly, which is equivalent to a variable
//Enter gps.config.h from there. It can be seen that the serial communication of gps is defined as USart2, which can be modified here
        /*Memory address (pointer to variable to be transferred)*/
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)gps_rbuff;

        /*Direction: from peripherals to memory */        
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;    

        /*Transfer size dma_buffersize = sendbuffer_size*/    
        DMA_InitStructure.DMA_BufferSize = GPS_RBUFF_SIZE;

        /*Peripheral address not added*/        
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //If you want to modify, you can find the corresponding name directly

        /*Memory address self increment*/
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    

        /*Peripheral data unit*/    
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

        /*Memory data unit: 8bit*/
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;     

        /*DMA Mode: continuous cycle*/
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;     

        /*Priority: medium*/    
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  

        /*Disable memory to memory transfer    */
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

        /*Configure DMA channels*/           
        DMA_Init(GPS_DMA_CHANNEL, &DMA_InitStructure);        
    
    GPS_Interrupt_Config();
        
    DMA_ITConfig(GPS_DMA_CHANNEL,DMA_IT_HT|DMA_IT_TC,ENABLE);  //Configure an interrupt after DMA transmission is completed

        /*Enable DMA*/
        DMA_Cmd (GPS_DMA_CHANNEL,ENABLE);        
    
    /* Configure serial port to send TX request to DMA */
        USART_DMACmd(GPS_USART, USART_DMAReq_Rx, ENABLE);


}

/**
  * @brief  GPS_Config gps initialization
  * @param  nothing
  * @retval nothing
  */
void GPS_Config(void)
{
  GPS_USART_INIT();   //Initialize serial port
  GPS_DMA_Config();  //Initialize DMA mode of serial port
  
}

 

/**
  * @brief  trace Output the captured GPS statement during decoding
  * @param  str: String to output, str_size: data length
  * @retval nothing
  */
void trace(const char *str, int str_size)
{
  #Ifdef _gps_debug / / configure this macro in the gps_config.h file. Output debugging information
    uint16_t i;
    printf("\r\nTrace: ");
    for(i=0;i<str_size;i++)
      printf("%c",*(str+i));
  
    printf("\n");
  #endif
}

/**
  * @brief  error Output prompt message when decoding error
  * @param  str: String to output, str_size: data length
  * @retval nothing
  */
void error(const char *str, int str_size)
{
    #ifdef __GPS_DEBUG / / in GPS_ The config. H file configures this macro to output debugging information

    uint16_t i;
    printf("\r\nError: ");
    for(i=0;i<str_size;i++)
      printf("%c",*(str+i));
    printf("\n");
    #endif
}



/******************************************************************************************************** 
**     Function name: bit isleapyear (uint8_t iyear) 
**    Function Description: judge leap years (only for years after 2000) 
**    Entry parameter: iYear two digit year 
**    Exit parameter: uint8_ T 1: leap year 0: normal year 
********************************************************************************************************/ 
static uint8_t IsLeapYear(uint8_t iYear) 
{ 
    uint16_t    Year; 
    Year    =    2000+iYear; 
    if((Year&3)==0) 
    { 
        return ((Year%400==0) || (Year%100!=0)); 
    } 
     return 0; 
} 

/******************************************************************************************************** 
**     Function name: void gmtconvert (uint8_t * DT, uint8_t GMT, uint8_t area) 
**    Function Description: Greenwich time converts the time of time zones in the world 
**    Entry parameter: * DT: array format representing date and time YY,MM,DD,HH,MM,SS 
**                        GMT:    Number of time zones 
**                        AREA:    1(+)East W0(-) West 
********************************************************************************************************/ 
void    GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT,uint8_t AREA) 
{ 
    uint32_t    YY,MM,DD,hh,mm,ss;        //Temporary variable of month, day, hour, minute and second 
     
    if(GMT==0)    return;                //If you are in the 0 time zone, return directly 
    if(GMT>12)    return;                //The maximum time zone is 12. If it exceeds, it will be returned         

    YY    =    SourceTime->year;                //Acquisition year 
    MM    =    SourceTime->mon;                 //Get month 
    DD    =    SourceTime->day;                 //Acquisition day 
    hh    =    SourceTime->hour;                //When getting 
    mm    =    SourceTime->min;                 //Get points 
    ss    =    SourceTime->sec;                 //Get seconds 

    if(AREA)                        //East (+) time zone processing 
    { 
        if(hh+GMT<24)    hh    +=    GMT;//If it is on the same day as Greenwich mean time, just add hours 
        else                        //If it is already 1 day later than GMT, date processing will be performed 
        { 
            hh    =    hh+GMT-24;        //Get the time first 
            if(MM==1 || MM==3 || MM==5 || MM==7 || MM==8 || MM==10)    //Large month (handled separately in December) 
            { 
                if(DD<31)    DD++; 
                else 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
            } 
            else if(MM==4 || MM==6 || MM==9 || MM==11)                //Small month (handled separately in February) 
            { 
                if(DD<30)    DD++; 
                else 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
            } 
            else if(MM==2)    //Processing February 
            { 
                if((DD==29) || (DD==28 && IsLeapYear(YY)==0))        //It was a leap year and it was February 29 or it was not a leap year and it was February 28 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
                else    DD++; 
            } 
            else if(MM==12)    //Processing December 
            { 
                if(DD<31)    DD++; 
                else        //The last day of the new year 
                {               
                    DD    =    1; 
                    MM    =    1; 
                    YY    ++; 
                } 
            } 
        } 
    } 
    else 
    {     
        if(hh>=GMT)    hh    -=    GMT;    //If it is on the same day as Greenwich mean time, only hours can be reduced 
        else                        //If it is already 1 day earlier than GMT, date processing will be performed 
        { 
            hh    =    hh+24-GMT;        //Get the time first 
            if(MM==2 || MM==4 || MM==6 || MM==8 || MM==9 || MM==11)    //Last month is a big month (January is handled separately) 
            { 
                if(DD>1)    DD--; 
                else 
                { 
                    DD    =    31; 
                    MM    --; 
                } 
            } 
            else if(MM==5 || MM==7 || MM==10 || MM==12)                //Last month is a small month (processed separately in February) 
            { 
                if(DD>1)    DD--; 
                else 
                { 
                    DD    =    30; 
                    MM    --; 
                } 
            } 
            else if(MM==3)    //Last month was February 
            { 
                if((DD==1) && IsLeapYear(YY)==0)                    //Not a leap year 
                { 
                    DD    =    28; 
                    MM    --; 
                } 
                else    DD--; 
            } 
            else if(MM==1)    //Processing January 
            { 
                if(DD>1)    DD--; 
                else        //The first day of the new year 
                {               
                    DD    =    31; 
                    MM    =    12; 
                    YY    --; 
                } 
            } 
        } 
    }         

    ConvertTime->year   =    YY;                //Renewal year 
    ConvertTime->mon    =    MM;                //Update month 
    ConvertTime->day    =    DD;                //Update date 
    ConvertTime->hour   =    hh;                //When updating 
    ConvertTime->min    =    mm;                //Update score 
    ConvertTime->sec    =    ss;                //Update seconds 
}  



// Author: Dan Cheng, senior student Q746876041, Bi shebang


/*********************************************************end of file**************************************************/

6 finally

Technical solutions, design help and problem opening guidance
print("Q 746876041") 

Complete set of single chip microcomputer projects:
https://blog.csdn.net/huawei123444/article/details/119822845

Posted on Sun, 26 Sep 2021 02:55:48 -0400 by mad4dweb