• 方案介紹
    • 一、環(huán)境介紹
    • 二、MC20模塊
    • 三、代碼功能
    • 四、核心代碼
    • 五、OneNet創(chuàng)建產(chǎn)品
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

STM32+移遠(yuǎn)MC20模塊采用MQTT協(xié)議登錄OneNet上傳GPS數(shù)據(jù)

01/29 08:54
2763
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

更多詳細(xì)資料請聯(lián)系.docx

共1個文件

一、環(huán)境介紹

MCU:??STM32F103C8T6

GSM模塊:?移遠(yuǎn)MC20 (MT2503D)(GSM+GPS共存)功能很強(qiáng)大

開發(fā)軟件:?Keil5

MQTT協(xié)議采用OneNet的舊版協(xié)議,登錄OneNet控制臺創(chuàng)建應(yīng)用時要選擇舊版本。

如果想使用新版本的標(biāo)準(zhǔn)MQTT協(xié)議連接OnetNet請參考這里:
https://blog.csdn.net/xiaolong1126626497/article/details/107385118

完整源代碼下載:?
https://download.csdn.net/download/xiaolong1126626497/18245206

二、MC20模塊

MC20模塊采用聯(lián)發(fā)科技最新推出的多功能通信定位芯片研制而成。它是一款集成LCC封裝、四頻段GSM/GPRS和先進(jìn)算法GNSS引擎于一體的全功能通信模塊,具有超小體積、低功耗、雙卡單待等優(yōu)勢。MC20不僅內(nèi)嵌豐富的網(wǎng)絡(luò)協(xié)議(如 TCP、UDP、PPP、FTP、HTTP以及SSL),還集成了多星座衛(wèi)星系統(tǒng)(如北斗、GPS、QZSS),因此能提供無線移動通信以及精準(zhǔn)的導(dǎo)航定位功能。

除具備GSM/GPRS無線通信功能外,MC20模塊還支持先進(jìn)的GNSS技術(shù)。它集成了EPOTM(用戶無需自設(shè)服務(wù)器,直接從MTK服務(wù)器獲取EPO數(shù)據(jù))、秒定等技術(shù),能夠?qū)崿F(xiàn)快速首次定位。由于支持北斗、GPS、QZSS等多星座衛(wèi)星系統(tǒng)解調(diào)算法,其定位更加精準(zhǔn),抗多路徑干擾能力更強(qiáng),比傳統(tǒng)GPS模塊具有更多優(yōu)勢。另外,MC20模塊中內(nèi)置LNA和低功耗算法:前者使其接收靈敏度提升至-149dBm;后者使其在低功耗模式(GLP Mode)下的耗流僅為正常工作模式的40%。

MC20模塊較傳統(tǒng)GSM+GNSS方案體積減少40%,使其在各種應(yīng)用中占具更大優(yōu)勢。其主要應(yīng)用領(lǐng)域?yàn)椋?a class="article-link" target="_blank" href="/tag/%E5%8F%AF%E7%A9%BF%E6%88%B4%E8%AE%BE%E5%A4%87/">可穿戴設(shè)備(智能手表)、寵物追蹤、財產(chǎn)追蹤及行車記錄儀等等。
主要優(yōu)勢
● 超小體積: 18.7mm × 16.0mm × 2.1mm
● 多衛(wèi)星導(dǎo)航系統(tǒng): GPS/BeiDou/QZSS
● GNSS 接收機(jī)通道: 99 路捕獲通道/33 路跟蹤通道
● 支持多種 AGPS 技術(shù),如 EASYTM 、EPOTM 、秒定等
● 內(nèi)置 LNA 大大提升 GNSS 接收機(jī)靈敏度(-167dBm@跟蹤模式):可使用無源 GNSS 天線而無需任何外部低噪聲放大器
● 支持增強(qiáng)型 GNSS 功能,如 SDK 命令、LOCUSTM 、AIC 和 GLP
● 多功能四頻段 GSM模塊: 850/900/1800/1900MHz
● 內(nèi)嵌豐富網(wǎng)絡(luò)協(xié)議: TCP/UDP/PPP/HTTP/FTP/SSL
● 支持語音、短信、QuecFOTATM 、雙卡單待以及 OpenCPU 功能
● 支持藍(lán)牙 V3.0 以及 SPP & HFP-AG 配置文件

