【毕业设计教程】单片机发送短信消息(GMS模块) - 物联网 嵌入式 stm32

这篇具有很好参考价值的文章主要介绍了【毕业设计教程】单片机发送短信消息(GMS模块) - 物联网 嵌入式 stm32。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1 简介

Hi,大家好,这里是丹成学长,今天向大家介绍如何使用GMS模块,达到单片机发送短信的效果,应用场景非常广泛

** 单片机发送短信消息(GMS模块)**

大家可用于 课程设计 或 毕业设计


单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052文章来源地址https://www.toymoban.com/news/detail-431133.html


2 GMS模块

【毕业设计教程】单片机发送短信消息(GMS模块) - 物联网 嵌入式 stm32
GSM模块使用上海SIMcom公司的SIM900高精度无线GSM/GPRS完全四频芯片,使用SMT封装且融 合了高性能的ARM926EJ-S内核。可以适应小型设备的高性价比解决方案。

模块采用标准工业级接口,SIM900配备支持GSM/GPRS 850/900/1800/1900MHz的语音、短信、 数据和传真,高内聚性且低功耗。

模块在通信时瞬时电流可达2A,所以需要给控制板外接电源,一般的7.5V 2000mA直流电源即可。也可另购直流7.5V电源或者电池盒。

3 技术规格

  • 全四频 850/ 900/ 1800/ 1900 MHz
  • GPRS多热点类型10/8
  • GPRS符合B型基站
  • GSM 2/2+ 标准
  • 4型 (2 W @850/ 900 MHz)
  • 1型 (1 W @ 1800/1900MHz)
  • 支持SAIC (Single Antenna Interference Cancellation)
  • 采用兼容AT指令控制(GSM 07.07 ,07.05以及SIMCOM增强型指令)
  • 低电运行时0.1mA
  • 工作温度 -40°C to +85 °C

3.1 适应性

兼容蜂窝AT指令

AT指令简介

  • 使用任何串口调试终端,需要勾选“添加新行”或者类似的。使用Arduino IDE 1.0以上版本的串口窗口需要选择“Both NL& CR”,低版本的IDE不支持这个功能。

  • 所谓AT指令,就是通讯模块通信用的一种指令,以字母“AT”开头。发送AT指令后,会返回以"+"开头的执行结果,如果出错会返回“ERROR”信息,如果正常则会在消息最后发“OK”字样。

下面仅以常用功能举例,复杂的功能请参见SIM900_ATC文档。

测试信号质量,用串口发送下面的指令:

 AT+CSQ

会收到形如下面这样的回复消息:

+CSQ: 11,0
OK

拨打电话(这条指令后的分号不可少),可以把下面指令里的10086,替换成其他号码。

 ATD10086;

接听电话

 ATA

发送短信

首先设置成文本模式:
 AT+CMGF=1
设置使用模块默认的国际标准字母字符集发送短信
 AT+CSCS?
发送目标号码
 AT+CMGS="10086"
此时系统会出现“>”提示符,直接输入短信内容
> YE
这条短信的目的是发送给10086,用来查询余额。发送成功以后会收到系统如下提示,后面的数字表示发送短信的编号。
+CMGS: 115 
OK

4 arduino + GMS 示例代码


#include <Wire.h>

#define  GprsPWR     37    //模块电源开关信号,处理器输出高电平会导致模块拉低PWRKEY来开启和关闭模块。 用户可以通过 拉低PWERKEY 保持至少1秒然后释放来开启和关闭模块。
#define  GprsNRST    2    //外部复位控制脚,处理器控制信号给高电平,导致模块管脚复位低电平复位。
#define  GprsSTATUS  10   //模块状态输出管脚,低电平:模块掉电,高电平:模块在工作状态,模块电源开关或者模块复位后至少需要等待2.5秒后才能检查STATUS管脚状态。


//函数原型:  void GprsPWRkey(void)                                       
//参数说明:  无                                        
//返回值:    无                                                               
//说明:      GPRS模块开关机时序
///
void GprsPWRkey(void)
{
  digitalWrite(GprsPWR,HIGH);
  delay(1500);  //至少维持1秒钟
  digitalWrite(GprsPWR,LOW);
  delay(2500);  //等待2.5秒后,在去检测STATUS管脚,STATUS低电平:模块掉电,高电平:模块在工作状态
}


