前言:
最近入手了个GPS模块,手上只有GD32的开发板。网上有很多使用STM32库函数的GPS驱动程序,但是基于GD32库函数读取GPS驱动的教程居然一篇都没有。所以为了学习GD32库的同学,还是写一篇博客记录一下。
资料下载:
1、教程所用到的GPS模块资料的百度云链接:
1https://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初始化代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// 串口 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// 串口 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的输入代码如下:
1
2
3
4
5
6
7//串口0的专用 getchar 函数 char USART0_getchar(void) { /* 等待串口输入数据 */ while (usart_flag_get(USART0, USART_FLAG_RBNE) == RESET); return (char)usart_data_receive(USART0); }
串口1的输入代码如下:
1
2
3
4
5
6
7//串口1的专用 getchar 函数 char USART1_getchar(void) { /* 等待串口输入数据 */ while (usart_flag_get(USART1, USART_FLAG_RBNE) == RESET); return (char)usart_data_receive(USART1); }
三、串口打印
串口0的串口打印输出代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//串口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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//串口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模组手册里面有其他数据解析的说明,这里只解析经纬度,其他数据的解析也是大同小异。经纬度的计算方法如下:
解析代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60#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; }
主函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#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
1
2
3
4
5
6
7
8
9
10
11
12#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94#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模块数据并解析经纬度教程-附完整代码和资料文件内容请搜索靠谱客的其他文章。
发表评论 取消回复