三、代碼功能

使用STM32F103C8T6 通過串口+AT指令控制MC20模塊+MQTT協(xié)議,登錄OneNet服務(wù)器上傳GPS數(shù)據(jù),LED控制(網(wǎng)頁按鈕控制開發(fā)板上的LED燈)。

四、核心代碼

4.1 main.c

#include "stm32f10x.h"
#include "beep.h"
#include "delay.h"
#include "led.h"
#include "sys.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>
#include "timer.h"
#include "mc20.h"

//網(wǎng)絡(luò)協(xié)議層
#include "onenet.h"

//協(xié)議封裝文件
#include "dStream.h"

//產(chǎn)品ID
char PROID[]="231174";

//鑒權(quán)信息
char AUTH_INFO[]="1234567890";

//設(shè)備ID
char DEVID[]="523369555";

//API KEY
char API_KEY[]="k6vtrrEd1H7UMddiF3DzripS47w=";

//緩沖區(qū)
char onenet_http_cmd[1024];

//服務(wù)器IP地址
#define TCP_SERVER_IP_ADDR "183.230.40.39"

//服務(wù)器端口號
#define TCP_SERVER_PORT 6002


//數(shù)據(jù)流結(jié)構(gòu)
DATA_STREAM data_stream[1]=
{
	{"gps","88.88",TYPE_JSON,1},
};


/*
	STM32開發(fā)板接線說明:
	STM32					MC20
	3.3V	------>	V_IO
	GND		<----->	GND
	PA3		<------	GSM_TX
	PA2		------>	GSM_RX
*/

int main()
{   
	u32 time_cnt=0;
	u32 cnt=0;
	double Longitude; //經(jīng)度
	double latitude;  //緯度
  
	LED_Init();
  BEEP_Init();
	USART_X_Init(USART1,72,115200);
  TIM2_Init(72,20000);					//輔助串口2接收,超時時間為20ms
  USART_X_Init(USART2,36,9600); //連接著MC20(GPS+GPRS)
  
	printf("串口準(zhǔn)備就緒.....rn");
	DelayMs(500);
	
	printf("程序修改時間: %srn",__TIME__);
  while(1)
  {
		 u8 stat;
		/*初始化MC20,并連接到指定服務(wù)器*/
		 MC20_InitConnect(TCP_SERVER_IP_ADDR,TCP_SERVER_PORT);
		 
		 /*登錄OneNET服務(wù)器,上線設(shè)備*/
		 stat=OneNet_DevLink();
		 if(stat)printf("ERROR:%d,接入OneNET失敗:%drn",stat,cnt++);
		 else break; //登錄成功
		 
		 LED1=!LED1;
     delay_ms(200); 
		
		 break;//失敗也退出繼續(xù)運(yùn)行下面代碼
  }
	printf("6. OneNET服務(wù)器登錄成功!rn");
	delay_ms(100);
	
	while(1)
	{ 
		/*6. 向OneNet服務(wù)器5秒發(fā)送一次數(shù)據(jù)*/
		 time_cnt++;
		 DelayMs(1);
		 if(time_cnt>=5000)
		 {
					time_cnt=0;
					/*獲取一次GPS輸出的經(jīng)緯度信息*/
					switch(MC20_GetGPS_Data(&Longitude,&latitude))
					{
					 case 0: printf("經(jīng)度:%f,緯度:%frn",Longitude,latitude); break;
					 case 1: printf("ERROR:GPS數(shù)據(jù)接收失敗!rn"); break;
					 case 2: printf("ERROR:GPS定位數(shù)據(jù)解碼失敗!<請將GPS拿到空曠位置定位>rn"); break;
					}
					
					//組裝數(shù)據(jù)格式
				  sprintf(onenet_http_cmd,"{"lon":%f,"lat":%f}",Longitude,latitude);
			    data_stream[0].dataPoint=onenet_http_cmd; //賦值GPS數(shù)據(jù)
			 
          //向云端發(fā)送數(shù)據(jù)流
          OneNet_SendData(FORMAT_TYPE1,DEVID,API_KEY,data_stream,1);
		 }
		
		 /*實(shí)時接收MC20收到的數(shù)據(jù),進(jìn)行解析*/
     if(USART2_RX_FLAG)
     {
         USART2_RX_BUFF[USART2_RX_CNT]='?';
				  printf("USART2_RX_BUFF=%srn",USART2_RX_BUFF); //向串口打印信息
			   //解析平臺返回的數(shù)據(jù)
         OneNet_RevPro(USART2_RX_BUFF);
         USART2_RX_CNT=0;
         USART2_RX_FLAG=0;
         memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
     }
	}
}

