#ifndef BSP__GPS_H__
#define BSP__GPS_H__
#include "cmsis_os2.h"
#include "hi_io.h"
#include "hi_gpio.h"
#include "hi_uart.h" // 添加UART专用头文件
#include <stdio.h>
#include <string.h>
#include "bsp_uart.h"
#include "hi_errno.h"
// GPS 数据结构定义
typedef struct {
float longitude; // 经度 (度)
float latitude; // 纬度 (度)
char nshemi; // 北纬/南纬 (N/S)
char ewhemi; // 东经/西经 (E/W)
struct {
uint8_t hour; // UTC 小时
uint8_t min; // UTC 分钟
uint8_t sec; // UTC 秒
} utc;
uint8_t fixmode; // 定位模式
uint8_t posslnum; // 参与定位的卫星数
float altitude; // 海拔高度 (米)
} nmea_msg;
#define GPS_UART_IDX HI_UART_IDX_2 // 使用UART1
#define GPS_BAUDRATE 9600
#define RX_BUF_LEN 128 // 定义接收缓冲区大小
// 函数声明
void gps_init(void);
void gps_parse_nmea(nmea_msg *gps, const char *buf);
void gps_show_data(const nmea_msg *gps);
#endif#include "bsp_gps.h"
#include <stdlib.h>
#include "bsp_uart.h"
#include <string.h>
// 查找逗号位置
// 计算m的n次方
static uint32_t NMEA_Pow(uint8_t m, uint8_t n) {
uint32_t result = 1;
while (n--) result *= m;
return result;
}
// 查找逗号位置(修改为接受const指针)
uint8_t nmea_comma_pos(const uint8_t *buf, uint8_t cx) {
const uint8_t *p = buf;
while (cx) {
if (*buf == '*' || *buf < ' ' || *buf > 'z')
return 0xFF; // 错误终止符
if (*buf == ',') cx--;
buf++;
}
return buf - p;
}
// 字符串转数字(修改为接受const指针)
int nmea_str2num(const uint8_t *buf, uint8_t *dx) {
const uint8_t *p = buf;
uint32_t ires = 0, fres = 0;
uint8_t ilen = 0, flen = 0, i;
uint8_t mask = 0;
int res;
while (1) {
if (*p == '-') { mask |= 0x02; p++; } // 负数标记
if (*p == ',' || *p == '*') break; // 结束符
if (*p == '.') { mask |= 0x01; p++; } // 小数点
else if (*p > '9' || *p < '0') { // 非法字符
ilen = 0; flen = 0; break;
}
if (mask & 0x01) flen++;
else ilen++;
p++;
}
if (mask & 0x02) buf++; // 跳过负号
for (i = 0; i < ilen; i++) // 整数部分
ires += NMEA_Pow(10, ilen - 1 - i) * (buf[i] - '0');
if (flen > 5) flen = 5; // 最多5位小数
if (dx) *dx = flen; // 安全处理空指针
for (i = 0; i < flen; i++) // 小数部分
fres += NMEA_Pow(10, flen - 1 - i) * (buf[ilen + 1 + i] - '0');
res = ires * NMEA_Pow(10, flen) + fres;
if (mask & 0x02) res = -res;
return res;
}
// 解析 GPRMC 语句
static void parse_gprmc(nmea_msg *gps, const char *buf) {
const char *p = strstr(buf, "GPRMC");
if (!p) return;
uint8_t pos = nmea_comma_pos((const uint8_t *)p, 1); // UTC 时间
if (pos != 0xFF) {
uint32_t time = nmea_str2num((const uint8_t *)(p + pos), NULL);
gps->utc.hour = time / 10000;
gps->utc.min = (time % 10000) / 100;
gps->utc.sec = time % 100;
}
pos = nmea_comma_pos((const uint8_t *)p, 3); // 纬度
if (pos != 0xFF) {
float lat = nmea_str2num((const uint8_t *)(p + pos), NULL) / 100000.0f;
gps->latitude = (int)(lat / 100) + (lat - (int)(lat / 100) * 100) / 60.0f;
}
pos = nmea_comma_pos((const uint8_t *)p, 4); // 纬度半球
if (pos != 0xFF) gps->nshemi = *(p + pos);
pos = nmea_comma_pos((const uint8_t *)p, 5); // 经度
if (pos != 0xFF) {
float lon = nmea_str2num((const uint8_t *)(p + pos), NULL) / 100000.0f;
gps->longitude = (int)(lon / 100) + (lon - (int)(lon / 100) * 100) / 60.0f;
}
pos = nmea_comma_pos((const uint8_t *)p, 6); // 经度半球
if (pos != 0xFF) gps->ewhemi = *(p + pos);
}
// 解析 GPGGA 语句 (添加此函数)
static void parse_gpgga(nmea_msg *gps, const char *buf) {
const char *p = strstr(buf, "GPGGA");
if (!p) return;
// UTC时间
uint8_t pos = nmea_comma_pos((const uint8_t *)p, 1);
if (pos != 0xFF) {
uint32_t time = nmea_str2num((const uint8_t *)(p + pos), NULL);
gps->utc.hour = time / 10000;
gps->utc.min = (time % 10000) / 100;
gps->utc.sec = time % 100;
}
#include <stdio.h>
#include <unistd.h>
#include <string.h> // 添加memset头文件
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "bsp_gps.h"
#include "hi_uart.h" // 添加UART操作头文件
#include "hi_time.h" // 添加时间函数头文件
// 全局变量
static nmea_msg g_gps_data = {0}; // 初始化GPS数据结构
static uint8_t rx_buf[RX_BUF_LEN] = {0}; // 初始化接收缓冲区
static osThreadId_t GPS_Task_ID; // 任务ID
// 修正任务函数名
void gps_task(void *argument) {
(void)argument;
gps_init(); // 初始化GPS
// 添加启动延迟,等待GPS模块初始化
sleep(2);
while (1) {
uint32_t len = hi_uart_read(GPS_UART_IDX, rx_buf, sizeof(rx_buf) - 1);
if (len > 0) {
rx_buf[len] = '\0';
// 打印原始数据用于调试
// printf("Raw: %s\n", rx_buf);
gps_parse_nmea(&g_gps_data, (const char*)rx_buf);
// 添加时间戳
printf("\n[%02d:%02d:%02d] GPS Data:\n",
g_gps_data.utc.hour,
g_gps_data.utc.min,
g_gps_data.utc.sec);
gps_show_data(&g_gps_data);
memset(rx_buf, 0, sizeof(rx_buf));
}
// 设置合适的刷新率(500ms)
sleep(1);
}
}
void gps_task_create(void)
{
osThreadAttr_t taskOptions;
taskOptions.name = "GPSTask"; // 任务的名字
taskOptions.attr_bits = 0; // 属性位
taskOptions.cb_mem = NULL; // 堆空间地址
taskOptions.cb_size = 0; // 堆空间大小
taskOptions.stack_mem = NULL; // 栈空间地址
taskOptions.stack_size = 4096; // 栈空间大小 单位:字节
taskOptions.priority = osPriorityNormal; // 任务的优先级
GPS_Task_ID = osThreadNew(gps_task, NULL, &taskOptions); // 创建任务
if (GPS_Task_ID != NULL)
{
printf("ID = %p, Create GPS_Task is OK!\n", GPS_Task_ID);
};
}
static void template_demo(void)
{
printf("普中-Hi3861开发板--GPS实验\r\n");
gps_task_create();
}
SYS_RUN(template_demo);
该代码是基于海思hi 3861外接NEO-6M-0-001在串口助手上显示经纬度和当前北京时间的代码但在串口助手上显示以下内容是什么原因并进行修改��
�
����
��N�B�����������
�!���
�
�����
��F�0�
���������~�B���1�!���
��
��~�*���
�
��
��
����
���
������
��~���
�
��
��B�1���
�F�1�N���
��
�������
�*�!
��^�*�
��B�1���
���
��^�
���^�
����
�����~���
������
���
�!��F���
�!�
���^�:�����
����������
�
��
����
����
������B���
�1�!��
�
����
����
�����B�0�
��B�1�
����
�
��
��~�
�1�
�
����
�B�2�
�������2��B���
���
���
����������_�����B���^�2���
�
�х����N���B�����
���
���
�N����^���������