//函数原型:  void GprsReset(void)                                    
//参数说明:  无                                        
//返回值:    无                                                               
//说明:      GPRS模块复位时序
///
void GprsReset(void)
{
  digitalWrite(GprsNRST,HIGH);
  delayMicroseconds(50);  //至少50US复位信号
  digitalWrite(GprsNRST,LOW);
  delay(2500);  //等待2.5秒后,在去检测STATUS管脚,STATUS低电平:模块掉电,高电平:模块在工作状态
}


//函数原型:  void GprsInit(void)                                         
//参数说明:  无                                        
//返回值:    开机状态, 0:模块掉电  1:模块在工作状态                                                          
//说明:      GPRS初始化
///
int GprsInit(void)
{
  int temp = 0;
  pinMode(GprsPWR,OUTPUT); //将各个控制IO设置为输出
  pinMode(GprsNRST,OUTPUT);  
  pinMode(GprsSTATUS,INPUT); 
  Serial.begin(9600);      //使用serial 2 和 GPRS通信
  Serial2.begin(9600);      //使用serial 2 和 GPRS通信

  GprsReset();  //模块复位
  
  return temp;
}


//函数原型:  void GprsInit(void)                                         
//参数说明:  无                                        
//返回值:    无                                                          
//说明:      GPRS模块测试,打电话,在串口调试终端输入ATDxxxxx13800138000;回车换行 拨打电话
//           发送AT+CSQ回车换行 查询信号强度。在这里可以测试各种AT指令 
///
void GprsTest(void)
{
   Serial2.print("A");  //发送一个大写字母A来同步GPRS模块的波特率  
  
          //发送短信
     Serial2.println("AT+CMGF=1");
     Serial.println("AT+CMGF=1");
     delay(1000);
     Serial2.println("AT+CMGS=\"13800138000\"");//xxx为电话号码
     Serial.println("AT+CMGS=\"13800138000\"");//xxx为电话号码
     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为电话号码
     Serial.println("AT+CMGS=\"10086\"");//xxx为电话号码
     delay(1000);
     Serial2.print("YE");
     Serial.print("YE");
     delay(1000);
     Serial2.write(26);
      Serial2.write(26);
      Serial2.println();

     while(1){
        if(Serial.available())  //读取 USB串口数据将数据发送给GPRS模块
       {
         char input = Serial.read();
        Serial2.print(input); 
       }
       if( Serial2.available())  //接收 GPRS模块返回数据,将数据显示到USB串口终端
      { 
        char input2 = Serial2.read();
        Serial.print(input2);
      }
     }
}


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

void loop()
{
    
}

//
//            SIM900 GSM/GPRS模块驱动
//模块使用7.5V电源供电,在测试时必须插入SIM卡
// 作者:丹成学长Q746876041 毕设帮助
//

5 实现效果

结合GPS模块,把GPS数据发送到自己的手机上

【毕业设计教程】单片机发送短信消息(GMS模块) - 物联网 嵌入式 stm32

部分核心代码 (使用STM32单片机)

// 作者:丹成学长Q746876041 毕设帮助

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


/* DMA接收缓冲  */
uint8_t gps_rbuff[GPS_RBUFF_SIZE];

/* DMA传输结束标志 */
__IO uint8_t GPS_TransferEnd = 0, GPS_HalfTransferEnd = 0;



/**
  * @brief  GPS_Interrupt_Config 配置GPS使用的DMA中断 
  * @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不是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中断服务函数
  * @param  None.
  * @retval None.
  */
void GPS_ProcessDMAIRQ(void)
{
  
  if(DMA_GetITStatus(GPS_DMA_IT_HT) )         /* DMA 半传输完成 */
  {
    GPS_HalfTransferEnd = 1;                //设置半传输完成标志位
    DMA_ClearFlag(GPS_DMA_FLAG_HT);
        
  }
  else if(DMA_GetITStatus(GPS_DMA_IT_TC))     /* DMA 传输完成 */
  {
    GPS_TransferEnd = 1;                    //设置传输完成标志位
    DMA_ClearFlag(GPS_DMA_FLAG_TC);

   }
}