4.2? mc20.c

#include "mc20.h"
/*
函數(shù)功能:向MC20模塊發(fā)送指令
函數(shù)參數(shù):
				char *cmd  發(fā)送的命令
			  char *check_data 檢測返回的數(shù)據(jù)
返回值: 0表示成功 1表示失敗
*/
u8 MC20_SendCmd(char *cmd,char *check_data)
{
   u16 i,j;
   for(i=0;i<5;i++) //測試的總次數(shù)
   {
      USART2_RX_FLAG=0;
      USART2_RX_CNT=0;
			memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));
			USART_X_SendString(USART2,cmd); //發(fā)送指令
      for(j=0;j<500;j++) //等待的時間(ms單位)
      {
          if(USART2_RX_FLAG)
          {
              USART2_RX_BUFF[USART2_RX_CNT]='?';
              if(strstr((char*)USART2_RX_BUFF,check_data))
              {
                  return 0;
              }
              else break;
          }
          delay_ms(10); //一次的時間
      }
   }
   return 1;
}


/*
函數(shù)功能:  MC20初始化檢查
*/
u8 MC20_InitCheck(void)
{
		return MC20_SendCmd("ATrn","OKrn");
}


/*
函數(shù)功能: 開啟GPS功能
返 回 值:0表示成功  1表示失敗
*/
u8 MC20_StartGPS(void)
{
		//先判斷GPS功能是否啟動
		if(MC20_SendCmd("AT+QGNSSC?rn","+QGNSSC: 1")) 
		{
				//沒有啟動就啟動GPS功能
				if(MC20_SendCmd("AT+QGNSSC=1rn","OKrn"))
				{
						return 1;  //GPS功能啟動失敗
				}
		}
		return 0;
}


/*
函數(shù)功能:從buf里面得到第cnt個逗號所在的位置
返 回 值:0~254,代表逗號所在位置的偏移.
255,代表不存在第cnt個逗號
*/
u8 GPS_GetCommaOffset(char *buf,u8 cnt)
{
	char *p=buf;
	while(cnt)
	{
		if(*buf=='*'||*buf<' '||*buf>'z')return 255;//遇到'*'或者非法字符,則不存在第cx個逗號
		if(*buf==',')cnt--;
		buf++;
	}
	return buf-p; //計(jì)算偏移量
}


