375 lines
12 KiB
C
375 lines
12 KiB
C
/********************************************************************
|
||
* Copyright (C), 2022, 中天海洋系统有限公司
|
||
* 文件名:McuBspAdc.c
|
||
* 作者:任家豪(ZT-040157)
|
||
* 日期:2022年5月16日
|
||
* 描述:关于带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;
|
||
}
|