我是靠谱客的博主 害怕老师,最近开发中收集的这篇文章主要介绍GD32串口读取GPS模块数据并解析经纬度教程-附完整代码和资料文件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言:

        最近入手了个GPS模块,手上只有GD32的开发板。网上有很多使用STM32库函数的GPS驱动程序,但是基于GD32库函数读取GPS驱动的教程居然一篇都没有。所以为了学习GD32库的同学,还是写一篇博客记录一下。

资料下载:

1、教程所用到的GPS模块资料的百度云链接:

https://pan.baidu.com/s/1scQYIS97CqzUzH5XQ3CI6A?pwd=5u0w

2、完整代码下载链接:

https://download.csdn.net/download/YANGJIERUN/87381512

使用的开发板:

 

        本教程使用的开发板为DRG GD-2 GD32F103C8T6最小系统板。使用的GPS集成中科微电子的模组,市面上买得到的GPS模块都可以用本程序读取定位数据。

GD32串口引脚定义如下:

 一般USART0用于下载程序和作为Debug打印数据使用,市面上大多数的开发板的串口都是默认占用USART0。所以我使用USART1读取GPS数据。

一、串口的初始化

        串口初始化网上也有很多教程,这里简单带过。USART0和USART1的初始化步骤一致,只是函数参数上USART0改为了USART1而已。这里直接放代码。

串口0初始化代码:

// 串口 0 初始化
void USART0_init(uint32_t bound)
{
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* connect port to USARTx_Tx */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
/* connect port to USARTx_Rx */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
/* USART configure */
usart_deinit(USART0);
usart_baudrate_set(USART0, bound);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}

串口1初始化代码:

// 串口 1 初始化
void USART1_init(uint32_t bound)
{
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART1);
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* connect port to USARTx_Tx */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* connect port to USARTx_Rx */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
/* USART configure */
usart_deinit(USART1);
usart_baudrate_set(USART1, bound);
usart_word_length_set(USART1, USART_WL_8BIT);
usart_stop_bit_set(USART1, USART_STB_1BIT);
usart_parity_config(USART1, USART_PM_NONE);
usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);
usart_receive_config(USART1, USART_RECEIVE_ENABLE);
usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
usart_enable(USART1);
}

二、串口的输入

        串口输入本教程使用最简单的轮询输入。网上有教程是通过重写scanf实现串口输入的,但是重写scanf的实际使用很不好。数据一多就出错,而且只能被一个串口使用,本人不推荐大家使用。个人觉得还是C语言库里面的getchar()用的舒服。

串口0的输入代码如下:

//串口0的专用 getchar 函数
char USART0_getchar(void)
{
/* 等待串口输入数据 */
while (usart_flag_get(USART0, USART_FLAG_RBNE) == RESET);
return (char)usart_data_receive(USART0);
}

串口1的输入代码如下:

//串口1的专用 getchar 函数
char USART1_getchar(void)
{
/* 等待串口输入数据 */
while (usart_flag_get(USART1, USART_FLAG_RBNE) == RESET);
return (char)usart_data_receive(USART1);
}

三、串口打印

串口0的串口打印输出代码如下:

