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] != '\0')
	{
		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] != '\0')
	{
		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("\r\n");

	USART0_puts("Save_Data.E_W = ");
	USART0_puts(Save_Data.E_W);
	USART0_puts("\r\n");
	*/
}

// 获取 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...\r\n");
	USART1_puts("USART1 begin...\r\n");
   	while(1)
	{
		parseGpsBuffer();				// 解析串口 1 上 GPS 模块的数据
		
		USART0_puts("N_S = ");
		USART0_puts(Get_Gps_N_S_str());	// 打印维度字符串数据
		USART0_puts("\r\n");
		
		USART0_puts("E_W = ");
		USART0_puts(Get_Gps_E_W_str());	// 打印经度字符串数据
		USART0_puts("\r\n");
	}
}

串口助手读取到的数据:

 使用定位工具可以判断读取的数据是否准确。注意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...\r\n");
	USART1_puts("USART1 begin...\r\n");
   	while(1)
	{
		parseGpsBuffer();				// 解析串口 1 上 GPS 模块的数据
		
		USART0_puts("N_S = ");
		USART0_puts(Get_Gps_N_S_str());	// 打印维度字符串数据
		USART0_puts("\r\n");
		
		USART0_puts("E_W = ");
		USART0_puts(Get_Gps_E_W_str());	// 打印经度字符串数据
		USART0_puts("\r\n");
	}
}

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("\r\n");

	USART0_puts("Save_Data.E_W = ");
	USART0_puts(Save_Data.E_W);
	USART0_puts("\r\n");
	*/
}

// 获取 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] != '\0')
	{
		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] != '\0')
	{
		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);
}

猜你喜欢

转载自blog.csdn.net/YANGJIERUN/article/details/128667480