/*
函數(shù)功能: 獲取GPS經(jīng)緯度數(shù)據(jù)值
函數(shù)參數(shù):
        double *Longitude  :經(jīng)度
        double *latitude   :緯度
返回值: 0表示定位成功,1表示定位失敗

說明: 解析$GNRMC命令,得到經(jīng)緯度
$GNRMC,023705.000,A,2842.4164,N,11549.5713,E,1.73,91.65,150319,,,A*41

轉(zhuǎn)換公式示例:
經(jīng)度: dddmm.mmmm 東經(jīng) 11408.4790 114+(08.4790/60)=114.141317
緯度: ddmm.mmmm 北緯 2236.9453 22+(36.9453/60)= 22.615755
*/
u8 GPS_GNRMC_Decoding(char *gps_buffer,double *Longitude,double *latitude)
{
    u8 Offset;
    u32 int_data;
    double s_Longitude,s_latitude;
    char *p;

    /*1. 確定下定位是否成功*/
    p=strstr(gps_buffer,"$GNRMC");
    if(!p)return 1;
    
    Offset=GPS_GetCommaOffset(p,2);
    if(Offset==255)return 2;
    if(*(p+Offset)!='A')return 3; //定位不準(zhǔn)確
    
    /*2. 得到緯度*/
    Offset=GPS_GetCommaOffset(p,3);
    if(Offset==255)return 4;
    sscanf(p+Offset,"%lf",&s_latitude);
    s_latitude=s_latitude/100;
    int_data=s_latitude;//得到緯度整數(shù)部分
    s_latitude=s_latitude-int_data;//得到緯度小數(shù)部分
    s_latitude=(s_latitude)*100;
    *latitude=int_data+(s_latitude/60.0); //得到轉(zhuǎn)換后的值
    
		/*3. 得到經(jīng)度*/
    Offset=GPS_GetCommaOffset(p,5);
    if(Offset==255)return 5;
    sscanf(p+Offset,"%lf",&s_Longitude);    
    s_Longitude=s_Longitude/100;
    int_data=s_Longitude;//得到經(jīng)度整數(shù)部分
    s_Longitude=s_Longitude-int_data; //得到經(jīng)度小數(shù)部分
    s_Longitude=s_Longitude*100;
    *Longitude=int_data+(s_Longitude/60.0);   
    return 0;
}


/*
函數(shù)功能: 獲取一次GPS經(jīng)緯度數(shù)據(jù)
函數(shù)參數(shù):
        double *Longitude  :經(jīng)度
        double *latitude   :緯度
返回值: 0表示定位成功,1表示數(shù)據(jù)接收失敗,2表示定位失敗
*/
u8 MC20_GetGPS_Data(double *Longitude,double *latitude)
{
		/*1. 發(fā)送獲取GPS數(shù)據(jù)的指令*/
		if(MC20_SendCmd("AT+QGNSSRD="NMEA/RMC"rn", "OKrn"))return 1;
		
		/*2. 對GPS數(shù)據(jù)進(jìn)行解碼*/
		if(GPS_GNRMC_Decoding((char *)USART2_RX_BUFF,Longitude,latitude))return 2;
		
		//解碼成功
		return 0; 
}

/*
函數(shù)功能: 連接服務(wù)器
函數(shù)參數(shù):
        char *server_ip  服務(wù)器IP地址  
				u16 port  服務(wù)器端口號
返回值: 0表示連接成功,1表示連接失敗
*/
u8 MC20_Connect_TCP_Server(char *server_ip,u16 port)
{
		 char send_buf[100]={0};
		 sprintf(send_buf,"AT+QIOPEN="TCP","%s","%d"rn",server_ip,port);
		 
		 //連接至服務(wù)器
		 if(MC20_SendCmd(send_buf, "CONNECT"))
		 {
				return 1; //連接失敗
		 }
		 return 0; //連接成功
}


/*
函數(shù)功能: 向服務(wù)器發(fā)送數(shù)據(jù)
函數(shù)參數(shù): 
					u8 *buffer 發(fā)送的數(shù)據(jù)
					u32 len  發(fā)送的長度
返 回 值: 0表示發(fā)送成功,1表示準(zhǔn)備發(fā)送失敗,2表示數(shù)據(jù)發(fā)送失敗
*/
u8 MC20_ClientSendData(u8 *buffer,u32 len)
{
	  char send_buf[2];
	  /*1. 準(zhǔn)備發(fā)送數(shù)據(jù)*/
		if(MC20_SendCmd("AT+QISENDrn",">"))
		{
				printf("AT+QISEND->ERROR Info:%srn",USART2_RX_BUFF);
				return 1; 
		}
		
		/*2. 開始發(fā)送數(shù)據(jù)*/
		USART_X_SendData(USART2,buffer,len);
		delay_ms(20);
		
		/*3. 發(fā)送結(jié)束符*/
		send_buf[0] = 0x1a;
		send_buf[1] = '?';
		if(MC20_SendCmd(send_buf,"OKrn"))
		{
				printf("發(fā)送結(jié)束符->ERROR Info:%srn",USART2_RX_BUFF);
				return 2;
		}
		return 0;
}