//串口0的专用 putchar 函数
void USART0_putchar(char ch)
{
usart_data_transmit(USART0, (uint8_t)ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
//串口0的专用 puts 函数
void USART0_puts(char* fmt)
{
uint16_t i = 0;
while(fmt[i] != '')
{
USART0_putchar(fmt[i]);
i++;
}
}

串口1的串口打印输出代码如下:

//串口1的专用 putchar 函数
void USART1_putchar(char ch)
{
usart_data_transmit(USART1, (uint8_t)ch);
while(RESET == usart_flag_get(USART1, USART_FLAG_TBE));
}
//串口1的专用 puts 函数
void USART1_puts(char* fmt)
{
uint16_t i = 0;
while(fmt[i] != '')
{
USART1_putchar(fmt[i]);
i++;
}
}

四、GPS模块的数据解析

        学会了串口的输入输出,解析GPS的经纬度就是个简单的字符串匹配。中科微的GPS模组手册里面有其他数据解析的说明,这里只解析经纬度,其他数据的解析也是大同小异。经纬度的计算方法如下:

 解析代码:

#include "DRG_GPS_Mode.h"
#define BUFF_SIZE 200
typedef struct SaveData
{
char N_S[N_S_Length];
//N/S
char E_W[E_W_Length];
//E/W
} _SaveData;
_SaveData Save_Data;
// 解析 GPS 数据
void parseGpsBuffer(void)
{
uint8_t ch,Rxbuffer[BUFF_SIZE];
uint16_t index,i;
while(1)
{
ch = USART1_getchar();
if(ch == '$')
{
index = 0;
while(ch != ',')
{
ch = USART1_getchar();
Rxbuffer[index] = ch;
index++;
}
if(!strcmp("GNGLL,",(const char*)Rxbuffer))
{
for(i = 0;i < 10;i++)
Save_Data.N_S[i] = USART1_getchar();
ch = USART1_getchar();
ch = USART1_getchar();
ch = USART1_getchar();
for(i = 0;i < 10;i++)
Save_Data.E_W[i] = USART1_getchar();
break;
}
}
}
/*
USART0_puts("Save_Data.N_S = ");
USART0_puts(Save_Data.N_S);
USART0_puts("rn");
USART0_puts("Save_Data.E_W = ");
USART0_puts(Save_Data.E_W);
USART0_puts("rn");
*/
}
// 获取 GPS 纬度数据 - 字符串形式
char* Get_Gps_N_S_str(void)
{
return Save_Data.N_S;
}
// 获取 GPS 经度数据 - 字符串形式
char* Get_Gps_E_W_str(void)
{
return Save_Data.E_W;
}

主函数:

#include "DRG_GPS_Mode.h"
int main(void)
{
USART0_init(115200U);
USART1_init(9600U);
USART0_puts("USART0 begin...rn");
USART1_puts("USART1 begin...rn");
while(1)
{
parseGpsBuffer();
// 解析串口 1 上 GPS 模块的数据
USART0_puts("N_S = ");
USART0_puts(Get_Gps_N_S_str());	// 打印维度字符串数据
USART0_puts("rn");
USART0_puts("E_W = ");
USART0_puts(Get_Gps_E_W_str());	// 打印经度字符串数据
USART0_puts("rn");
}
}

串口助手读取到的数据:

 使用定位工具可以判断读取的数据是否准确。注意GPS模块要拿到室外定位,这样数据才准确。

 完整代码:

工程结构如下:

 my_usart为串口驱动,GPS_Mode包含GPS解析的步骤。

1、main.c

#include "DRG_GPS_Mode.h"
int main(void)
{
USART0_init(115200U);
USART1_init(9600U);
USART0_puts("USART0 begin...rn");
USART1_puts("USART1 begin...rn");
while(1)
{
parseGpsBuffer();
// 解析串口 1 上 GPS 模块的数据
USART0_puts("N_S = ");
USART0_puts(Get_Gps_N_S_str());	// 打印维度字符串数据
USART0_puts("rn");
USART0_puts("E_W = ");
USART0_puts(Get_Gps_E_W_str());	// 打印经度字符串数据
USART0_puts("rn");
}
}

2、DRG_GPS_Mode.h

#ifndef _DRG_GPS_MODE_H_
#define _DRG_GPS_MODE_H_
#include "my_usart.h"
//定义数组长度
#define N_S_Length 11
#define E_W_Length 11
void parseGpsBuffer(void);
// 解析 GPS 数据
char* Get_Gps_N_S_str(void);	// 获取 GPS 纬度数据 - 字符串形式
char* Get_Gps_E_W_str(void);	// 获取 GPS 经度数据 - 字符串形式
#endif

3、DRG_GPS_Mode.c

#include "DRG_GPS_Mode.h"
#define BUFF_SIZE 200
typedef struct SaveData
{
char N_S[N_S_Length];
//N/S
char E_W[E_W_Length];
//E/W
} _SaveData;
_SaveData Save_Data;
// 解析 GPS 数据
void parseGpsBuffer(void)
{
uint8_t ch,Rxbuffer[BUFF_SIZE];
uint16_t index,i;
while(1)
{
ch = USART1_getchar();
if(ch == '$')
{
index = 0;
while(ch != ',')
{
ch = USART1_getchar();
Rxbuffer[index] = ch;
index++;
}
if(!strcmp("GNGLL,",(const char*)Rxbuffer))
{
for(i = 0;i < 10;i++)
Save_Data.N_S[i] = USART1_getchar();
ch = USART1_getchar();
ch = USART1_getchar();
ch = USART1_getchar();
for(i = 0;i < 10;i++)
Save_Data.E_W[i] = USART1_getchar();
break;
}
}
}
/*
USART0_puts("Save_Data.N_S = ");
USART0_puts(Save_Data.N_S);
USART0_puts("rn");
USART0_puts("Save_Data.E_W = ");
USART0_puts(Save_Data.E_W);
USART0_puts("rn");
*/
}
// 获取 GPS 纬度数据 - 字符串形式
char* Get_Gps_N_S_str(void)
{
return Save_Data.N_S;
}
// 获取 GPS 经度数据 - 字符串形式
char* Get_Gps_E_W_str(void)
{
return Save_Data.E_W;
}

4、my_usart.h

#ifndef _MY_USART_H_
#define _MY_USART_H_
#include "gd32f10x.h"
#include "string.h"
void USART0_init(uint32_t bound);	//串口0 初始化函数
void USART0_putchar(char ch);
//串口0 putchar() 函数
void USART0_puts(char* fmt);
//串口0 puts() 函数
char USART0_getchar(void);
//串口0 getchar() 函数
void USART1_init(uint32_t bound);	//串口1 初始化函数
void USART1_putchar(char ch);
//串口1 putchar() 函数
void USART1_puts(char* fmt);
//串口1 puts() 函数
char USART1_getchar(void);
//串口1 getchar() 函数
#endif

5、my_usart.c

#include "my_usart.h"
// 串口 0 初始化
void USART0_init(uint32_t bound)
{
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* connect port to USARTx_Tx */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
/* connect port to USARTx_Rx */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
/* USART configure */
usart_deinit(USART0);
usart_baudrate_set(USART0, bound);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}
//串口0的专用 getchar 函数
char USART0_getchar(void)
{
/* 等待串口输入数据 */
while (usart_flag_get(USART0, USART_FLAG_RBNE) == RESET);
return (char)usart_data_receive(USART0);
}
//串口0的专用 putchar 函数
void USART0_putchar(char ch)
{
usart_data_transmit(USART0, (uint8_t)ch);
while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
}
//串口0的专用 puts 函数
void USART0_puts(char* fmt)
{
uint16_t i = 0;
while(fmt[i] != '')
{
USART0_putchar(fmt[i]);
i++;
}
}
// 串口 1 初始化
void USART1_init(uint32_t bound)
{
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART1);
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* connect port to USARTx_Tx */
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* connect port to USARTx_Rx */
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
/* USART configure */
usart_deinit(USART1);
usart_baudrate_set(USART1, bound);
usart_word_length_set(USART1, USART_WL_8BIT);
usart_stop_bit_set(USART1, USART_STB_1BIT);
usart_parity_config(USART1, USART_PM_NONE);
usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);
usart_receive_config(USART1, USART_RECEIVE_ENABLE);
usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
usart_enable(USART1);
}
//串口1的专用 putchar 函数
void USART1_putchar(char ch)
{
usart_data_transmit(USART1, (uint8_t)ch);
while(RESET == usart_flag_get(USART1, USART_FLAG_TBE));
}
//串口1的专用 puts 函数
void USART1_puts(char* fmt)
{
uint16_t i = 0;
while(fmt[i] != '')
{
USART1_putchar(fmt[i]);
i++;
}
}
//串口1的专用 getchar 函数
char USART1_getchar(void)
{
/* 等待串口输入数据 */
while (usart_flag_get(USART1, USART_FLAG_RBNE) == RESET);
return (char)usart_data_receive(USART1);
}

最后

以上就是害怕老师为你收集整理的GD32串口读取GPS模块数据并解析经纬度教程-附完整代码和资料文件的全部内容,希望文章能够帮你解决GD32串口读取GPS模块数据并解析经纬度教程-附完整代码和资料文件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部