ESP32 ESP-IDF 获取GPS北斗模块的经纬度和日期时间

本文介绍如何使用ESP32及ESP-IDF开发环境读取并解析GPS北斗模块HT1818Z3G5L的经纬度与日期时间数据。通过编写C程序实现数据的读取与解析,并提供测试数据用于调试。

陈拓 2022/05/12-2022/05/13

1. 简介

在《ESP32 ESP-IDF串口的使用-读GPS北斗模块数据》

https://zhuanlan.zhihu.com/p/512932648

https://blog.youkuaiyun.com/chentuo2000/article/details/124719338

一文中我们已经用ESP32读到了GPS北斗模块HT1818Z3G5L的数据。

文本我们解析ESP32读到的数据,只取经纬度和日期时间。

2. 开发环境

《用乐鑫国内Gitee镜像搭建ESP32开发环境》

https://zhuanlan.zhihu.com/p/348106034

https://blog.youkuaiyun.com/chentuo2000/article/details/113424934?spm=1001.2014.3001.5501

3. 写程序

修改C程序uart_async_rxtxtasks_main.c:

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "string.h"
#include "driver/gpio.h"

static const char *TAG = "ESP32_GPS";
static const int RX_BUF_SIZE = 1024;
char *data = NULL;
char *dest = NULL;

typedef struct {
    char lat[16];
    char lon[16];
    char utc[16];
    char day[8];
    char month[8];
    char year[8];
} gps_data_t;

char *test_data ="\
$GNGGA,132506.000,2233.87430,N,11407.13740,E,1,13,1.0,103.3,M,-2.8,M,,*5E\n\
$GNGLL,2233.87430,N,11407.13740,E,132506.000,A,A*4E\n\
$GNGSA,A,3,02,05,15,23,24,29,195,,,,,,1.6,1.0,1.3,1*07\n\
$GNGSA,A,3,07,10,16,21,34,42,,,,,,,1.6,1.0,1.3,4*33\n\
$GPGSV,3,1,09,02,34,134,15,05,40,044,14,15,71,308,25,18,32,326,26,0*68\n\
$GPGSV,3,2,09,20,25,074,,23,13,293,37,24,32,174,31,29,45,251,37,0*6B\n\
$GPGSV,3,3,09,195,50,158,31,0*6A\n\
$BDGSV,3,1,11,03,,,28,07,13,193,27,10,14,207,32,12,,,35,0*71\n\
$BDGSV,3,2,11,16,66,191,29,21,47,308,41,22,41,027,,34,33,309,25,0*74\n\
$BDGSV,3,3,11,40,,,33,42,12,265,36,44,,,28,0*4B\n\
$GNRMC,132506.000,A,2233.87430,N,11407.13740,E,0.00,244.71,080522,,,A,V*0A\n\
$GNVTG,244.71,T,,M,0.00,N,0.00,K,A*27\n\
$GNZDA,132506.000,08,05,2022,00,00*44\n\
$GPTXT,01,01,01,ANTENNA OPEN*25\n\
";

#define TXD_PIN (GPIO_NUM_13)
#define RXD_PIN (GPIO_NUM_16)

static char *cut_substr(char *dest, char *src, char start, int n)
{
    char *p = dest;
    char *q = src;

    q += start;
    while(n--) *(p++ )= *(q++);
    *(p++) = '\0';
    return dest;
}

void init_uart2(void) {
    const uart_config_t uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_APB,
    };
    // We won't use a buffer for sending data.
    uart_driver_install(UART_NUM_2, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_2, &uart_config);
    uart_set_pin(UART_NUM_2, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}

static void rx2_task(void *arg)
{
    char *row;
    char *pos1;
    char *pos2;

    static const char *RX_TASK_TAG = "RX2_TASK";
    esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO);

    gps_data_t gps_data;
    while (1) {
        bzero(&gps_data, sizeof(gps_data));        
        const int rxBytes = uart_read_bytes(UART_NUM_2, data, RX_BUF_SIZE, 1000 / portTICK_PERIOD_MS);
        if (rxBytes > 0) {
            data[rxBytes] = 0;
            ESP_LOGI(RX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data);
            //ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO);
            // 取经纬度
            //row = strstr(test_data, "$GNGGA"); // 测试
            row = strstr(data, "$GNGGA");
            //printf("row=%s\n", row); // GGA
            pos1 = strchr(row, ','); // UTC时间...
            pos2 = strchr(pos1+1, ','); // 纬度...
            pos1 = strchr(pos2+1, ','); // 纬度方向...
            cut_substr(gps_data.lat, pos2, 1, pos1-pos2); // 纬度
            pos2 = strchr(pos1+1, ','); // 经度...
            pos1 = strchr(pos2+1, ','); // 经度方向...
            cut_substr(gps_data.lon, pos2, 1, pos1-pos2); // 经度
            printf("lat=%s lon=%s\n", gps_data.lat, gps_data.lon);
            // 取时间日期
            //row = strstr(test_data, "$GNZDA"); // 测试
            row = strstr(data, "$GNZDA");
            //printf("row=%s\n", row); // ZDA
            pos1 = strchr(row, ','); // UTC时间...
            pos2 = strchr(pos1+1, ','); // 日...         
            cut_substr(gps_data.utc, pos1, 1, pos2-pos1); // UTC时间
            //printf("utc=%s\n", gps_data.utc);
            pos1 = strchr(pos2+1, ','); // 月...
            cut_substr(gps_data.day, pos2, 1, pos1-pos2); // 日
            pos2 = strchr(pos1+1, ','); // 年...
            cut_substr(gps_data.month, pos1, 1, pos2-pos1); // 月
            pos1 = strchr(pos2+1, ','); // 本时区小时...
            cut_substr(gps_data.year, pos2, 1, pos1-pos2); // 年
            printf("utc=%s day=%s month=%s year=%s\n", gps_data.utc, gps_data.day, gps_data.month, gps_data.year);
        }
    }
}

void app_main(void)
{
    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());
    printf("======================================================\n");

    data = (char *)malloc(RX_BUF_SIZE+1);
    dest = (char *)malloc(16);
    init_uart2();
    xTaskCreate(rx2_task, "uart_rx2_task", 1024*2, NULL, configMAX_PRIORITIES, NULL);
}

GPS北斗模块HT1818Z3G5L接收到卫星信号正常工作时,每发送1帧数据模块上的绿色LED会闪烁1次。

如果模块在室内不能正常工作时可以使用测试数据test_data调试程序。

4. 构建项目

  • 刷新esp-idf环境

get_idf

注意:每次打开终端进入sdk都要执行一次此命令

idf.py set-target esp32

注意:在项目创建第一次使用,以后就不用运行这个命令了。

  • 清除以前的构建

idf.py fullclean

  • 配置项目

idf.py menuconfig

将闪存设置为4MB,保存,退出。

  • 编译

idf.py build

  • 烧写

上电后按一下RST键。

idf.py -p /dev/ttyS4 -b 115200 flash

  • 串口监视器

idf.py monitor -p /dev/ttyS4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晨之清风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值