20230731_XiaoFuZi_emb/ZheDaXiaoFuZiBoot/Src/Usr/Driver/Ldrv/WH-GN100/McuWH-GN100Drv.c

375 lines
12 KiB
C
Raw Normal View History

/********************************************************************
* Copyright (C), 2022,
* McuBspAdc.c
* (ZT-040157)
* 2022516
* FIFO的OV7670的驱动程序
* ******************************************************************/
#include "McuWH-GN100Drv.h"
#include "ZthyToolCheck.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* 延迟函数 */
#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) {
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_WAKEUP_GPIO_PORT,
MCU_DRV_WH_GN100_WAKEUP_GPIO_PIN,
MCU_BSP_GPIO_OUT_LOW);
McuBspGpioSetLevel(MCU_DRV_WH_GN100_POWER_GPIO_PORT,
MCU_DRV_WH_GN100_POWER_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;
}