/******************************************************************** * Copyright (C), 2022, 中天海洋系统有限公司 * 文件名:McuBspAdc.c * 作者:任家豪(ZT-040157) * 日期:2022年5月16日 * 描述:关于带FIFO的OV7670的驱动程序 * ******************************************************************/ #include "McuWH-GN100Drv.h" #include "ZthyToolCheck.h" #include #include #include /* 延迟函数 */ #define WHGN100_DELAY(x) HAL_Delay(x) #define WH_GN100_RBUF_LEN 100 #define RESPONSE_HEADER_STRING "$PGKC001" // 设置信息时,对方回应的应答消息的头 #define POSITION_HEADER_STRING "$GNRMC" // 定位信息的头 /* 关键信息ID */ #define RESTART_ID_STRING "030" // 重启的ID #define OUT_FREQ_ID_STRING "101" // 输出频率ID #define LOW_POWER_ID_STRING "105" // 低功耗ID #define SET_GPS_BD_MODE_ID_STRING "115" // GPS或者北斗的工作模式ID #define MESSAGE_EFFECTIVE_ENABLE 1 // 表示当前数据有效 #define MESSAGE_EFFECTIVE_DISABLE 0 // 表示当前数据无效 #define WHGN100_LON_AND_LAT_EFFECT 0 #define WHGN100_RESTART_ACK_EFFECT 1 #define WHGN100_OUT_FREQ_ACK_EFFECT 2 #define WHGN100_LOW_POWER_ACK_EFFECT 3 #define WHGN100_GPS_AND_BD_ACK_EFFECT 4 #define WHGN100_EFFECT_All 5 static void McuDrvWHGN100Write(uint8_t *buf, uint32_t BufLen); static void McuDrvWHGN100Recv(uint8_t RecvData); /* 处理接收的数据 */ static void McuDrvWHGN100RecvDataHandle(void); /* WGS84坐标系 */ double gMcuDrvWHGN100Time; int gMcuDrvWHGN100Time1; double gMcuDrvWHGN100Lon; // 精度 double gMcuDrvWHGN100Lat; // 纬度 uint8_t gMcuDrvWHGN100LonEorW = MCU_DRV_WH_GN100_LON_E; uint8_t gMcuDrvWHGN100LatNorS = MCU_DRV_WH_GN100_LAT_N; uint8_t gMcuDrvWHGN100LonAndLatUpdata = 0; /* 回应信息当前值 */ uint8_t gMcuDrvWHGN100RestartAck = 0; uint8_t gMcuDrvWHGN100OutFreqAck = 0; uint8_t gMcuDrvWHGN100LowPowerAck = 0; uint8_t gMcuDrvWHGN100GpsAndBdAck = 0; MCU_BSP_CLOCK gMcuDrvWHGN100GpsClock; static uint8_t gWhgn100Rbuf[WH_GN100_RBUF_LEN] = {0}; // 确保能完成留下一帧数据 static uint16_t gWhgn100RbufLocal = 0; /* 初始化函数 */ int McuDrvWHGN100Init(void) { MCU_BSP_UART_CONF UartConfig = {0}; UartConfig.BaudRate = MCU_DRV_WH_GN100_UART_BAUDRATE; UartConfig.WordLength = MCU_DRV_WH_GN100_UART_WORDLEN; UartConfig.StopBits = MCU_DRV_WH_GN100_UART_STOPBITS; UartConfig.Parity = MCU_DRV_WH_GN100_UART_PARITY; UartConfig.Mode = MCU_DRV_WH_GN100_UART_MODE; if (McuBspUartInit(MCU_DRV_WH_GN100_UART_ID, &UartConfig, NULL, McuDrvWHGN100Recv) < 0) { return -1; } McuBspUartStartRecv(MCU_DRV_WH_GN100_UART_ID); McuBspGpioInit(MCU_DRV_WH_GN100_WAKEUP_GPIO_PORT, MCU_DRV_WH_GN100_WAKEUP_GPIO_PIN, MCU_DRV_WH_GN100_WAKEUP_GPIO_MODE, MCU_DRV_WH_GN100_WAKEUP_GPIO_SPEED, MCU_DRV_WH_GN100_WAKEUP_GPIO_PULL, 0, NULL); McuBspGpioInit(MCU_DRV_WH_GN100_POWER_GPIO_PORT, MCU_DRV_WH_GN100_POWER_GPIO_PIN, MCU_DRV_WH_GN100_POWER_GPIO_MODE, MCU_DRV_WH_GN100_POWER_GPIO_SPEED, MCU_DRV_WH_GN100_POWER_GPIO_PULL, 0, NULL); McuDrvWHGN100LowPower(MCU_DRV_WH_GN100_LOW_POWER_FLAG); gWhgn100RbufLocal = 0; return 0; } /* 获取经纬度数据 */ int McuDrvWHGN100GetLatAndLon(float *Lat, unsigned char *LatFlag, float *Lon, unsigned char *LonFlag, MCU_BSP_CLOCK *Clock) { uint16_t i = 0; gMcuDrvWHGN100LonAndLatUpdata = 0; McuDrvWHGN100LowPower(MCU_DRV_WH_GN100_WAKEUP_FLAG); while (gMcuDrvWHGN100LonAndLatUpdata == 0) { WHGN100_DELAY(20); // 延迟ms if (i >= 6000) { McuDrvWHGN100LowPower(MCU_DRV_WH_GN100_LOW_POWER_FLAG); return -1; //设置失败 } i++; } McuDrvWHGN100LowPower(MCU_DRV_WH_GN100_LOW_POWER_FLAG); *Lat = gMcuDrvWHGN100Lat; *LatFlag = gMcuDrvWHGN100LatNorS; *Lon = gMcuDrvWHGN100Lon; *LonFlag = gMcuDrvWHGN100LonEorW; Clock->Year = gMcuDrvWHGN100GpsClock.Year; Clock->Month = gMcuDrvWHGN100GpsClock.Month; Clock->Date = gMcuDrvWHGN100GpsClock.Date; Clock->Hours = gMcuDrvWHGN100GpsClock.Hours; Clock->Minutes = gMcuDrvWHGN100GpsClock.Minutes; Clock->Seconds = gMcuDrvWHGN100GpsClock.Seconds; return 0; } /* 配置NMEA输出频率 freq单位为ms,范围为200-10000 */ int McuDrvWHGN100NMEAOutfreq(uint16_t freq) { char tbuf[50] = {0}; unsigned char Xor = 0; unsigned char i = 0; sprintf(tbuf, "$PGKC101,%d", freq); i = strlen(tbuf); ZthyToolCheckXor((unsigned char *)(tbuf + 1), i, &Xor); sprintf(&tbuf[i], "*%02x\r\n", Xor); i = 0; gMcuDrvWHGN100OutFreqAck = 0; McuDrvWHGN100Write((uint8_t *)tbuf, strlen(tbuf)); /* 等待是否收到消息回复 */ while (gMcuDrvWHGN100OutFreqAck == 0) { WHGN100_DELAY(10); // 延迟ms if (i >= 100) { return -1; //设置失败 } i++; } return 0; } /* 设置重启指令 */ int McuDrvWHGN100NMEASetRestart(uint8_t type) { char tbuf[50] = {0}; unsigned char Xor = 0; unsigned char i = 0; if (type != MCU_DRV_WH_GN100_RESTART_TYPE_HOT && type != MCU_DRV_WH_GN100_RESTART_TYPE_WARM && type != MCU_DRV_WH_GN100_RESTART_TYPE_COLD) { return -1; } sprintf(tbuf, "$PGKC030,%d,1", type); i = strlen(tbuf); ZthyToolCheckXor((unsigned char *)(tbuf + 1), i, &Xor); sprintf(&tbuf[i], "*%02x\r\n", Xor); i = 0; gMcuDrvWHGN100RestartAck = 0; McuDrvWHGN100Write((uint8_t *)tbuf, strlen(tbuf)); /* 等待是否收到消息回复 */ while (gMcuDrvWHGN100RestartAck == 0) { WHGN100_DELAY(10); // 延迟ms if (i >= 100) { return -1; //设置失败 } i++; } return 0; } /* 设置定位模式 */ int McuDrvWHGN100NMEASetPositioningMode(uint8_t mode) { char tbuf[50] = {0}; unsigned char Xor = 0; unsigned char i = 0; sprintf(tbuf, "$PGKC115,%d,%d,%d,%d", (mode & MCU_DRV_WH_GN100_POSITION_GPS), (mode & MCU_DRV_WH_GN100_POSITION_GNSS) >> 1, (mode & MCU_DRV_WH_GN100_POSITION_BD) >> 2, (mode & MCU_DRV_WH_GN100_POSITION_Gli) >> 3); i = strlen(tbuf); ZthyToolCheckXor((unsigned char *)(tbuf + 1), i, &Xor); sprintf(&tbuf[i], "*%02x\r\n", Xor); i = 0; gMcuDrvWHGN100GpsAndBdAck = 0; McuDrvWHGN100Write((uint8_t *)tbuf, strlen(tbuf)); /* 等待是否收到消息回复 */ while (gMcuDrvWHGN100GpsAndBdAck == 0) { WHGN100_DELAY(10); // 延迟ms if (i >= 100) { return -1; //设置失败 } i++; } return 0; } /* 进入或者唤醒低功耗 */ void McuDrvWHGN100LowPower(uint8_t flag) { if (flag == MCU_DRV_WH_GN100_WAKEUP_FLAG) { McuBspGpioSetLevel(MCU_DRV_WH_GN100_WAKEUP_GPIO_PORT, MCU_DRV_WH_GN100_WAKEUP_GPIO_PIN, MCU_BSP_GPIO_OUT_HIGH); McuBspGpioSetLevel(MCU_DRV_WH_GN100_POWER_GPIO_PORT, MCU_DRV_WH_GN100_POWER_GPIO_PIN, MCU_BSP_GPIO_OUT_HIGH); } else { McuBspGpioSetLevel(MCU_DRV_WH_GN100_POWER_GPIO_PORT, MCU_DRV_WH_GN100_POWER_GPIO_PIN, MCU_BSP_GPIO_OUT_LOW); McuBspGpioSetLevel(MCU_DRV_WH_GN100_WAKEUP_GPIO_PORT, MCU_DRV_WH_GN100_WAKEUP_GPIO_PIN, MCU_BSP_GPIO_OUT_LOW); } } /* 发送数据给定位模块 */ static void McuDrvWHGN100Write(uint8_t *buf, uint32_t BufLen) { McuBspUartSend(MCU_DRV_WH_GN100_UART_ID, buf, BufLen); } /* 处理接收的数据 */ static void McuDrvWHGN100RecvDataHandle(void) { char *p = NULL; char *q = NULL; /* 判断这一帧数据中是否存在GNRMC */ if (NULL != strstr((const char *)gWhgn100Rbuf, POSITION_HEADER_STRING)) { /* 找到内容中的第二个逗号与第三个逗号之间的值 */ p = strchr((const char *)gWhgn100Rbuf, ','); // 第一个逗号 if (p == NULL) { return; } p++; q = strchr((const char *)p, ','); // 第二个逗号 if (q == NULL) { return; } *q = 0; if (strlen(p) == 0) { return; } gMcuDrvWHGN100Time = atof(p); gMcuDrvWHGN100GpsClock.Hours = ((uint32_t)gMcuDrvWHGN100Time) / 10000; gMcuDrvWHGN100GpsClock.Minutes = (((uint32_t)gMcuDrvWHGN100Time) / 100) % 100; gMcuDrvWHGN100GpsClock.Seconds = ((uint32_t)gMcuDrvWHGN100Time) % 100; q++; p = strchr((const char *)q, ','); // 第三个逗号 if (p == NULL) { return; } *p = 0; if (strlen(q) == 0 || *q != 'A') { // 判断数据是否为空或者定位是否已经处于差分定位 return; } p++; q = strchr((const char *)p, ','); //找到纬度值所在位置 if (q == NULL) { return; } *q = 0; if (strlen(p) == 0) { // 判断数据是否为空 return; } gMcuDrvWHGN100Lat = atof(p); // 将纬度值赋值给接收变量 q++; p = strchr((const char *)q, ','); // 找到北纬南纬 if (p == NULL) { return; } *p = 0; if (strlen(q) == 0) { // 判断数据是否为空 return; } if (*q == 'N') { gMcuDrvWHGN100LatNorS = MCU_DRV_WH_GN100_LAT_N; } else { gMcuDrvWHGN100LatNorS = MCU_DRV_WH_GN100_LAT_S; } p++; q = strchr((const char *)p, ','); //找到经度值所在位置 if (q == NULL) { return; } *q = 0; if (strlen(p) == 0) { // 判断数据是否为空 return; } gMcuDrvWHGN100Lon = atof(p); // 将经度值赋值给接收变量 q++; p = strchr((const char *)q, ','); // 找到东经西经 if (p == NULL) { return; } *p = 0; if (strlen(q) == 0) { // 判断数据是否为空 return; } if (*q == 'E') { gMcuDrvWHGN100LonEorW = MCU_DRV_WH_GN100_LON_E; } else { gMcuDrvWHGN100LonEorW = MCU_DRV_WH_GN100_LON_W; } p++; q = strchr((const char *)p, ','); if (q == NULL) { return; } q++; p = strchr((const char *)q, ','); if (p == NULL) { return; } p++; q = strchr((const char *)p, ','); if (q == NULL) { return; } *q = 0; if (strlen(p) == 0) { return; } gMcuDrvWHGN100Time1 = atoi(p); gMcuDrvWHGN100GpsClock.Date = gMcuDrvWHGN100Time1 / 10000; gMcuDrvWHGN100GpsClock.Month = (gMcuDrvWHGN100Time1 / 100) %100; gMcuDrvWHGN100GpsClock.Year = 2000 + (gMcuDrvWHGN100Time1 % 100); gMcuDrvWHGN100LonAndLatUpdata = 1; } else if (NULL != strstr((const char *)gWhgn100Rbuf, RESPONSE_HEADER_STRING)) { /* 判断这一帧数据中是否存在 */ p = strchr((const char *)gWhgn100Rbuf, ','); // 第一个逗号 if (p == NULL) { return ; } p++; q = strchr((const char *)p, ','); // 第二个逗号 if (q == NULL) { return ; } *q = 0; if (NULL != strstr((const char *)p, RESTART_ID_STRING)) { q++; if (*q == '3') { gMcuDrvWHGN100RestartAck = 1; } } else if (NULL != strstr((const char *)p, OUT_FREQ_ID_STRING)) { q++; if (*q == '3') { gMcuDrvWHGN100OutFreqAck = 1; } } else if (NULL != strstr((const char *)p, LOW_POWER_ID_STRING)) { q++; if (*q == '3') { gMcuDrvWHGN100LowPowerAck = 1; } } else if (NULL != strstr((const char *)p, SET_GPS_BD_MODE_ID_STRING)) { q++; if (*q == '3') { gMcuDrvWHGN100GpsAndBdAck = 1; } } } } static void McuDrvWHGN100Recv(uint8_t RecvData) { gWhgn100Rbuf[gWhgn100RbufLocal] = RecvData; gWhgn100RbufLocal++; if (RecvData == '\n') { gWhgn100Rbuf[gWhgn100RbufLocal] = 0; // 给最后一帧 McuDrvWHGN100RecvDataHandle(); gWhgn100RbufLocal = 0; } // 取余,容错处理,防止串口数据乱流导致部分逻辑错误 gWhgn100RbufLocal = gWhgn100RbufLocal % WH_GN100_RBUF_LEN; }