1 簡(jiǎn)介
Hi,大家好,這里是丹成學(xué)長(zhǎng),今天向大家介紹如何使用GMS模塊,達(dá)到單片機(jī)發(fā)送短信的效果,應(yīng)用場(chǎng)景非常廣泛
** 單片機(jī)發(fā)送短信消息(GMS模塊)**
大家可用于 課程設(shè)計(jì) 或 畢業(yè)設(shè)計(jì)
單片機(jī)-嵌入式畢設(shè)選題大全及項(xiàng)目分享:
https://blog.csdn.net/m0_71572576/article/details/125409052文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-431133.html
2 GMS模塊
GSM模塊使用上海SIMcom公司的SIM900高精度無(wú)線GSM/GPRS完全四頻芯片,使用SMT封裝且融 合了高性能的ARM926EJ-S內(nèi)核??梢赃m應(yīng)小型設(shè)備的高性?xún)r(jià)比解決方案。
模塊采用標(biāo)準(zhǔn)工業(yè)級(jí)接口,SIM900配備支持GSM/GPRS 850/900/1800/1900MHz的語(yǔ)音、短信、 數(shù)據(jù)和傳真,高內(nèi)聚性且低功耗。
模塊在通信時(shí)瞬時(shí)電流可達(dá)2A,所以需要給控制板外接電源,一般的7.5V 2000mA直流電源即可。也可另購(gòu)直流7.5V電源或者電池盒。
3 技術(shù)規(guī)格
- 全四頻 850/ 900/ 1800/ 1900 MHz
- GPRS多熱點(diǎn)類(lèi)型10/8
- GPRS符合B型基站
- GSM 2/2+ 標(biāo)準(zhǔn)
- 4型 (2 W @850/ 900 MHz)
- 1型 (1 W @ 1800/1900MHz)
- 支持SAIC (Single Antenna Interference Cancellation)
- 采用兼容AT指令控制(GSM 07.07 ,07.05以及SIMCOM增強(qiáng)型指令)
- 低電運(yùn)行時(shí)0.1mA
- 工作溫度 -40°C to +85 °C
3.1 適應(yīng)性
兼容蜂窩AT指令
AT指令簡(jiǎn)介
-
使用任何串口調(diào)試終端,需要勾選“添加新行”或者類(lèi)似的。使用Arduino IDE 1.0以上版本的串口窗口需要選擇“Both NL& CR”,低版本的IDE不支持這個(gè)功能。
-
所謂AT指令,就是通訊模塊通信用的一種指令,以字母“AT”開(kāi)頭。發(fā)送AT指令后,會(huì)返回以"+"開(kāi)頭的執(zhí)行結(jié)果,如果出錯(cuò)會(huì)返回“ERROR”信息,如果正常則會(huì)在消息最后發(fā)“OK”字樣。
下面僅以常用功能舉例,復(fù)雜的功能請(qǐng)參見(jiàn)SIM900_ATC文檔。
測(cè)試信號(hào)質(zhì)量,用串口發(fā)送下面的指令:
AT+CSQ
會(huì)收到形如下面這樣的回復(fù)消息:
+CSQ: 11,0
OK
撥打電話(huà)(這條指令后的分號(hào)不可少),可以把下面指令里的10086,替換成其他號(hào)碼。
ATD10086;
接聽(tīng)電話(huà)
ATA
發(fā)送短信
首先設(shè)置成文本模式:
AT+CMGF=1
設(shè)置使用模塊默認(rèn)的國(guó)際標(biāo)準(zhǔn)字母字符集發(fā)送短信
AT+CSCS?
發(fā)送目標(biāo)號(hào)碼
AT+CMGS="10086"
此時(shí)系統(tǒng)會(huì)出現(xiàn)“>”提示符,直接輸入短信內(nèi)容
> YE
這條短信的目的是發(fā)送給10086,用來(lái)查詢(xún)余額。發(fā)送成功以后會(huì)收到系統(tǒng)如下提示,后面的數(shù)字表示發(fā)送短信的編號(hào)。
+CMGS: 115
OK
4 arduino + GMS 示例代碼
#include <Wire.h>
#define GprsPWR 37 //模塊電源開(kāi)關(guān)信號(hào),處理器輸出高電平會(huì)導(dǎo)致模塊拉低PWRKEY來(lái)開(kāi)啟和關(guān)閉模塊。 用戶(hù)可以通過(guò) 拉低PWERKEY 保持至少1秒然后釋放來(lái)開(kāi)啟和關(guān)閉模塊。
#define GprsNRST 2 //外部復(fù)位控制腳,處理器控制信號(hào)給高電平,導(dǎo)致模塊管腳復(fù)位低電平復(fù)位。
#define GprsSTATUS 10 //模塊狀態(tài)輸出管腳,低電平:模塊掉電,高電平:模塊在工作狀態(tài),模塊電源開(kāi)關(guān)或者模塊復(fù)位后至少需要等待2.5秒后才能檢查STATUS管腳狀態(tài)。
//函數(shù)原型: void GprsPWRkey(void)
//參數(shù)說(shuō)明: 無(wú)
//返回值: 無(wú)
//說(shuō)明: GPRS模塊開(kāi)關(guān)機(jī)時(shí)序
///
void GprsPWRkey(void)
{
digitalWrite(GprsPWR,HIGH);
delay(1500); //至少維持1秒鐘
digitalWrite(GprsPWR,LOW);
delay(2500); //等待2.5秒后,在去檢測(cè)STATUS管腳,STATUS低電平:模塊掉電,高電平:模塊在工作狀態(tài)
}
//函數(shù)原型: void GprsReset(void)
//參數(shù)說(shuō)明: 無(wú)
//返回值: 無(wú)
//說(shuō)明: GPRS模塊復(fù)位時(shí)序
///
void GprsReset(void)
{
digitalWrite(GprsNRST,HIGH);
delayMicroseconds(50); //至少50US復(fù)位信號(hào)
digitalWrite(GprsNRST,LOW);
delay(2500); //等待2.5秒后,在去檢測(cè)STATUS管腳,STATUS低電平:模塊掉電,高電平:模塊在工作狀態(tài)
}
//函數(shù)原型: void GprsInit(void)
//參數(shù)說(shuō)明: 無(wú)
//返回值: 開(kāi)機(jī)狀態(tài), 0:模塊掉電 1:模塊在工作狀態(tài)
//說(shuō)明: GPRS初始化
///
int GprsInit(void)
{
int temp = 0;
pinMode(GprsPWR,OUTPUT); //將各個(gè)控制IO設(shè)置為輸出
pinMode(GprsNRST,OUTPUT);
pinMode(GprsSTATUS,INPUT);
Serial.begin(9600); //使用serial 2 和 GPRS通信
Serial2.begin(9600); //使用serial 2 和 GPRS通信
GprsReset(); //模塊復(fù)位
return temp;
}
//函數(shù)原型: void GprsInit(void)
//參數(shù)說(shuō)明: 無(wú)
//返回值: 無(wú)
//說(shuō)明: GPRS模塊測(cè)試,打電話(huà),在串口調(diào)試終端輸入ATDxxxxx13800138000;回車(chē)換行 撥打電話(huà)
// 發(fā)送AT+CSQ回車(chē)換行 查詢(xún)信號(hào)強(qiáng)度。在這里可以測(cè)試各種AT指令
///
void GprsTest(void)
{
Serial2.print("A"); //發(fā)送一個(gè)大寫(xiě)字母A來(lái)同步GPRS模塊的波特率
//發(fā)送短信
Serial2.println("AT+CMGF=1");
Serial.println("AT+CMGF=1");
delay(1000);
Serial2.println("AT+CMGS=\"13800138000\"");//xxx為電話(huà)號(hào)碼
Serial.println("AT+CMGS=\"13800138000\"");//xxx為電話(huà)號(hào)碼
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為電話(huà)號(hào)碼
Serial.println("AT+CMGS=\"10086\"");//xxx為電話(huà)號(hào)碼
delay(1000);
Serial2.print("YE");
Serial.print("YE");
delay(1000);
Serial2.write(26);
Serial2.write(26);
Serial2.println();
while(1){
if(Serial.available()) //讀取 USB串口數(shù)據(jù)將數(shù)據(jù)發(fā)送給GPRS模塊
{
char input = Serial.read();
Serial2.print(input);
}
if( Serial2.available()) //接收 GPRS模塊返回?cái)?shù)據(jù),將數(shù)據(jù)顯示到USB串口終端
{
char input2 = Serial2.read();
Serial.print(input2);
}
}
}
void setup()
{
GprsPWRkey();
GprsInit();
delay(2000);
//GprsReset();
GprsTest();
}
void loop()
{
}
//
// SIM900 GSM/GPRS模塊驅(qū)動(dòng)
//模塊使用7.5V電源供電,在測(cè)試時(shí)必須插入SIM卡
// 作者:丹成學(xué)長(zhǎng)Q746876041 畢設(shè)幫助
//
5 實(shí)現(xiàn)效果
結(jié)合GPS模塊,把GPS數(shù)據(jù)發(fā)送到自己的手機(jī)上
部分核心代碼 (使用STM32單片機(jī))
// 作者:丹成學(xué)長(zhǎng)Q746876041 畢設(shè)幫助
#include "gps_config.h"
#include "bsp_usart3.h"
#include "nmea/nmea.h"
/* DMA接收緩沖 */
uint8_t gps_rbuff[GPS_RBUFF_SIZE];
/* DMA傳輸結(jié)束標(biāo)志 */
__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中斷服務(wù)函數(shù)
* @param None.
* @retval None.
*/
void GPS_ProcessDMAIRQ(void)
{
if(DMA_GetITStatus(GPS_DMA_IT_HT) ) /* DMA 半傳輸完成 */
{
GPS_HalfTransferEnd = 1; //設(shè)置半傳輸完成標(biāo)志位
DMA_ClearFlag(GPS_DMA_FLAG_HT);
}
else if(DMA_GetITStatus(GPS_DMA_IT_TC)) /* DMA 傳輸完成 */
{
GPS_TransferEnd = 1; //設(shè)置傳輸完成標(biāo)志位
DMA_ClearFlag(GPS_DMA_FLAG_TC);
}
}
/**
* @brief GPS_DMA_Config gps dma接收配置
* @param 無(wú)
* @retval 無(wú)
*/
static void GPS_DMA_Config(void) //其為一個(gè)函數(shù)
{
DMA_InitTypeDef DMA_InitStructure; //定義一個(gè)DMA_InitTypeDef類(lèi)型的結(jié)構(gòu)體,名為DMA_InitStructure
/*開(kāi)啟DMA時(shí)鐘*/
RCC_AHBPeriphClockCmd(GPS_DMA_CLK, ENABLE);
/*設(shè)置DMA源:串口數(shù)據(jù)寄存器地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = GPS_DATA_ADDR; //帶點(diǎn)號(hào)為結(jié)構(gòu)體內(nèi)的成員,可直接賦值,相當(dāng)于變量
//從該處進(jìn)入gps.config.h可見(jiàn),gps的串口通信定義為USart2,我們可從這里修改
/*內(nèi)存地址(要傳輸?shù)淖兞康闹羔?*/
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)gps_rbuff;
/*方向:從外設(shè)到內(nèi)存 */
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
/*傳輸大小DMA_BufferSize=SENDBUFF_SIZE*/
DMA_InitStructure.DMA_BufferSize = GPS_RBUFF_SIZE;
/*外設(shè)地址不增*/
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //想修改可直接找到相對(duì)應(yīng)的名字修改
/*內(nèi)存地址自增*/
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
/*外設(shè)數(shù)據(jù)單位*/
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
/*內(nèi)存數(shù)據(jù)單位 8bit*/
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
/*DMA模式:不斷循環(huán)*/
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
/*優(yōu)先級(jí):中*/
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
/*禁止內(nèi)存到內(nèi)存的傳輸 */
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發(fā)送完成后產(chǎn)生中斷
/*使能DMA*/
DMA_Cmd (GPS_DMA_CHANNEL,ENABLE);
/* 配置串口 向 DMA發(fā)出TX請(qǐng)求 */
USART_DMACmd(GPS_USART, USART_DMAReq_Rx, ENABLE);
}
/**
* @brief GPS_Config gps 初始化
* @param 無(wú)
* @retval 無(wú)
*/
void GPS_Config(void)
{
GPS_USART_INIT(); //初始化串口
GPS_DMA_Config(); //初始化串口配套的DMA模式
}
/**
* @brief trace 在解碼時(shí)輸出捕獲的GPS語(yǔ)句
* @param str: 要輸出的字符串,str_size:數(shù)據(jù)長(zhǎng)度
* @retval 無(wú)
*/
void trace(const char *str, int str_size)
{
#ifdef __GPS_DEBUG //在gps_config.h文件配置這個(gè)宏,是否輸出調(diào)試信息
uint16_t i;
printf("\r\nTrace: ");
for(i=0;i<str_size;i++)
printf("%c",*(str+i));
printf("\n");
#endif
}
/**
* @brief error 在解碼出錯(cuò)時(shí)輸出提示消息
* @param str: 要輸出的字符串,str_size:數(shù)據(jù)長(zhǎng)度
* @retval 無(wú)
*/
void error(const char *str, int str_size)
{
#ifdef __GPS_DEBUG //在gps_config.h文件配置這個(gè)宏,是否輸出調(diào)試信息
uint16_t i;
printf("\r\nError: ");
for(i=0;i<str_size;i++)
printf("%c",*(str+i));
printf("\n");
#endif
}
/********************************************************************************************************
** 函數(shù)名稱(chēng): bit IsLeapYear(uint8_t iYear)
** 功能描述: 判斷閏年(僅針對(duì)于2000以后的年份)
** 入口參數(shù): iYear 兩位年數(shù)
** 出口參數(shù): 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;
}
/********************************************************************************************************
** 函數(shù)名稱(chēng): void GMTconvert(uint8_t *DT,uint8_t GMT,uint8_t AREA)
** 功能描述: 格林尼治時(shí)間換算世界各時(shí)區(qū)時(shí)間
** 入口參數(shù): *DT: 表示日期時(shí)間的數(shù)組 格式 YY,MM,DD,HH,MM,SS
** GMT: 時(shí)區(qū)數(shù)
** AREA: 1(+)東區(qū) W0(-)西區(qū)
********************************************************************************************************/
void GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT,uint8_t AREA)
{
uint32_t YY,MM,DD,hh,mm,ss; //年月日時(shí)分秒暫存變量
if(GMT==0) return; //如果處于0時(shí)區(qū)直接返回
if(GMT>12) return; //時(shí)區(qū)最大為12 超過(guò)則返回
YY = SourceTime->year; //獲取年
MM = SourceTime->mon; //獲取月
DD = SourceTime->day; //獲取日
hh = SourceTime->hour; //獲取時(shí)
mm = SourceTime->min; //獲取分
ss = SourceTime->sec; //獲取秒
if(AREA) //東(+)時(shí)區(qū)處理
{
if(hh+GMT<24) hh += GMT;//如果與格林尼治時(shí)間處于同一天則僅加小時(shí)即可
else //如果已經(jīng)晚于格林尼治時(shí)間1天則進(jìn)行日期處理
{
hh = hh+GMT-24; //先得出時(shí)間
if(MM==1 || MM==3 || MM==5 || MM==7 || MM==8 || MM==10) //大月份(12月單獨(dú)處理)
{
if(DD<31) DD++;
else
{
DD = 1;
MM ++;
}
}
else if(MM==4 || MM==6 || MM==9 || MM==11) //小月份2月單獨(dú)處理)
{
if(DD<30) DD++;
else
{
DD = 1;
MM ++;
}
}
else if(MM==2) //處理2月份
{
if((DD==29) || (DD==28 && IsLeapYear(YY)==0)) //本來(lái)是閏年且是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; //如果與格林尼治時(shí)間處于同一天則僅減小時(shí)即可
else //如果已經(jīng)早于格林尼治時(shí)間1天則進(jìn)行日期處理
{
hh = hh+24-GMT; //先得出時(shí)間
if(MM==2 || MM==4 || MM==6 || MM==8 || MM==9 || MM==11) //上月是大月份(1月單獨(dú)處理)
{
if(DD>1) DD--;
else
{
DD = 31;
MM --;
}
}
else if(MM==5 || MM==7 || MM==10 || MM==12) //上月是小月份2月單獨(dú)處理)
{
if(DD>1) DD--;
else
{
DD = 30;
MM --;
}
}
else if(MM==3) //處理上個(gè)月是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; //更新時(shí)
ConvertTime->min = mm; //更新分
ConvertTime->sec = ss; //更新秒
}
// 作者:丹成學(xué)長(zhǎng)Q746876041 畢設(shè)幫助
/*********************************************************end of file**************************************************/
單片機(jī)-嵌入式畢設(shè)選題大全及項(xiàng)目分享:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-431133.html
https://blog.csdn.net/m0_71572576/article/details/125409052
6 最后
到了這里,關(guān)于【畢業(yè)設(shè)計(jì)教程】單片機(jī)發(fā)送短信消息(GMS模塊) - 物聯(lián)網(wǎng) 嵌入式 stm32的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!