一、环境介绍

MCU:  STM32F103C8T6

GSM模块: 移远MC20 (MT2503D)(GSM+GPS共存)功能很强大

开发软件: Keil5

MQTT协议采用OneNet的旧版协议,登录OneNet控制台创建应用时要选择旧版本。

如果想使用新版本的标准MQTT协议连接OnetNet请参考这里:  https://blog.csdn.net/xiaolong1126626497/article/details/107385118

完整源代码下载:  https://download.csdn.net/download/xiaolong1126626497/18245206

二、MC20模块

MC20模块采用联发科技最新推出的多功能通信定位芯片研制而成。它是一款集成LCC封装、四频段GSM/GPRS和先进算法GNSS引擎于一体的全功能通信模块,具有超小体积、低功耗、双卡单待等优势。MC20不仅内嵌丰富的网络协议(如 TCP、UDP、PPP、FTP、HTTP以及SSL),还集成了多星座卫星系统(如北斗、GPS、QZSS),因此能提供无线移动通信以及精准的导航定位功能。

除具备GSM/GPRS无线通信功能外,MC20模块还支持先进的GNSS技术。它集成了EPOTM(用户无需自设服务器,直接从MTK服务器获取EPO数据)、秒定等技术,能够实现快速首次定位。由于支持北斗、GPS、QZSS等多星座卫星系统解调算法,其定位更加精准,抗多路径干扰能力更强,比传统GPS模块具有更多优势。另外,MC20模块中内置LNA和低功耗算法:前者使其接收灵敏度提升至-149dBm;后者使其在低功耗模式(GLP Mode)下的耗流仅为正常工作模式的40%。

MC20模块较传统GSM+GNSS方案体积减少40%,使其在各种应用中占具更大优势。其主要应用领域为:可穿戴设备(智能手表)、宠物追踪、财产追踪及行车记录仪等等。
主要优势
● 超小体积: 18.7mm × 16.0mm × 2.1mm
● 多卫星导航系统: GPS/BeiDou/QZSS
● GNSS 接收机通道: 99 路捕获通道/33 路跟踪通道
● 支持多种 AGPS 技术,如 EASYTM 、EPOTM 、秒定等
● 内置 LNA 大大提升 GNSS 接收机灵敏度(-167dBm@跟踪模式):可使用无源 GNSS 天线而无需任何外部低噪声放大器
● 支持增强型 GNSS 功能,如 SDK 命令、LOCUSTM 、AIC 和 GLP
● 多功能四频段 GSM模块: 850/900/1800/1900MHz
● 内嵌丰富网络协议: TCP/UDP/PPP/HTTP/FTP/SSL
● 支持语音、短信、QuecFOTATM 、双卡单待以及 OpenCPU 功能
● 支持蓝牙 V3.0 以及 SPP & HFP-AG 配置文件

三、代码功能

