4G_module/custom/GPS/src/gps_config.c

337 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "cm_iomux.h"
#include "cm_gpio.h"
#include "stdio.h"
#include "stdlib.h"
#include "stdarg.h"
#include "cm_os.h"
#include "cm_mem.h"
#include "cm_sys.h"
#include "cm_uart.h"
#include "app_common.h"
#include "app_uart.h"
#include "gps_config.h"
#include "local_tts.h"
#if 0
#include "app_uart.h"
#define DEBUG(fmt, args...) app_printf("[GPS]" fmt, ##args)
#else
#include "app_uart.h"
#define DEBUG(fmt, ...)
#endif
#define GPS_URAT CM_UART_DEV_1
#define GPS_RX_IOMUX UART1_RX_IOMUX
#define GPS_TX_IOMUX UART1_TX_IOMUX
#define GPS_BUF_LEN 512
static int gps_rev_len = 0;
static char gps_rev_data[GPS_BUF_LEN] = {0};
static osThreadId_t GPS_ThreadId = NULL; //串口数据接收、解析任务Handle
static void* gps_uart_sem = NULL; //串口数据接收、解析任务信号量
/**
* @brief trace 在解码时输出捕获的GPS语句
* @param str: 要输出的字符串str_size:数据长度
* @retval 无
*/
void trace(const char *str, int str_size){
// app_printf("\r\nTrace: ");
// uart0_send_msg((uint8_t*)str, str_size, 0);
}
/**
* @brief error 在解码出错时输出提示消息
* @param str: 要输出的字符串str_size:数据长度
* @retval 无
*/
void error(const char *str, int str_size){
// app_printf("\r\nError: ");
// uart0_send_msg((uint8_t*)str, str_size, 0);
}
/**
* @brief error 在解码出错时输出提示消息
* @param str: 要输出的字符串str_size:数据长度
* @retval 无
*/
// void gps_info(const char *str, int str_size){
// app_printf("\r\nInfo: ");
// cm_uart_write(CM_UART_DEV_0, (void*)str, str_size, 1000);
// }
gps_data_t gps_data;
static nmeaPARSER parser;
//将度分格式转为十进制度
double dm_to_dd(double dm) {
int deg = (int)(dm / 100);
double min = dm - deg * 100;
return deg + min/60;
}
/* 串口接收处理任务,平时使用信号量挂起,当收到接收事件后,释放信号量以触发读取任务 */
static void gps_TaskHandle(void *param){
int temp_len = 0;
int it = 0;
uint8_t gps_flag = 0;
uint8_t gps_flag_last = 0;
/* 设置用于输出调试信息的函数 */
nmea_property()->trace_func = &trace;
nmea_property()->error_func = &error;
// nmea_property()->info_func = &gps_info;
gps_data.flow_num =0;
nmea_zero_INFO(&gps_data.info);
nmea_parser_init(&parser);
while(1){
if(gps_uart_sem != NULL){
osSemaphoreAcquire(gps_uart_sem, osWaitForever);//阻塞
}
temp_len = cm_uart_read(GPS_URAT, (void*)&gps_rev_data[gps_rev_len], GPS_BUF_LEN - gps_rev_len, 1000);
gps_rev_len += temp_len;
if(gps_rev_len > 370){
osMutexAcquire(gps_data.mutex, osWaitForever);
nmea_parse(&parser, gps_rev_data, gps_rev_len, &gps_data.info);
gps_data.longitude=dm_to_dd(gps_data.info.lon);
gps_data.latitude=dm_to_dd(gps_data.info.lat);
osMutexRelease(gps_data.mutex);
//nmea_info2pos(&gps_data.info, &gps_data.dpos);
gps_data.flow_num++;
DEBUG("%03d,Lat:%.09f,Lon:%.09f,Sig:%d,Fix:%d,RL=%d\n\n",
it++, gps_data.latitude, gps_data.longitude, gps_data.info.sig, gps_data.info.fix, gps_rev_len
);
if((gps_data.info.fix == 1)||(gps_data.info.sig == 0)){ // 不可用
gps_flag =0;
}else{
gps_flag =1;
}
if(gps_flag!= gps_flag_last){ // GPS状态变化
gps_flag_last = gps_flag;
if(gps_flag == 1){
// app_printf("GPS locate success!\n");
led_set_event(EVENT_GPS_LOCATE_SUCCESS);
local_tts_text_play("定位成功",0,0);
}else{
// app_printf("GPS no locate!\n");
led_set_event(EVENT_GPS_NO_LOCATE);
local_tts_text_play("定位信号弱",0,0);
}
}
memset((void*)gps_rev_data, 0, gps_rev_len);
temp_len = 0;
gps_rev_len = 0;
}
}
// nmea_parser_destroy(&parser);
}
// 串口事件回调函数
static void gps_uart_event_callback(void *param, uint32_t type){
// uart_event_msg_t msg = {0};
if (CM_UART_EVENT_TYPE_RX_ARRIVED & type){
/* 收到接收事件,触发其他线程执行读取数据 */
osSemaphoreRelease(gps_uart_sem);
}
if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type){
/* 收到溢出事件,触发其他线程处理溢出事件 */
osSemaphoreRelease(gps_uart_sem);
// msg.msg_type = type;
// if (uart_event_queue != NULL){//向队列发送数据
// osMessageQueuePut(uart_event_queue, &msg, 0, 0);
// }
}
}
void gps_config_init(void){
int32_t ret = -1;
// 配置引脚复用
cm_iomux_set_pin_func(GPS_RX_IOMUX);
cm_iomux_set_pin_func(GPS_TX_IOMUX);
cm_iomux_set_pin_cmd(CM_IOMUX_PIN_28, CM_IOMUX_PINCMD3_PULL, CM_IOMUX_PINCMD3_FUNC2_PULL_HIGH);
// cm_iomux_set_pin_cmd(CM_IOMUX_PIN_29, CM_IOMUX_PINCMD3_PULL, CM_IOMUX_PINCMD3_FUNC2_PULL_HIGH);
// 事件参数
cm_uart_event_t uart_event = {
CM_UART_EVENT_TYPE_RX_ARRIVED | CM_UART_EVENT_TYPE_RX_OVERFLOW, //注册需要上报的事件类型
"uart1", //用户参数
gps_uart_event_callback //上报事件的回调函数
};
// 注册事件和回调函数
ret = cm_uart_register_event(GPS_URAT, &uart_event);
if(ret != RET_SUCCESS){
cm_log_printf(0, "uart register event err,ret=%d\n", ret);
return;
}
// 配置参数
cm_uart_cfg_t uart_cfg ={
CM_UART_BYTE_SIZE_8,
CM_UART_PARITY_NONE,
CM_UART_STOP_BIT_ONE,
CM_UART_FLOW_CTRL_NONE,
CM_UART_BAUDRATE_115200,
0 //配置为普通串口模式若要配置为低功耗模式可改为1
};
// 开启串口
ret = cm_uart_open(GPS_URAT, &uart_cfg);
if(ret != RET_SUCCESS){
cm_log_printf(0, "uart init err,ret=%d\n", ret);
return;
}
// 串口接收处理任务
osThreadAttr_t gps_task_attr = {0};
gps_task_attr.name = "gps_uart_task";
gps_task_attr.stack_size = 4096 * 4;
gps_task_attr.priority= osPriorityNormal;
gps_data.mutex = osMutexNew(NULL); // 创建互斥锁
GPS_ThreadId= osThreadNew(gps_TaskHandle, 0, &gps_task_attr);
if(gps_uart_sem == NULL) {
gps_uart_sem = osSemaphoreNew(1, 0, NULL);
}
}
/* 关闭串口 */
void gps_config_close(void){
cm_uart_dev_e dev = GPS_URAT;
if(0 == cm_uart_close(dev)){
DEBUG("uart%d close is ok\n", dev);
}else{
DEBUG("uart%d close is error\n", dev);
}
}
// 判断闰年(仅针对于2000以后的年份)
// iYear 两位年数
// 1:为闰年 0:为平年
static uint8_t IsLeapYear(uint8_t iYear){
uint16_t Year;
Year = 2000 + iYear;
if ((Year & 3) == 0){
return ((Year % 400 == 0) || (Year % 100 != 0));
}
return 0;
}
// 格林尼治时间换算世界各时区时间
// *DT: 表示日期时间的数组 格式 YY,MM,DD,HH,MM,SS
// GMT: 时区数
// AREA: 1(+)东区 W0(-)西区
void GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT, uint8_t AREA){
uint32_t YY, MM, DD, hh, mm, ss; // 年月日时分秒暂存变量
if (GMT == 0)
return; // 如果处于0时区直接返回
if (GMT > 12)
return; // 时区最大为12 超过则返回
YY = SourceTime->year; // 获取年
MM = SourceTime->mon; // 获取月
DD = SourceTime->day; // 获取日
hh = SourceTime->hour; // 获取时
mm = SourceTime->min; // 获取分
ss = SourceTime->sec; // 获取秒
if(AREA){ // 东(+)时区处理
if(hh + GMT < 24){
hh += GMT; // 如果与格林尼治时间处于同一天则仅加小时即可
}else{ // 如果已经晚于格林尼治时间1天则进行日期处理
hh = hh + GMT - 24; // 先得出时间
if(MM == 1 || MM == 3 || MM == 5 || MM == 7 || MM == 8 || MM == 10){ // 大月份(12月单独处理)
if(DD < 31){
DD++;
}else{
DD = 1;
MM++;
}
}else if(MM == 4 || MM == 6 || MM == 9 || MM == 11){ // 小月份2月单独处理)
if(DD < 30){
DD++;
}else{
DD = 1;
MM++;
}
}else if (MM == 2){ // 处理2月份
if((DD == 29) || (DD == 28 && IsLeapYear(YY) == 0)){ // 本来是闰年且是2月29日 或者不是闰年且是2月28日
DD = 1;
MM++;
}else{
DD++;
}
}else if (MM == 12){ // 处理12月份
if (DD < 31){
DD++;
}else{ // 跨年最后一天
DD = 1;
MM = 1;
YY++;
}
}
}
}else{
if(hh >= GMT){
hh -= GMT; // 如果与格林尼治时间处于同一天则仅减小时即可
}else{ // 如果已经早于格林尼治时间1天则进行日期处理
hh = hh + 24 - GMT; // 先得出时间
if(MM == 2 || MM == 4 || MM == 6 || MM == 8 || MM == 9 || MM == 11){ // 上月是大月份(1月单独处理)
if(DD > 1){
DD--;
}else{
DD = 31;
MM--;
}
}else if(MM == 5 || MM == 7 || MM == 10 || MM == 12){ // 上月是小月份2月单独处理)
if(DD > 1){
DD--;
}else{
DD = 30;
MM--;
}
}else if(MM == 3){ // 处理上个月是2月份
if((DD == 1) && IsLeapYear(YY) == 0){ // 不是闰年
DD = 28;
MM--;
}else{
DD--;
}
}else if(MM == 1){ // 处理1月份
if(DD > 1){
DD--;
}else{ // 新年第一天
DD = 31;
MM = 12;
YY--;
}
}
}
}
ConvertTime->year = YY; // 更新年
ConvertTime->mon = MM; // 更新月
ConvertTime->day = DD; // 更新日
ConvertTime->hour = hh; // 更新时
ConvertTime->min = mm; // 更新分
ConvertTime->sec = ss; // 更新秒
}