/**
  * @brief  GPS_DMA_Config gps dma接收配置
  * @param  无
  * @retval 无
  */
static void GPS_DMA_Config(void) //其为一个函数
{
        DMA_InitTypeDef DMA_InitStructure; //定义一个DMA_InitTypeDef类型的结构体,名为DMA_InitStructure
    
        /*开启DMA时钟*/
        RCC_AHBPeriphClockCmd(GPS_DMA_CLK, ENABLE);

        /*设置DMA源:串口数据寄存器地址*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = GPS_DATA_ADDR;       //带点号为结构体内的成员,可直接赋值,相当于变量
//从该处进入gps.config.h可见,gps的串口通信定义为USart2,我们可从这里修改
        /*内存地址(要传输的变量的指针)*/
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)gps_rbuff;

        /*方向:从外设到内存 */        
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;    

        /*传输大小DMA_BufferSize=SENDBUFF_SIZE*/    
        DMA_InitStructure.DMA_BufferSize = GPS_RBUFF_SIZE;

        /*外设地址不增*/        
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //想修改可直接找到相对应的名字修改

        /*内存地址自增*/
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    

        /*外设数据单位*/    
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

        /*内存数据单位 8bit*/
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;     

        /*DMA模式:不断循环*/
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;     

        /*优先级:中*/    
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  

        /*禁止内存到内存的传输    */
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

        /*配置DMA的通道*/           
        DMA_Init(GPS_DMA_CHANNEL, &DMA_InitStructure);        
    
    GPS_Interrupt_Config();
        
    DMA_ITConfig(GPS_DMA_CHANNEL,DMA_IT_HT|DMA_IT_TC,ENABLE);  //配置DMA发送完成后产生中断

        /*使能DMA*/
        DMA_Cmd (GPS_DMA_CHANNEL,ENABLE);        
    
    /* 配置串口 向 DMA发出TX请求 */
        USART_DMACmd(GPS_USART, USART_DMAReq_Rx, ENABLE);


}

/**
  * @brief  GPS_Config gps 初始化
  * @param  无
  * @retval 无
  */
void GPS_Config(void)
{
  GPS_USART_INIT();   //初始化串口
  GPS_DMA_Config();  //初始化串口配套的DMA模式
  
}

 

/**
  * @brief  trace 在解码时输出捕获的GPS语句
  * @param  str: 要输出的字符串,str_size:数据长度
  * @retval 无
  */
void trace(const char *str, int str_size)
{
  #ifdef __GPS_DEBUG    //在gps_config.h文件配置这个宏,是否输出调试信息
    uint16_t i;
    printf("\r\nTrace: ");
    for(i=0;i<str_size;i++)
      printf("%c",*(str+i));
  
    printf("\n");
  #endif
}

/**
  * @brief  error 在解码出错时输出提示消息
  * @param  str: 要输出的字符串,str_size:数据长度
  * @retval 无
  */
void error(const char *str, int str_size)
{
    #ifdef __GPS_DEBUG   //在gps_config.h文件配置这个宏,是否输出调试信息

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



/******************************************************************************************************** 
**     函数名称:            bit        IsLeapYear(uint8_t    iYear) 
**    功能描述:            判断闰年(仅针对于2000以后的年份) 
**    入口参数:            iYear    两位年数 
**    出口参数:            uint8_t        1:为闰年    0:为平年 
********************************************************************************************************/ 
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; 
} 

