STM32

您所在的位置:网站首页 gps模块与单片机链接视频教程 STM32

STM32

2024-03-22 03:22| 来源: 网络整理| 查看: 265

模块介绍

ATGM336H定位模块支持GPS系统,BDS(北斗)系统,GLONASS(俄罗斯)系统,伽利略卫星导航系统(欧盟)。这个模块要拿到室外才能接收到信号,且初次初始化或者隔太久时间没有启用会导致获取定位信息的时间很长。 请添加图片描述 可以使用中科微电子提供的集成软件设置模块,可以设置串口输出的参数,波特率等等参数。 本文介绍用STM32串口接收定位模块的数据,并将数据进行解析,解析后得到经纬度的原始数据,把经纬度原始数据转换成精确的经纬度信息后存放到数组里,可打印或继续串口传输到其他设备,后面会介绍传输到ESP32,并保存到SPIFFS中。 请添加图片描述上图是模块通过串口向上位机输出的数据帧样例。

通过GNSS工具可以看到模块能够获取的数据帧有如下格式。 请添加图片描述 请添加图片描述其中RMC数据是最简定位信息,得到这串数据后,可以将GNRMC开始的前六项数据提取,分别是UTC时间,数据有效标志位,纬度,纬度方向,经度,经度方向。此时的经度和纬度只是原始数据,需要再转换为精确数据。

RMC的数据样例为 $GNRMC,123211.000,A,2295.33602,N,11326.27041,E,3.21,217.19,100722,,,A*7A 程序思路

数据转换: 2322.74250 格式:ddmm.mmmmm 11326.27041 格式:ddmm.mmmmm 转换成北纬:23 + 22.74250 / 60 = 23.37904 转换成东经:113 + 26.27041 / 60 = 113.43784 比较不准。。串口输出的数据就是这样的,估计芯片哪里出了问题。。 读取数据可以先用一个缓存数组接收所有的数据,先判断是不是$GNRMC开头的数据帧,如果是的话则逐个字符接收,因为数据帧是以换行符为结尾的,当读取到’\n’则是数据帧的结尾。 定义几个字符数组,用于分别存放UTC时间,经度和纬度的原始数组,经度和纬度的方向。 以逗号为分隔符切割字符串,这里我们需要用到strstr这个函数。 在这里插入图片描述 返回指向str1中第一次出现str2的位置的指针,当str1中没有str2则返回空指针。我们可以定义一个子串指针,用这个函数在数据帧中找逗号,再用memcpy函数把数据分割后存在相应的数组。

#include "ATGM336H.h" #include "string.h" #define GPS_Buffer_Length 80 #define UTCTime_Length 11 #define latitude_Length 11 #define N_S_Length 2 #define longitude_Length 12 #define E_W_Length 2 char USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. typedef struct SaveData { char GPS_Buffer[GPS_Buffer_Length]; char isGetData; //数据获取完成标志位 char isParseData; //解析完成标志位 char UTCTime[UTCTime_Length]; //UTC时间 char latitude[latitude_Length]; //纬度 char N_S[N_S_Length]; //N/S char longitude[longitude_Length]; //经度 char E_W[E_W_Length]; //E/W char isUsefull; //信息有效标志位 }GNRMC;

首先定义一个结构体存放几个数组,并宏定义数组的长度。

void ATGM_StructInit() { GNRMC_Info.isGetData = false; GNRMC_Info.isParseData = false; GNRMC_Info.isUsefull = false; memset(GNRMC_Info.GPS_Buffer, 0, GPS_Buffer_Length); memset(GNRMC_Info.UTCTime, 0, UTCTime_Length); memset(GNRMC_Info.latitude, 0, latitude_Length); memset(GNRMC_Info.N_S, 0, N_S_Length); memset(GNRMC_Info.longitude, 0, longitude_Length); memset(GNRMC_Info.E_W, 0, E_W_Length); }

首先初始化结构体,先把结构体成员内容全部置零。

void ATGM336H_Init() { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; USART_InitTypeDef USART_InitStructure; ATGM_StructInit(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //USART1_TX PA.9 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX PA.10 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); //配置中断通道 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ;//优先级最低 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); ClrBuf(); //初始化 }

之后配置引脚,配置串口1中断,配置串口。引脚TX我选择PA9,RX选择PA10。TX要选择复用推挽输出,RX选择浮空输入。之后开通NVIC中断通道,配置串口波特率为9600,8位数据位,1位停止位,吴娇艳,无硬件流控制,模式为收发模式,因为我既要接收定位数据,也要打印或发送数据。最后别忘记使能中断和串口。

unsigned int DataIndex = 0; void USART1_IRQHandler() { unsigned char receive; if(USART_GetITStatus(USART1, USART_IT_RXNE) == 1) { receive = USART_ReceiveData(USART1); //读取接收到的数据 if(receive == '$') DataIndex = 0; USART_RX_BUF[DataIndex++] = receive; //GNRMC\GPRMC if(USART_RX_BUF[0] == '$' && USART_RX_BUF[4] == 'M' && USART_RX_BUF[5] == 'C') { if(receive == '\n') { memset(GNRMC_Info.GPS_Buffer, 0, GPS_Buffer_Length); //清空 memcpy(GNRMC_Info.GPS_Buffer, USART_RX_BUF, DataIndex); //保存数据 GNRMC_Info.isGetData = true; DataIndex = 0; memset(USART_RX_BUF, 0, USART_REC_LEN); //清空 } } } }

先是定义一个DataIndex作为数组的下标,当读到了$标志表示数据帧开始,将下标置零,之后判断是不是我们要读取的这种格式,如果是则读到’\n’,即把数据转而存储到GPS_Buffer中,并把数据读取标志位置为true。

void ParseGps() { char *subString; char *subStringNext; char i = 0; if (GNRMC_Info.isGetData) { GNRMC_Info.isGetData = false; // printf("\r\n"); // printf(GNRMC_Info.GPS_Buffer); //截取数据帧前六部分 |对地航速 对地航向 日期 //$GNRMC,112536.000,A,2322.75023,N,11326.28605,E,| 0.00, 0.00, 100722,,,A*78 for (i = 0 ; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3