基于上一章的介绍,本章将介绍如何基于gd32开发板使用gps定位模块。

一、官方代码分析

正点原子的官方测试例程,测试代码的逻辑还是比较简单的,主要就是先调用函数atk_mo1218_init()进行初始化,接着就调用 SkyTraq binary 协议的 API 函数来配置ATK-MO1218 模块,配置无误后,ATK-MO1218 模块便会根据配置的测量频率不断的输出数据,接下来就调用函数 atk_mo1218_update()来获取 ATK-MO1218 模块输出的各个数据信息,然后打印至串口调试助手。

void demo_run(void)
{uint8_t ret;//初始化ret = atk_mo1218_init(38400);if (ret != 0){printf("ATK-MO1218 init failed!\r\n");while (1){LED0_TOGGLE();delay_ms(200);}}//配置ret  = atk_mo1218_factory_reset(ATK_MO1218_FACTORY_RESET_REBOOT);ret += atk_mo1218_config_output_type(ATK_MO1218_OUTPUT_NMEA, ATK_MO1218_SAVE_SRAM_FLASH);ret += atk_mo1218_config_nmea_msg(1, 1, 1, 1, 1, 1, 0, ATK_MO1218_SAVE_SRAM_FLASH);ret += atk_mo1218_config_position_rate(ATK_MO1218_POSITION_RATE_5HZ, ATK_MO1218_SAVE_SRAM_FLASH);ret += atk_mo1218_config_gnss_for_navigation(ATK_MO1218_GNSS_GPS_BEIDOU, ATK_MO1218_SAVE_SRAM_FLASH);if (ret != 0){printf("ATK-MO1218 configure failed!\r\n");while (1){LED0_TOGGLE();delay_ms(200);}}while (1){uint8_t ret;atk_mo1218_time_t utc;atk_mo1218_position_t position;int16_t altitude;uint16_t speed;atk_mo1218_fix_info_t fix_info;atk_mo1218_visible_satellite_info_t gps_satellite_info = {0};atk_mo1218_visible_satellite_info_t beidou_satellite_info = {0};uint8_t satellite_index;while (1){//获取 ATK-MO1218 模块输出的各个数据信息ret = atk_mo1218_update(&utc, &position, &altitude, &speed, &fix_info, NULL, NULL, 5000);if (ret == ATK_MO1218_EOK){/* UTC */printf("UTC Time: %04d-%02d-%02d %02d:%02d:%02d.%03d\r\n", utc.year, utc.month, utc.day, utc.hour, utc.minute, utc.second, utc.millisecond);//经纬度 (放大了100000)printf("Position: %d.%d'%s %d.%d'%s\r\n", position.longitude.degree / 100000, position.longitude.degree % 100000, (position.longitude.indicator == ATK_MO1218_LONGITUDE_EAST) ? "E" : "W", position.latitude.degree / 100000, position.latitude.degree % 100000, (position.latitude.indicator == ATK_MO1218_LATITUDE_NORTH) ? "N" : "S");//海拔高度 (放大了10)printf("Altitude: %d.%dm\r\n", altitude / 10, altitude % 10);// 速度(放大了10)printf("Speed: %d.%dKm/H\r\n", speed / 10, speed % 10);//定位质量printf("Fix quality: %s\r\n", (fix_info.quality == ATK_MO1218_GPS_UNAVAILABLE) ? "Unavailable" : ((fix_info.quality == ATK_MO1218_GPS_VALID_SPS) ? "SPS mode" : "differential GPS mode"));//用于定位的卫星数量printf("Satellites Used: %d\r\n", fix_info.satellite_num);//定位方式printf("Fix type: %s\r\n", (fix_info.type == ATK_MO1218_FIX_NOT_AVAILABLE) ? "Unavailable" : ((fix_info.type == ATK_MO1218_FIX_2D) ? "2D" : "3D"));//用于定位的卫星编号for (satellite_index=0; satellite_index<fix_info.satellite_num; satellite_index++){if (satellite_index == 0){printf("Satellite ID:");}printf(" %d", fix_info.satellite_id[satellite_index]);if (satellite_index == fix_info.satellite_num - 1){printf("\r\n");}}//位置、水平、垂直精度因子(放大了10)printf("PDOP: %d.%d\r\n", fix_info.pdop / 10, fix_info.pdop % 10);printf("HDOP: %d.%d\r\n", fix_info.hdop / 10, fix_info.hdop % 10);printf("VDOP: %d.%d\r\n", fix_info.vdop / 10, fix_info.vdop % 10);//可见的gps,北斗卫星数量printf("Number of GPS visible satellite: %d\r\n", gps_satellite_info.satellite_num);printf("Number of Beidou visible satellite: %d\r\n", beidou_satellite_info.satellite_num);printf("\r\n");}else{//ATK-MO1218模块未定位时,不输出NMEA协议的GSV语句,//导致因获取不到可见GPS、北斗卫星的信息而超时失败,//此时可将函数atk_mo1218_update()的入参gps_satellite_info和beidou_satellite_info传入NULL,//从而获取未定位时的其它数据printf("Error!\r\n");}delay_ms(1000);}}
}