/******************************************************************************************************** 
**     函数名称:            void    GMTconvert(uint8_t *DT,uint8_t GMT,uint8_t AREA) 
**    功能描述:            格林尼治时间换算世界各时区时间 
**    入口参数:            *DT:    表示日期时间的数组 格式 YY,MM,DD,HH,MM,SS 
**                        GMT:    时区数 
**                        AREA:    1(+)东区 W0(-)西区 
********************************************************************************************************/ 
void    GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT,uint8_t AREA) 
{ 
    uint32_t    YY,MM,DD,hh,mm,ss;        //年月日时分秒暂存变量 
     
    if(GMT==0)    return;                //如果处于0时区直接返回 
    if(GMT>12)    return;                //时区最大为12 超过则返回         

    YY    =    SourceTime->year;                //获取年 
    MM    =    SourceTime->mon;                 //获取月 
    DD    =    SourceTime->day;                 //获取日 
    hh    =    SourceTime->hour;                //获取时 
    mm    =    SourceTime->min;                 //获取分 
    ss    =    SourceTime->sec;                 //获取秒 

    if(AREA)                        //东(+)时区处理 
    { 
        if(hh+GMT<24)    hh    +=    GMT;//如果与格林尼治时间处于同一天则仅加小时即可 
        else                        //如果已经晚于格林尼治时间1天则进行日期处理 
        { 
            hh    =    hh+GMT-24;        //先得出时间 
            if(MM==1 || MM==3 || MM==5 || MM==7 || MM==8 || MM==10)    //大月份(12月单独处理) 
            { 
                if(DD<31)    DD++; 
                else 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
            } 
            else if(MM==4 || MM==6 || MM==9 || MM==11)                //小月份2月单独处理) 
            { 
                if(DD<30)    DD++; 
                else 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
            } 
            else if(MM==2)    //处理2月份 
            { 
                if((DD==29) || (DD==28 && IsLeapYear(YY)==0))        //本来是闰年且是2月29日 或者不是闰年且是2月28日 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
                else    DD++; 
            } 
            else if(MM==12)    //处理12月份 
            { 
                if(DD<31)    DD++; 
                else        //跨年最后一天 
                {               
                    DD    =    1; 
                    MM    =    1; 
                    YY    ++; 
                } 
            } 
        } 
    } 
    else 
    {     
        if(hh>=GMT)    hh    -=    GMT;    //如果与格林尼治时间处于同一天则仅减小时即可 
        else                        //如果已经早于格林尼治时间1天则进行日期处理 
        { 
            hh    =    hh+24-GMT;        //先得出时间 
            if(MM==2 || MM==4 || MM==6 || MM==8 || MM==9 || MM==11)    //上月是大月份(1月单独处理) 
            { 
                if(DD>1)    DD--; 
                else 
                { 
                    DD    =    31; 
                    MM    --; 
                } 
            } 
            else if(MM==5 || MM==7 || MM==10 || MM==12)                //上月是小月份2月单独处理) 
            { 
                if(DD>1)    DD--; 
                else 
                { 
                    DD    =    30; 
                    MM    --; 
                } 
            } 
            else if(MM==3)    //处理上个月是2月份 
            { 
                if((DD==1) && IsLeapYear(YY)==0)                    //不是闰年 
                { 
                    DD    =    28; 
                    MM    --; 
                } 
                else    DD--; 
            } 
            else if(MM==1)    //处理1月份 
            { 
                if(DD>1)    DD--; 
                else        //新年第一天 
                {               
                    DD    =    31; 
                    MM    =    12; 
                    YY    --; 
                } 
            } 
        } 
    }         

    ConvertTime->year   =    YY;                //更新年 
    ConvertTime->mon    =    MM;                //更新月 
    ConvertTime->day    =    DD;                //更新日 
    ConvertTime->hour   =    hh;                //更新时 
    ConvertTime->min    =    mm;                //更新分 
    ConvertTime->sec    =    ss;                //更新秒 
}  



// 作者:丹成学长Q746876041 毕设帮助


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

单片机-嵌入式毕设选题大全及项目分享:

https://blog.csdn.net/m0_71572576/article/details/125409052


6 最后