/*
函數(shù)功能: MC20初始化檢查并連接至服務(wù)器 
*/
#include "led.h"
void MC20_InitConnect(char *server_ip,u16 port)
{
	/*1. MC20模塊初始化檢查*/
	while(MC20_InitCheck())
	{
			LED1=!LED1;
			printf("ERROR:MC20模塊初始化檢查失敗!rn");
			delay_ms(100);
	}
	printf("1. MC20模塊初始化成功!rn");
	delay_ms(100);
	
	/*2. 查詢是否有PIN碼鎖定*/
	while(MC20_SendCmd("AT+CPIN?rn","READY"))
	{
			LED1=!LED1;
			printf("ERROR:PIN碼鎖定檢查失敗!rn");
			delay_ms(100);
	}
	printf("2. PIN碼鎖定檢查成功!rn");
	delay_ms(100);
	
	/*3. 查詢SIM卡網(wǎng)絡(luò)注冊信息*/
	if(MC20_SendCmd("AT+CREG?rn",",1"))	//本地SIM卡
	{
			if(MC20_SendCmd("AT+CREG?rn",",5"))//漫游SIM卡
			{
					printf("ERROR:查詢SIM卡網(wǎng)絡(luò)注冊信息失敗!n");
			}
			else	printf("3. 漫游SIM卡網(wǎng)絡(luò)注冊成功!n");
	}
	else	printf("3. 本地SIM卡網(wǎng)絡(luò)注冊成功!n");
	delay_ms(100);
	
	/*4. 啟動GPS功能*/
	if(MC20_StartGPS())
	{
			printf("ERROR:GPS功能啟動失敗!n");
	}
	else printf("4. GPS功能啟動成功!n");
	delay_ms(100);
	
	/*5. 連接指定服務(wù)器*/
	while(MC20_Connect_TCP_Server(server_ip,port))
	{
			printf("ERROR: 連接TCP服務(wù)器失敗!rn現(xiàn)在正在斷開服務(wù)器,進(jìn)行重連!rn需要保證服務(wù)器地址正確,并且SIM卡可以上網(wǎng)rn");
		
			/*先斷開服務(wù)器連接 (如果之前沒有連接過服務(wù)器,這里就會出現(xiàn)錯誤)*/
			MC20_SendCmd("AT+QICLOSErn","OKrn");
			delay_ms(100);
			
			MC20_SendCmd("AT+QIDEACTrn","OKrn");
			delay_ms(100);
	}
	printf("5. 連接TCP服務(wù)器成功!n");
	delay_ms(100);
}

4.2 mc20.h

#ifndef  _MC20_H
#define  _MC20_H
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"
#include <string.h>
u8 MC20_SendCmd(char *cmd,char *check_data);
u8 MC20_InitCheck(void);
u8 MC20_StartGPS(void);
u8 MC20_GetGPS_Data(double *Longitude,double *latitude);
u8 MC20_Connect_TCP_Server(char *server_ip,u16 port);
u8 MC20_ClientSendData(u8 *buffer,u32 len);


void MC20_InitConnect(char *server_ip,u16 port);
#endif

五、OneNet創(chuàng)建產(chǎn)品

鏈接地址:??https://open.iot.10086.cn/develop/global/product/#/console

  • 更多詳細(xì)資料請聯(lián)系.docx
    下載
意法半導(dǎo)體

意法半導(dǎo)體

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車用集成電路領(lǐng)域居世界前列.

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車用集成電路領(lǐng)域居世界前列.收起

查看更多

相關(guān)推薦