值得一提的是,由于 ATK-MO1218 模块通过 UART 发送给主控芯片的数据的长度是不固定的,因此主控芯片就无法直接通过接收到数据的长度来判断 ATK-MO1218 模块传来的一帧数据是否完成。对于这种通过 UART 接收不定长数据的情况,可以通过 UART 总线是否空闲来判断一帧的传输是否完成,恰巧 STM32 的 UART 提供了总线空闲中断功能,因此可以开启 UART 的总线空闲中断,并在中断中做相应的处理。

void ATK_MO1218_UART_IRQHandler(void)
{uint8_t tmp;if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_ORE) != RESET)       {__HAL_UART_CLEAR_OREFLAG(&g_uart_handle);                           (void)g_uart_handle.Instance->SR;                                   (void)g_uart_handle.Instance->DR;}if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_RXNE) != RESET)       {HAL_UART_Receive(&g_uart_handle, &tmp, 1, HAL_MAX_DELAY);           if (g_uart_rx_frame.sta.len < (ATK_MO1218_UART_RX_BUF_SIZE - 1))    {g_uart_rx_frame.buf[g_uart_rx_frame.sta.len] = tmp;            g_uart_rx_frame.sta.len++;                                      }else                                                               {g_uart_rx_frame.sta.len = 0;                                 g_uart_rx_frame.buf[g_uart_rx_frame.sta.len] = tmp;             g_uart_rx_frame.sta.len++;                                    }}if (__HAL_UART_GET_FLAG(&g_uart_handle, UART_FLAG_IDLE) != RESET)       {g_uart_rx_frame.sta.finsh = 1;                                      __HAL_UART_CLEAR_IDLEFLAG(&g_uart_handle);                          }
}

二、硬件

开发板使用GD32F450,串口使用USART5,引脚为PC6和PC7。杜邦线按设备要求进行连接即可。

使用了四根杜邦线连接到开发板的电源3.3V,GND和PC6、PC7引脚。

三、软件

NEMA协议是一种用于GPS设备的通信协议,它定义了一系列标准消息格式,用于传输GPS设备的位置、速度和时间等信息。在使用gd32进行NEMA协议解析时,可以采用以下步骤:

1、配置串口通信参数,如波特率、数据位、停止位和校验位等。

2、通过串口接收数据,每次接收到一条完整的NEMA协议消息后,进行解析。

3、解析消息头,判断消息类型和数据长度。

4、解析消息体,提取需要的位置、速度和时间等信息。

5、对解析出来的数据进行处理或者存储,以便后续使用。

需要注意的是,NEMA协议中的消息格式比较复杂,解析过程需要仔细处理各个字段的含义和数据类型,避免出现解析错误的情况。同时,由于GPS设备的数据传输速率较快,需要采用合适的缓存机制,确保数据不被丢失或者重复解析。

参考代码:

#include "gd32f30x.h"
#include <stdio.h>
#include <string.h>/* 定义串口接收缓冲区大小 */
#define RX_BUF_SIZE  128
/* 定义NEMA协议消息类型枚举 */
typedef enum {NEMA_MSG_GPGGA,   // GGA消息NEMA_MSG_GPVTG,   // VTG消息NEMA_MSG_GPGSA,   // GSA消息NEMA_MSG_GPGSV,   // GSV消息NEMA_MSG_UNKNOWN, // 未知消息
} nema_msg_type_t;
/* 定义NEMA协议消息结构体 */
typedef struct {nema_msg_type_t type;   // 消息类型uint32_t time;          // 时间float latitude;         // 纬度float longitude;        // 经度float altitude;         // 海拔高度float speed;            // 速度float course;           // 航向uint8_t num_satellites; // 卫星数
} nema_msg_t;/* 定义全局变量 */
static uint8_t rx_buf[RX_BUF_SIZE];
static uint8_t rx_index = 0;
static nema_msg_t nema_msg;/* 串口接收中断处理函数 */
void USART5_IRQHandler(void)
{if (RESET != usart_interrupt_flag_get(USART5, USART_INT_FLAG_RBNE)) {/* 读取接收数据寄存器 */uint8_t data = usart_data_receive(USART5);/* 判断是否接收到换行符 */if (data == '\n') {/* 解析NEMA协议消息 */if (0 == strncmp((const char *)rx_buf, "$GPGGA,", 7)) {/* GGA消息 */nema_msg.type = NEMA_MSG_GPGGA;/* 解析消息体 */sscanf((const char *)rx_buf, "$GPGGA,%lu,%f,%c,%f,%c,%d,%d,%f,%f,M,%f,M,,",&nema_msg.time, &nema_msg.latitude, &latitude_dir, &nema_msg.longitude,&longitude_dir, &nema_msg.fix_quality, &nema_msg.num_satellites,&nema_msg.hdop, &nema_msg.altitude, &nema_msg.geoid_sep);} else if (0 == strncmp((const char *)rx_buf, "$GPVTG,", 7)) {/* VTG消息 */nema_msg.type = NEMA_MSG_GPVTG;/* 解析消息体 */sscanf((const char *)rx_buf, "$GPVTG,%f,T,%f,M,%f,N,%f,K",&nema_msg.course, &nema_msg.course_true, &nema_msg.speed, &nema_msg.speed_knots);} else if (0 == strncmp((const char *)rx_buf, "$GPGSA,", 7)) {/* GSA消息 */nema_msg.type = NEMA_MSG_GPGSA;/* 解析消息体 */sscanf((const char *)rx_buf, "$GPGSA,%c,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%f",&nema_msg.fix_mode, &nema_msg.fix_type, &nema_msg.sat1, &nema_msg.sat2,&nema_msg.sat3, &nema_msg.sat4, &nema_msg.sat5, &nema_msg.sat6,&nema_msg.sat7, &nema_msg.pdop, &nema_msg.hdop, &nema_msg.vdop);} else if (0 == strncmp((const char *)rx_buf, "$GPGSV,", 7)) {/* GSV消息 */nema_msg.type = NEMA_MSG_GPGSV;/* 解析消息体 */sscanf((const char *)rx_buf, "$GPGSV,%d,%d,%d",&nema_msg.num_msgs, &nema_msg.msg_num, &nema_msg.num_sats);} else {/* 未知消息 */nema_msg.type = NEMA_MSG_UNKNOWN;}/* 清空接收缓冲区 */memset(rx_buf, 0, sizeof(rx_buf));rx_index = 0;} else {/* 累加接收缓冲区 */rx_buf[rx_index++] = data;}}
}int main(void)
{/* 配置串口通信参数 */usart_deinit(USART5);usart_baudrate_set(USART5, 38400);usart_word_length_set(USART5, USART_WL_8BIT);usart_stop_bit_set(USART5, USART_STB_1BIT);usart_parity_config(USART5, USART_PM_NONE);usart_receive_config(USART5, USART_RECEIVE_ENABLE);usart_interrupt_enable(USART5, USART_INT_RBNE);nvic_enable_irq(NVIC_USART5_IRQ);usart_enable(USART5);/* 解析NEMA协议消息 */while (1) {if (nema_msg.type != NEMA_MSG_UNKNOWN) {/* 处理解析出来的数据 */// .../* 清空消息结构体 */memset(&nema_msg, 0, sizeof(nema_msg));}}
}

实际移植了正点原子的例程到gd32的开发板,测试如下:

获取打印的是utc时间,utc时间是8点56, 加上8则为本地时间,本地时间时16点56,和实际一致符合预期。

个人公众号:嵌入式学习与实践

基于GD32开发板的GPS定位模块的使用操作相关推荐

  1. 基于ARM开发板或linux工控机的远程操作的小结

    需求: (1).黑龙江现场A处有一个一直在执行任务的工控机(或ARM板),该板子处在一个局域网192.xxx.2.1网段,局域网可以联网: (2).本地为深圳的C处,网络处在2.1网段:需求就是C处远 ...

  2. 移植根文件系统到linux内核 s3c2440,u-boot-2011.06在基于s3c2440开发板的移植之引导内核与加载根文件系统...

    三.根文件系统的制作 我们利用busybox来制作根文件系统 1.在下列网站下载busybox-1.15.0.tar.bz2 在当前目录下解压busybox tar -jxvf busybox-1.1 ...

  3. 【RTOS】基于V7开发板的uCOS-III,uCOS-II,RTX4,RTX5,FreeRTOS原版和带CMSIS-RTOS V2封装层版全部集齐...

    RTOS模板制作好后,后面堆各种中间件就方便了. 1.基于V7开发板的最新版uCOS-II V2.92.16程序模板,含MDK和IAR,支持uC/Probe https://www.cnblogs.c ...

  4. 基于uFUN开发板的心率计(三)Qt上位机的实现

    前言 上两周利用周末的时间,分别写了基于uFUN开发板的心率计(一)DMA方式获取传感器数据和基于uFUN开发板的心率计(二)动态阈值算法获取心率值,介绍了AD采集传感器数据和数据的滤波处理获取心率值 ...

  5. 基于uFUN开发板的RGB调色板

    前言 使用uFUN开发板配合Qt上位机,实现任意颜色的混合,Qt上位机下发RGB数值,范围0-255,uFUN开发板进行解析,然后输出不同占空比的PWM,从而实现通过RGB三原色调制出任意颜色. Qt ...

  6. request[limit]取不到前台的值_基于uFUN开发板的心率计(二)动态阈值算法获取心率值...

    前言 上一篇文章:基于uFUN开发板的心率计(一)DMA方式获取传感器数据,介绍了如何获取PulseSensor心率传感器的电压值,并对硬件电路进行了计算分析.心率计,重要的是要获取到心率值,本篇文章 ...

  7. 基于uFUN开发板和扩展板的联网校准时钟

    项目概述 上周在uFUN试用群里看到管理员说试用活动快结束了,要抓紧完成评测总结,看大家的评测总结也都写了,我也不能落后啊!正好最近做的扩展板到手了,于是赶紧进行调试,做了一个不用校准的时钟,时钟这种 ...

  8. 基于uFUN开发板的心率计(二)动态阈值算法获取心率值

    文章目录 前言 IBI和BPM 核心操作 -- 识别一个脉搏信号 问题一:阈值的选取 问题二:特征点识别 算法整体框架与代码实现 总结 基于uFUN开发板的Keil源码下载 uFUN评测系列文章 前言 ...

  9. 基于STM32开发板I²C总线通信协议浅析

    基于STM32开发板I²C总线通信协议浅析 一.前言 I²C(Inter-Integrated Circuit),中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,是由飞利浦公司在1980 ...

最新文章

  1. python txt提取特定数据_Python提取列表中的内容 用“python”怎么提取文件里的指定内容?...
  2. const引用和非const引用
  3. leetcode算法题--K 次串联后最大子数组之和★
  4. 未来耳机可能将成为最强大的健康监护仪
  5. [SCOI2005]扫雷
  6. ubuntu一般软件安装在什么目录
  7. 获取二进制或者16/32位的某一位的值
  8. 升级到 Tomcat 8 后 Cookie 可能出现的问题
  9. python julian date_Python 的内嵌time模板翻译及说明
  10. 离散数学及其应用傅彦pdf_《离散数学及其应用》第二章 计算与探索
  11. HTML基本功之文档结构
  12. Centos7中完美搭建ftp服务器
  13. 设计模式系列 - 装饰器模式
  14. H5做linux界面开发,如何利用HTML5打造桌面应用?
  15. win11游戏窗口化如何设置 windows11游戏窗口化的设置方法
  16. pdf书籍笔记助手,BookxNote使用记录
  17. 基于matlab的音频处理论文,基于Matlab的语音信号处理与仿真设计毕业论文
  18. matlab 傅里叶变换频谱
  19. java 文本编码_Java文件编码
  20. 计算机专业人士研究生论文,计算机专业研究生论文致谢

热门文章

  1. 【软件安装教程】【360清理大师】(在windows系统里的应用商店有自带的)
  2. 修改wifi密码 及168.192.1.1登录
  3. 电脑计算机打开没有权限管理,电脑没有权限打不开软件怎么办?
  4. java实现加密解密抽象_DES加密解密-java实现
  5. Lubuntu纯小白级别安装配置
  6. 如何设计制作你的新浪微博个人封面、模版下载、个性封面下载
  7. 在生鲜零售业,DolphinScheduler 还能这么玩!
  8. 为什么有人会觉得五一没有放假?
  9. 2021高考成绩查询电话号码多少,2021高考查分时间表 高考分数线几号公布
  10. 如何使用正则表达式进行QQ校友的数据采集