到了这里,关于【毕业设计教程】单片机发送短信消息(GMS模块) - 物联网 嵌入式 stm32的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【单片机毕业设计】【mcuclub-jj-011】基于单片机的加湿器的设计

    项目名:加湿器 项目编号:mcuclub-jj-011 单片机类型:STC89C52 具体功能: 1、通过DHT11获取湿度值,当湿度值低于设置最小值,则启动加湿器加湿,大于设置最大值,则停止加湿 2、通过液位检测模块检测加湿器中是否还有水,如果没有,则自动停止加湿、声光提醒 3、通过按键

    2023年04月17日
    浏览(106)
  • 毕业设计 - 基于单片机的智能饮水机系统设计与实现 (物联网 嵌入式 单片机)

    Hi,大家好,学长今天向大家介绍一个 单片机项目 基于单片机的智能饮水机系统设计与实现 大家可用于 课程设计 或 毕业设计 这次设计的智能饮水机就是单片机结合传感器的一个应用。 该系统设计综合单片机以及电子技术理论,从生活实际出发,完善了饮水机的功能。整个

    2024年02月03日
    浏览(109)
  • 【单片机毕业设计】【mcuclub-dz-196】基于单片机下的新型智能花盆设计

    项目名:基于单片机下的新型智能花盆设计 项目名:花盆(实物) 项目编号:mcuclub-dz-196 单片机类型:STM32F103C8T6 具体功能: 1、通过防水式DS18B20测量土壤温度,当温度高于设置最大值时,进行风扇降温,低于设置最大值,进行防水加热 2、通过土壤湿度传感器检测湿度值,

    2024年02月19日
    浏览(96)
  • 【单片机毕业设计】【mcuclub-dz-032】基于单片机的智能门禁控制系统设计

    项目名:基于单片机的门禁的设计 单片机:STM32F103C8T6 mcuclub-dz-032 功能简介: 1、通过扫码枪进行扫描二维码,当二维码识别成功,10s内需触发红外避障管,并通过红外测温模块进行测温,如果温度正常,则自动开锁,如果温度异常,则声光报警3次,锁不打开 2、通过RFID进行

    2024年01月18日
    浏览(72)
  • 【单片机毕业设计】【mcuclub-dz-198】基于单片机的车辆安全驾驶预警系统设计

    项目名:基于单片机的车辆安全驾驶预警系统设计 项目名:驾驶检测(实物)(mcuclub-105) 项目编号:mcuclub-dz-198 单片机类型:STM32F103C8T6 具体功能: 1、通过红测速模块管检测当前老年车的速度; 2、通过超声波测距测量车前障碍物的距离,若距离大于设定最大值,绿灯亮;

    2024年02月20日
    浏览(58)
  • 单片机开发教程3——串口发送MPU6050姿态角

    MPU6050 是 InvenSense 公司推出的整合性 6 轴运动处理组件,其内部整合了 3 轴陀螺仪和 3 轴加速度传感器,并且含有一个IIC 接口, 可用于连接外部磁力传感器,并利用自带的数字运动处理器(DMP: Digital Motion Processor) 硬件加速引擎,通过主 IIC 接口,向应用端输出完整的 9 轴融

    2024年02月14日
    浏览(43)
  • 毕业设计 单片机选题100例(一)

    【单片机毕业设计项目分享系列】 🔥 单片机毕业设计及享100例系列的第一篇,目的是分享高质量的毕设作品给大家,包含全面内容:源码+原理图+PCB+实物演示+论文。 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的单片机项目缺少创新和亮点,往往达不到

    2024年02月07日
    浏览(65)
  • 毕业设计单片机可以用万能板吗?

    可以是可以,就是焊接起来比较麻烦,特别是有好几个重复连线点的时候,检测起来就不那么容易了,而且布线看起来乱糟糟的,如果后期一不小心把线弄断了,查起来就更麻烦了,倒不如pcb打板来的方便。最近很多小伙伴找我,说想要一些单片机的资料,然后我根据自己从

    2024年02月04日
    浏览(60)
  • 【单片机毕业设计】【mcuclub-dz-177】基于32单片机的自动扶梯控制系统设计

    项目名:基于32单片机的自动扶梯控制系统设计 项目名:扶梯(实物) 项目编号:mcuclub-dz-177 单片机类型:STM32F103C8T6 具体功能: 1、通过MX1508驱动两个直流电机模拟上下扶梯(一个正转代表上行,一个反转代表下行) 2、每个扶梯都有两个红外对射管,进行人数计数,如果扶

    2024年02月21日
    浏览(74)
  • 【单片机毕业设计】【mcuclub-dz-112】基于单片机的智能饮水机系统设计与实现

    项目名:基于单片机的智能饮水机系统设计与实现 项目名:基于单片机的饮水机的设计 单片机:STC89C52 功能简介: 1、通过一个按键模拟加热电源的开关 2、通过防水式DS18B20检测水温,当电源打开时,温度小于设置最小值,进行自动加热,直到加热到最大值时停止; 3、通过

    2024年03月09日
    浏览(165)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包