使用STM32F103C8T6 通过串口+AT指令控制MC20模块+MQTT协议,登录OneNet服务器上传GPS数据,LED控制(网页按钮控制开发板上的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"//网络协议层
#include "onenet.h"//协议封装文件
#include "dStream.h"//产品ID
char PROID[]="231174";//鉴权信息
char AUTH_INFO[]="1234567890";//设备ID
char DEVID[]="523369555";//API KEY
char API_KEY[]="k6vtrrEd1H7UMddiF3DzripS47w=";//缓冲区
char onenet_http_cmd[1024];//服务器IP地址
#define TCP_SERVER_IP_ADDR "183.230.40.39"//服务器端口号
#define TCP_SERVER_PORT 6002//数据流结构
DATA_STREAM data_stream[1]=
{{"gps","88.88",TYPE_JSON,1},
};/*STM32开发板接线说明:STM32                   MC203.3V    ------>  V_IOGND     <----->   GNDPA3      <------  GSM_TXPA2       ------>  GSM_RX
*/int main()
{   u32 time_cnt=0;u32 cnt=0;double Longitude; //经度double latitude;  //纬度LED_Init();BEEP_Init();USART_X_Init(USART1,72,115200);TIM2_Init(72,20000);                   //辅助串口2接收,超时时间为20msUSART_X_Init(USART2,36,9600); //连接着MC20(GPS+GPRS)printf("串口准备就绪.....\r\n");DelayMs(500);printf("程序修改时间: %s\r\n",__TIME__);while(1){u8 stat;/*初始化MC20,并连接到指定服务器*/MC20_InitConnect(TCP_SERVER_IP_ADDR,TCP_SERVER_PORT);/*登录OneNET服务器,上线设备*/stat=OneNet_DevLink();if(stat)printf("ERROR:%d,接入OneNET失败:%d\r\n",stat,cnt++);else break; //登录成功LED1=!LED1;delay_ms(200); break;//失败也退出继续运行下面代码}printf("6. OneNET服务器登录成功!\r\n");delay_ms(100);while(1){ /*6. 向OneNet服务器5秒发送一次数据*/time_cnt++;DelayMs(1);if(time_cnt>=5000){time_cnt=0;/*获取一次GPS输出的经纬度信息*/switch(MC20_GetGPS_Data(&Longitude,&latitude)){case 0: printf("经度:%f,纬度:%f\r\n",Longitude,latitude); break;case 1: printf("ERROR:GPS数据接收失败!\r\n"); break;case 2: printf("ERROR:GPS定位数据解码失败!<请将GPS拿到空旷位置定位>\r\n"); break;}//组装数据格式sprintf(onenet_http_cmd,"{\"lon\":%f,\"lat\":%f}",Longitude,latitude);data_stream[0].dataPoint=onenet_http_cmd; //赋值GPS数据//向云端发送数据流OneNet_SendData(FORMAT_TYPE1,DEVID,API_KEY,data_stream,1);}/*实时接收MC20收到的数据,进行解析*/if(USART2_RX_FLAG){USART2_RX_BUFF[USART2_RX_CNT]='\0';printf("USART2_RX_BUFF=%s\r\n",USART2_RX_BUFF); //向串口打印信息//解析平台返回的数据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"
/*
函数功能:向MC20模块发送指令
函数参数:char *cmd  发送的命令char *check_data 检测返回的数据
返回值: 0表示成功 1表示失败
*/
u8 MC20_SendCmd(char *cmd,char *check_data)
{u16 i,j;for(i=0;i<5;i++) //测试的总次数{USART2_RX_FLAG=0;USART2_RX_CNT=0;memset(USART2_RX_BUFF,0,sizeof(USART2_RX_BUFF));USART_X_SendString(USART2,cmd); //发送指令for(j=0;j<500;j++) //等待的时间(ms单位){if(USART2_RX_FLAG){USART2_RX_BUFF[USART2_RX_CNT]='\0';if(strstr((char*)USART2_RX_BUFF,check_data)){return 0;}else break;}delay_ms(10); //一次的时间}}return 1;
}/*
函数功能:  MC20初始化检查
*/
u8 MC20_InitCheck(void)
{return MC20_SendCmd("AT\r\n","OK\r\n");
}/*
函数功能: 开启GPS功能
返 回 值:0表示成功  1表示失败
*/
u8 MC20_StartGPS(void)
{//先判断GPS功能是否启动if(MC20_SendCmd("AT+QGNSSC?\r\n","+QGNSSC: 1")) {//没有启动就启动GPS功能if(MC20_SendCmd("AT+QGNSSC=1\r\n","OK\r\n")){return 1;  //GPS功能启动失败}}return 0;
}/*
函数功能:从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; //计算偏移量
}/*
函数功能: 获取GPS经纬度数据值
函数参数:double *Longitude  :经度double *latitude   :纬度
返回值: 0表示定位成功,1表示定位失败说明: 解析$GNRMC命令,得到经纬度
$GNRMC,023705.000,A,2842.4164,N,11549.5713,E,1.73,91.65,150319,,,A*41转换公式示例:
经度: dddmm.mmmm 东经 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; //定位不准确/*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;//得到纬度整数部分s_latitude=s_latitude-int_data;//得到纬度小数部分s_latitude=(s_latitude)*100;*latitude=int_data+(s_latitude/60.0); //得到转换后的值/*3. 得到经度*/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;//得到经度整数部分s_Longitude=s_Longitude-int_data; //得到经度小数部分s_Longitude=s_Longitude*100;*Longitude=int_data+(s_Longitude/60.0);   return 0;
}/*
函数功能: 获取一次GPS经纬度数据
函数参数:double *Longitude  :经度double *latitude   :纬度
返回值: 0表示定位成功,1表示数据接收失败,2表示定位失败
*/
u8 MC20_GetGPS_Data(double *Longitude,double *latitude)
{/*1. 发送获取GPS数据的指令*/if(MC20_SendCmd("AT+QGNSSRD=\"NMEA/RMC\"\r\n", "OK\r\n"))return 1;/*2. 对GPS数据进行解码*/if(GPS_GNRMC_Decoding((char *)USART2_RX_BUFF,Longitude,latitude))return 2;//解码成功return 0;
}/*
函数功能: 连接服务器
函数参数:char *server_ip  服务器IP地址  u16 port  服务器端口号
返回值: 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\"\r\n",server_ip,port);//连接至服务器if(MC20_SendCmd(send_buf, "CONNECT")){return 1; //连接失败}return 0; //连接成功
}/*
函数功能: 向服务器发送数据
函数参数: u8 *buffer 发送的数据u32 len  发送的长度
返 回 值: 0表示发送成功,1表示准备发送失败,2表示数据发送失败
*/
u8 MC20_ClientSendData(u8 *buffer,u32 len)
{char send_buf[2];/*1. 准备发送数据*/if(MC20_SendCmd("AT+QISEND\r\n",">")){printf("AT+QISEND->ERROR Info:%s\r\n",USART2_RX_BUFF);return 1; }/*2. 开始发送数据*/USART_X_SendData(USART2,buffer,len);delay_ms(20);/*3. 发送结束符*/send_buf[0] = 0x1a;send_buf[1] = '\0';if(MC20_SendCmd(send_buf,"OK\r\n")){printf("发送结束符->ERROR Info:%s\r\n",USART2_RX_BUFF);return 2;}return 0;
}/*
函数功能: MC20初始化检查并连接至服务器
*/
#include "led.h"
void MC20_InitConnect(char *server_ip,u16 port)
{/*1. MC20模块初始化检查*/while(MC20_InitCheck()){LED1=!LED1;printf("ERROR:MC20模块初始化检查失败!\r\n");delay_ms(100);}printf("1. MC20模块初始化成功!\r\n");delay_ms(100);/*2. 查询是否有PIN码锁定*/while(MC20_SendCmd("AT+CPIN?\r\n","READY")){LED1=!LED1;printf("ERROR:PIN码锁定检查失败!\r\n");delay_ms(100);}printf("2. PIN码锁定检查成功!\r\n");delay_ms(100);/*3. 查询SIM卡网络注册信息*/if(MC20_SendCmd("AT+CREG?\r\n",",1")) //本地SIM卡{if(MC20_SendCmd("AT+CREG?\r\n",",5"))//漫游SIM卡{printf("ERROR:查询SIM卡网络注册信息失败!\n");}else   printf("3. 漫游SIM卡网络注册成功!\n");}else    printf("3. 本地SIM卡网络注册成功!\n");delay_ms(100);/*4. 启动GPS功能*/if(MC20_StartGPS()){printf("ERROR:GPS功能启动失败!\n");}else printf("4. GPS功能启动成功!\n");delay_ms(100);/*5. 连接指定服务器*/while(MC20_Connect_TCP_Server(server_ip,port)){printf("ERROR: 连接TCP服务器失败!\r\n现在正在断开服务器,进行重连!\r\n需要保证服务器地址正确,并且SIM卡可以上网\r\n");/*先断开服务器连接 (如果之前没有连接过服务器,这里就会出现错误)*/MC20_SendCmd("AT+QICLOSE\r\n","OK\r\n");delay_ms(100);MC20_SendCmd("AT+QIDEACT\r\n","OK\r\n");delay_ms(100);}printf("5. 连接TCP服务器成功!\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创建产品

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

STM32+移远MC20模块采用MQTT协议登录OneNet上传GPS数据相关推荐

  1. STM32+果云GA6-GPRS/GSM模块+MQTT+HTTP协议连接中移OneNet上传GPS数据定位

    一.环境介绍 MCU:  STM32F103C8T6 GSM模块: GA6--果云 开发软件: Keil5 完整源码下载:  https://download.csdn.net/download/xi ...

  2. 52单片机连接ESP8266烧入固件使用MQTT协议将温湿度上传至OneNET云平台

    52单片机连接ESP8266烧入固件使用MQTT协议连接OneNET云平台 参考: ---------------------------------------------------------- ...

  3. ESP32-C3通过MQTT协议把温湿度上传到阿里云物联网平台

    最近本来想实现微信小程序通过OneNet平台控制灯开关的,没想到微信小程序代码都写好接口了,才发现onenet想下发命令的应用管理得要钱了,秉承白嫖绝不白给的精神,毅然决然的转用阿里云平台. 文章目录 ...

  4. stm32 m5311上传gps数据上onenet云平台实现地图定位

    新手,第一次写博客,如有不足请大家见谅并指出.下面开始正文. 本文是帮一个朋友做一个NB_Iot的小东西这个过程的学习记录吧. NB模块是M5311,然后还有一个stm32f103的最小系统开发板,后 ...

  5. SIM800C连接OneNet平台HTTP协议上传GPS数据

    1. 前言 科技进步不断推动新产品的出现,越来越多的电子产品开始着力解决社会焦点问题,随着城市发展以及人口流动性的增加,儿童户外被拐,老人外出走丢,交通工具被盗和大型物件丢失等问题变样严重起来,因此, ...

  6. stm32+mc20上传gps信息至onenet 可路径显示

    开发环境: 芯片: STM32F103C8T6 GSM模块: 移远MC20 开发软件: Keil5 协议 :多协议接入--TCP透传 手机端显示图像 使用STM32F103C8T6 通过串口+AT指令 ...

  7. 物联网-移远M26模块MQTT开发(AT命令)

    MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分.该协议支持所有平台,几乎可以把所有联 ...

  8. NBIOT(3)---NBIOT 移远BC28模块+stm32

    NBIOT 移远BC28模块+stm32 大白为了开发者能够快速入门BC28的开发,加快开发者的项目进度,大白开发出此款针对BC28的stm32开发板和完善的发送网络数据的示例程序(TCP协议.COA ...

  9. 中移ML302模组通过MQTT协议接入oneNT平台

    @中移ML302模组通过MQTT协议接入oneNT平台 ML302 是中国移动最新推出的 LTE Cat.1 模块. 丰富的 Internet 协议.行业标准接口和功能,支持 Windows.Linu ...

最新文章

  1. 2021年Java后端技术知识体系
  2. vue-cli4入门
  3. vue项目实现列表页-详情页返回不刷新,再点其他菜单项返回刷新的需求
  4. [转]被当做狗和鸡来驱赶的百姓
  5. Vuejs 条件判断
  6. Javaweb之session创建销毁问题
  7. linux服务器拓扑图,Linux服务器作为网关的DNS分离解析服务(CentOS 7版本)
  8. shell 编程基础
  9. Android基础知识之智能指针:强指针和弱指针
  10. day 69 orm操作之表关系,多对多,多对一(wusir总结官网的API)
  11. Python游戏开发入门3 Pygame屏幕绘制机制
  12. 迅通雾霾处理技术为清晰都市保驾护航
  13. angular中$cacheFactory用法(缓存)
  14. 在xp中不能查看或更改文件夹的“只读”属性或“系统”属性解决方法
  15. 模拟量的输入和输出问题及选型
  16. 哪些行业适合开发小程序商城
  17. P3975 [TJOI2015]弦论 - 后缀自动机(SAM)
  18. RPG Maker MV之起始队伍设置
  19. js去掉最后一个逗号
  20. Excel 单元格中插入附件

热门文章

  1. Neutron升级规划
  2. postfix邮件服务器搭建02-安装篇
  3. colab + cuda
  4. 7.6 观察者模式(Observer Pattern)
  5. 数据库审计和日志审计的三大区别分析
  6. 如何把获取的JSON数据插入到MySQL中
  7. touch pro2 T7373 直刷 安卓2.2
  8. 2023美赛ICM F题 详细思路
  9. PAT(Advanced) 1007 Maximum Subsequence Sum (25)
  10. 基于位置的服务(简介)