19,502
社区成员
发帖
与我相关
我的任务
分享
typedef struct {
char utc_time[15];
unsigned char status;
char latitude[15];
unsigned char north_or_south;
char longitude[15];
unsigned char east_or_west;
char speed[15];
char cursor[15];
char date[15];
}RMC_DATA;
/*
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
<1>UTC时间(世界时间),hhmmss(时分秒)格式
<2>定位状态,A=有效定位,V=无效定位
<3>纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<4>纬度半球N(北半球)或S(南半球)
<5>经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<6>经度半球E(东经)或W(西经)
<7>地面速率(000.0~999.9节,前面的0也将被传输)
<8>地面航向(000.0~359.9度,以正北为参考基准,前面的0也将被传输)
<9>UTC日期,ddmmyy(日月年)格式
<10>磁偏角(000.0~180.0度,前面的0也将被传输)
<11>磁偏角方向,E(东)或W(西)
<12>模式指示(仅NMEA01833.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
*/
void RMC_process(unsigned char* rmcData)
{
unsigned char i = 0;
unsigned char rmc_len = 0;
RMC_DATA sRMC;
unsigned char param_num = 0;
unsigned char param_index = 0;
memset(sRMC, 0, sizeof(RMC_DATA));
rmc_len = strlen(rmcData);
// 解析RMC
for (i=0; i<rmc_len; i++)
{
if (rmcData[i] == ',')
{
param_num++;
param_index = 0;
continue;
}
switch (param_num) {
case 1:
sRMC.utc_time[param_index++] = rmcData[i];
break;
case 2:
sRMC.status = rmcData[i];
break;
case 3:
sRMC.latitude[param_index++] = rmcData[i];
break;
case 4:
sRMC.north_or_south = rmcData[i];
break;
case 5:
sRMC.longitude[param_index++] = rmcData[i];
break;
case 6:
sRMC.east_or_west = rmcData[i];
break;
case 7:
sRMC.speed[param_index++] = rmcData[i];
break;
case 8:
sRMC.cursor[param_index++] = rmcData[i];
break;
case 9:
sRMC.date[param_index++] = rmcData[i];
break;
default:
break;
}
}
//
}
------ ------ ------ ------ ------ ------ ------
看了下你代码,有打人的冲动!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bsp_gps.h"
#include "usart2.h"
void Analyze0183(uint8_t *_ucaBuf, uint16_t _usLen);
int32_t StrToInt(char *_pStr);
int32_t StrToIntFix(char *_pStr, uint8_t _ucLen);
void HexToAscii(uint8_t *_ucpHex, uint8_t *_ucpAscII, uint8_t _ucLenasc);
BOOL Uart2RxBuf_full =FALSE;
unsigned char Uart2RxBuf[UART2_RX_BUF_SIZE];
unsigned char Uart1RxBuf[UART1_RX_BUF_SIZE]; /* com1_rf接收缓冲区 */
GPS myGPS;
char GpsBuf[GPS_BUFF_SIZE]; //该数据解析之后才更新显示GPS信息
/*
* 函 数 名: bsp_InitGPS
* 功能说明: 配置GPS串口
* 形 参: 无
* 返 回 值: 无
*/
void bsp_InitGPS(void)
{
/*
GPS 模块使用 UART 串口发送定位数据至 STM32, 每秒钟发送一组数据
因此,只需要配置串口即可。 bsp_uart_fifo.c 中已经配置好串口,此处不必再配置
*/
myGPS.PositionOk = 0; /* 数据设置为无效 */
myGPS.TimeOk = 0; /* 数据设置为无效 */
myGPS.UartOk = 0; /* 串口通信正常的标志, 如果以后收到了校验合格的命令串则设置为1 */
}
/*
* 函 数 名: gps_pro
* 功能说明: 从串口缓冲区中解析出GPS数据包。插入到主程序中执行即可。分析结果存放在全局变量 myGPS
* 形 参: 无
* 返 回 值: 无
*/
void gps_pro(void)
{
uint16_t i=0;
char *p,*pt;
if (Uart2RxBuf_full)
{
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE); //禁止接收中断
Uart2RxBuf_full = FALSE;
p = (char *)Uart2RxBuf;
pt = strchr(p, '$'); //P指向了该位置,在字符串中查找字符$第一次出现的位置
for(i=0;i<GPS_BUFF_SIZE;i++)
{
GpsBuf[i] = Uart2RxBuf[pt-p+i]; //以$开头的字符串
}
printf("%s\r\n",GpsBuf);/* 将收到的GPS模块数据按原样 打印到COM1口,便于跟踪调试 */
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能接收中断
}
}
void GPS_Data_update()
{
char * start_p = GpsBuf;
char *pos_p;
if(strncmp(GpsBuf, "$GPRMC",6)==0)
{
/*字段1 :UTC 时间,hhmmss.ss,时分秒格式 */
pos_p = strchr(start_p, ','); //查找字符串s中首次出现字符c的位置,剥离c前面的信息
if (pos_p == 0)
{
return;//2个逗号连在一起的情况
}
pos_p++; // p+1后指向UTC时间
myGPS.Hour = StrToIntFix(pos_p, 2);
pos_p += 2;
myGPS.Min = StrToIntFix(pos_p, 2);
pos_p += 2;
myGPS.Sec = StrToIntFix(pos_p, 2);
pos_p+= 3;
myGPS.mSec = StrToIntFix(pos_p, 2);
//微秒忽略
/* 字段2 : gps状态,A=有效;V=无效*/
pos_p= strchr(pos_p, ',');
if (pos_p== 0)
{
return;
}
pos_p++;
if (*pos_p != 'A')
{
/* 未定位则直接返回 */
myGPS.PositionOk = 0;
return;
}
myGPS.PositionOk = 1;
pos_p+= 1;
/* 字段3 :纬度ddmm.mmmmm,度分格式*/
pos_p = strchr(pos_p, ','); //接着刚才指针位置找下一个逗号
if (pos_p == 0)
{
return;
}
pos_p++;
myGPS.WeiDu_Du = StrToIntFix(pos_p, 2);
pos_p += 2;
myGPS.WeiDu_Fen = StrToIntFix(pos_p, 2) * 10000;
pos_p += 3;
myGPS.WeiDu_Fen += StrToIntFix(pos_p, 5);
pos_p += 5;
/* 字段4 :N(北纬)或S(南纬) */
pos_p = strchr(pos_p, ',');
if (pos_p == 0)
{
return;
}
pos_p++;
if (*pos_p == 'S')
{
myGPS.NS = 'S';
}
else if (*pos_p == 'N')
{
myGPS.NS = 'N';
}
else
{
return;
}
pos_p+= 1;
/* 字段5:经度dddmm.mmmmm,度分格式 */
pos_p = strchr(pos_p, ',');
if (pos_p == 0)
{
return;
}
pos_p++;
myGPS.JingDu_Du = StrToIntFix(pos_p, 3);
pos_p += 3;
myGPS.JingDu_Fen = StrToIntFix(pos_p, 2) * 10000;
pos_p += 3;
myGPS.JingDu_Fen += StrToIntFix(pos_p, 5);
pos_p += 5;
/* 字段6 :E(东经)或W(西经) */
pos_p = strchr(pos_p, ',');
if (pos_p == 0)
{
return;
}
pos_p++;
if (*pos_p == 'E')
{
myGPS.EW = 'E';
}
else if (*pos_p == 'W')
{
myGPS.EW = 'W';
}
else
{
return;
}
}
}
/*
* 函 数 名: CRC_Check
* 功能说明: 检查0183数据包的校验和是否正确:$与*之间的所有字符的异或运算
* 形 参: _ucaBuf 收到的数据
* _usLen 数据长度
* 返 回 值: TRUE 或 FALSE.
*/
CRCStatus CRC_Check(uint8_t *_ucaBuf, uint16_t _usLen)
{
uint8_t ucXorSum;
uint8_t ucaBuf[2];
uint16_t i;
if (_usLen < 3)
{
return CRC_ERROR;
}
/* 如果没有校验字节,也认为出错 */
if (_ucaBuf[_usLen - 3] != '*')
{
return CRC_ERROR;
}
/* 不允许出现非ASCII字符 */
for (i = 0; i < _usLen - 3; i++)
{
if ((_ucaBuf[i] & 0x80) || (_ucaBuf[i] == 0))
{
return CRC_ERROR;
}
}
ucXorSum = _ucaBuf[0];
for (i = 1; i < _usLen - 3; i++)
{
ucXorSum = ucXorSum ^ _ucaBuf[i];
}
HexToAscii(&ucXorSum, ucaBuf, 2);
if (memcmp(&_ucaBuf[_usLen - 2], ucaBuf, 2) == 0)
{
return CRC_OK;
}
return CRC_ERROR;
}
/*
* 函 数 名: gpsGPRMC
* 功能说明: 分析0183数据包中的 GPGSV 命令,结果存放到全局变量
* 形 参: _ucaBuf 收到的数据
* _usLen 数据长度
* 返 回 值: 无
*/
void gpsGPRMC(uint8_t *_ucaBuf, uint16_t _usLen)
{
char *p;
p = (char *)_ucaBuf;
p[_usLen] = 0;
/* 字段1 UTC时间,hhmmss.sss格式 */
p = strchr(p, ',');
if (p == 0)
{
return;
}
p++;
myGPS.Hour = StrToIntFix(p, 2);
p += 2;
myGPS.Min = StrToIntFix(p, 2);
p += 2;
myGPS.Sec = StrToIntFix(p, 2);
p += 3;
myGPS.mSec = StrToIntFix(p, 2);
p += 2;
/* 字段2 状态,A=定位,V=未定位 */
p = strchr(p, ',');
if (p == 0)
{
return;
}
p++;
if (*p != 'A')
{
/* 未定位则直接返回 */
myGPS.PositionOk = 0;
return;
}
myGPS.PositionOk = 1;
p += 1;
/* 字段3 纬度ddmm.mmmm,度分格式 */
p = strchr(p, ',');
if (p == 0)
{
return;
}
p++;
myGPS.WeiDu_Du = StrToIntFix(p, 2);
p += 2;
myGPS.WeiDu_Fen = StrToIntFix(p, 2) * 10000;
p += 3;
myGPS.WeiDu_Fen += StrToIntFix(p, 5);
p += 5;
/* 字段4 纬度N(北纬)或S(南纬)*/
p = strchr(p, ',');
if (p == 0)
{
return;
}
p++;
if (*p == 'S')
{
myGPS.NS = 'S';
}
else if (*p == 'N')
{
myGPS.NS = 'N';
}
else
{
return;
}
p += 1;
/* 字段5 经度dddmm.mmmm,度分格式 */
p = strchr(p, ',');
if (p == 0)
{
return;
}
p++;
myGPS.JingDu_Du = StrToIntFix(p, 3);
p += 3;
myGPS.JingDu_Fen = StrToIntFix(p, 2) * 10000;
p += 3;
myGPS.JingDu_Fen += StrToIntFix(p, 5);
p += 5;
/* 字段6:经度E(东经)或W(西经) */
p = strchr(p, ',');
if (p == 0)
{
return;
}
p++;
if (*p == 'E')
{
myGPS.EW = 'E';
}
else if (*p == 'W')
{
myGPS.EW = 'W';
}
else
{
return;
}
}
/*
* 函 数 名: Analyze0183
* 功能说明: 分析0183数据包
* 形 参: _ucaBuf 收到的数据
* _usLen 数据长度
* 返 回 值: 无
*/
void Analyze0183(uint8_t *_ucaBuf, uint16_t _usLen)
{
if (CRC_Check(_ucaBuf, _usLen) != CRC_OK)
{
return;
}
if (memcmp(_ucaBuf, "GPGGA,", 6) == 0)
{
gpsGPGGA(_ucaBuf, _usLen);
}
else if (memcmp(_ucaBuf, "GPGSA,", 6) == 0)
{
gpsGPGSA(_ucaBuf, _usLen);
}
else if (memcmp(_ucaBuf, "GPGSV,", 6) == 0)
{
gpsGPGSV(_ucaBuf, _usLen);
}
else if (memcmp(_ucaBuf, "GPRMC,", 6) == 0)
{
gpsGPRMC(_ucaBuf, _usLen);
}
else if (memcmp(_ucaBuf, "GPVTG,", 6) == 0)
{
gpsGPVTG(_ucaBuf, _usLen);
}
else if (memcmp(_ucaBuf, "GPGLL,", 6) == 0)
{
gpsGPGLL(_ucaBuf, _usLen);
}
}
/*
* 函 数 名: StrToInt
* 功能说明: 将ASCII码字符串转换成十进制
* 形 参: _pStr :待转换的ASCII码串. 可以以逗号或0结束
* 返 回 值: 二进制整数值
*/
int32_t StrToInt(char *_pStr)
{
uint8_t flag;
char *p;
uint32_t ulInt;
uint8_t i;
uint8_t ucTemp;
p = _pStr;
if (*p == '-')
{
flag = 1; /* 负数 */
p++;
}
else
{
flag = 0;
}
ulInt = 0;
for (i = 0; i < 15; i++)
{
ucTemp = *p;
if (ucTemp == '.') /* 遇到小数点,自动跳过1个字节 */
{
p++;
ucTemp = *p;
}
if ((ucTemp >= '0') && (ucTemp <= '9'))
{
ulInt = ulInt * 10 + (ucTemp - '0');
p++;
}
else
{
break;
}
}
if (flag == 1)
{
return -ulInt;
}
return ulInt;
}
/*
* 函 数 名: StrToIntFix
* 功能说明: 将ASCII码字符串转换成十进制, 给定长度
* 形 参: _pStr :待转换的ASCII码串. 可以以逗号或0结束
* _ucLen : 固定长度
* 返 回 值: 二进制整数值
*/
int32_t StrToIntFix(char *_pStr, uint8_t _ucLen)
{
uint8_t flag;
char *p;
uint32_t ulInt;
uint8_t i;
uint8_t ucTemp;
p = _pStr;
if (*p == '-')
{
flag = 1; /* 负数 */
p++;
_ucLen--;
}
else
{
flag = 0;
}
ulInt = 0;
for (i = 0; i < _ucLen; i++)
{
ucTemp = *p;
if (ucTemp == '.') /* 遇到小数点,自动跳过1个字节 */
{
p++;
ucTemp = *p;
}
if ((ucTemp >= '0') && (ucTemp <= '9'))
{
ulInt = ulInt * 10 + (ucTemp - '0');
p++;
}
else
{
break;
}
}
if (flag == 1)
{
return -ulInt;
}
return ulInt;
}
/*
* 函 数 名: gps_FenToDu
* 功能说明: 将分转换为度的小数部分,保留6位小数。 将分换算为度。
* 形 参: 无
* 返 回 值: 返回度的小数部分(十进制)
*/
uint32_t gps_FenToDu(uint32_t _fen)
{
uint32_t du;
/* myGPS.WeiDu_Fen; 纬度,分. 232475; 小数点后4位 表示 23.2475分 */
du = (_fen * 100) / 60;
return du;
}
/*
* 函 数 名: gps_FenToMiao
* 功能说明: 将分的小数部分转化秒
* 形 参: 无
* 返 回 值: 秒 整数部分
*/
uint16_t gps_FenToMiao(uint32_t _fen)
{
uint32_t miao;
miao = ((_fen % 10000) * 60);
if ((miao % 10000) >= 5000)
{
miao = miao / 10000 + 1;
}
else
{
miao = miao / 10000;
}
return miao;
}
/*
* 函 数 名: DispGPSStatus
* 功能说明: 打印GPS数据包解码结果
* 形 参:无
* 返 回 值: 无
*/
void DispGPSStatus(void)
{
char buf[128];
if (myGPS.NS == 'S')
{
sprintf(buf, "南纬 %02d.%07d°", myGPS.WeiDu_Du, gps_FenToDu(myGPS.WeiDu_Fen));
}
else
{
sprintf(buf, "北纬 %02d.%07d°",myGPS.WeiDu_Du, gps_FenToDu(myGPS.WeiDu_Fen));
}
printf(buf);
if (myGPS.EW == 'W')
{
sprintf(buf, "西经 %03d.%07d°", myGPS.JingDu_Du, gps_FenToDu(myGPS.JingDu_Fen));
}
else
{
sprintf(buf, "东经 %03d.%07d°", myGPS.JingDu_Du, gps_FenToDu(myGPS.JingDu_Fen));
}
printf(buf);
printf("\n");
}
void * my_memccpy(void *dest,const void *src,int c,int count)
{
while ( count && (*((char *)(dest = (char *)dest + 1) - 1) =
*((char *)(src = (char *)src + 1) - 1)) != (char)c )
count--;
return(count ? dest : NULL);
}