文章目录
- 效果展示
- 一、ATGM336H使用注意事项
- 二、ATGM336H数据帧介绍
- 三、ATGM336H数据接收解析程序设计
- 3.1 ATGM336H数据接收程序设计
- 3.2 ATGM336H数据处理程序设计
- 四、经纬度转换方法介绍
- 毕设特供
本文介绍的是带天线的GPS模块——ATGM336H。
效果展示
OLED显示转换后的经纬度和UTC时间日期
一、ATGM336H使用注意事项
关于ATGM336H可以做什么相信大家都比较清楚了,它获取你所在位置的经纬度信息,而且还可以返回UTC时间,我们可以通过UTC时间解析出当地时间,笔者试过,还是很准确的,用在毕设里面在某些情况下可以直接省掉DS1302而且还不需要手动调时间校准,很爽了!但是经过笔者的观察,大家在ATGM336H的具体使用上面其实还是存在很多疑问的,笔者这里挑选一些比较典型的问题来解答一下,让大家对于ATGM336H的使用注意事项有一个更清晰的了解。
问题一:ATGM336H只能在室外定位吗,室内能不能在室内定位?
答案是肯定的,ATGM336H必须在室外空旷地带才能进行定位,而且定位时还要保证陶瓷天线上的小圆点必须朝上,上方不要有遮挡物。笔者尝试过,要尽量找空旷地带,有些楼间距较小的地方也可能导致定位失败。
问题二:怎么判断有没有定位成功?
有些同学不知道要怎么确定自己是否定位成功,当然我们可以使用串口调试助手直接看模块的输出信息或者单片机解析一下做判断,但其实有一种最直接的方法,一般ATGM336H模块上面会带有一个板载的红色LED,如果定位成功红色LED会闪烁,定位失败的话处于常亮状态。
问题三:ATGM336H要怎么和单片机连接
笔者观察,引脚怎么连接是很多毕设人的问题,ATGM336H通常是有五个引脚,我们一一介绍一下它们的功能和连接方法
引脚 | 功能 |
---|---|
VCC | 电源正极(3.3V或5V) |
GND | 电源负极 |
TXD | 串口发送,接单片机的RXD |
RXD | 串口接收,接单片机的TXD |
PPS | 定位成功后输出秒脉冲信号,电压与模块VCC电压一致(可以悬空) |
问题四:为什么我一直定位失败
如果你在室外空旷的地方,保证陶瓷天线上的小圆点朝上且上方没有遮挡物,确定自己的模块没有坏掉且接线正确,但就是没有定位成功,这是因为首次开机冷启动需要等待1~2分钟,也就是说我们需要等待一段时间可能就定位成功了。
二、ATGM336H数据帧介绍
ATGM336H利用串口发送定位信息给主控芯片,串口波特率为9600,我们始可以用USB-TTL直接连接ATGM336H,到空旷地带等待定位成功后观察一下它的输出信息,输出信息中下面这一帧包含了我们需要的关键信息
$GNRMC,015135.000,A,123.456,N,789.1011,E,0.52,0.00,130825,,,A*7F
帧信息 | 含义 |
---|---|
GNRMC | 报文类型 |
015135.000 | UTC时间 |
A | 定位状态:A表示数据有效;V表示数据无效 |
123.456 | 纬度 |
N | 纬度半球 |
789.1011 | 经度 |
E | 经度半球 |
130825 | UTC日期 |
三、ATGM336H数据接收解析程序设计
我们的整体思路是使用串口1接收来自ATGM336H的报文信息并解析,利用串口2将解结果发送出来。
3.1 ATGM336H数据接收程序设计
主要设计思路是在串口接收中断中逐字节接收数据,接收时加入判断,仅接收存储"GPRMC/GNRMC帧的数据并通过判断帧头$和帧尾\n来提取完整的帧数据,下面是完整的程序设计。
/*
*==============================================================================
*函数名称:USART1_IRQHandler
*函数功能:串口1中断服务函数
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void USART1_IRQHandler (void)
{
u8 recContent; // 存储接收内容
// 如果串口接收到内容
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
recContent = USART_ReceiveData(USART1); // 存储接收内容
// 如果接收到的是$($是一帧信息的开始)
// 保证每接收到新的一帧信息就从缓冲区起始位置开始存储
if(recContent == '$')
{
gReceCunt = 0; // 清零帧信息计数变量
}
// 存储接收到的帧信息
gUart1RcecBuf[gReceCunt ++] = recContent;
// 确定是否收到"GPRMC/GNRMC"这一帧数据
if(gUart1RcecBuf[0] == '$' && gUart1RcecBuf[4] == 'M' && gUart1RcecBuf[5] == 'C')
{
// 接收到换行(接收完了一帧信息)
if(recContent == '\n')
{
memset(receDataFrame.Frame_Buffer, 0, Frame_Buffer_Length); // 初始化接收帧信息数组
memcpy(receDataFrame.Frame_Buffer, gUart1RcecBuf, gReceCunt); // 保存GPRMC/GNRMC这帧的数据
receDataFrame.isGetData = TRUE; // 接收成功
gReceCunt = 0; // 清零接收帧信息接收计数变量
memset(gUart1RcecBuf, 0, UART1RX_MAX_LENGTH); // 清空串口1接收Buf
}
}
// 如果接收内容超出最大长度,不再继续接收
if(gReceCunt >= UART1RX_MAX_LENGTH)
{
gReceCunt = UART1RX_MAX_LENGTH;
}
}
}
3.2 ATGM336H数据处理程序设计
接收到目标帧数据后我们需要从中得到想要的信息,我们的整体思路是逗号作为分隔符,利用strstr函数寻找逗号对应的地址,将两个逗号之间的信息存储到我们提前定义好的解析信息存储数组中,下面是完整的程序设计
/*
*==============================================================================
*函数名称:Uart_Rece_Pares
*函数功能:解析串口接收内容
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void Uart_Rece_Pares(void) // 串口接收内容解析函数
{
// 注意变量类型
char *point = 0; // 逗号的地址指针
char *nextPoint = 0; // 下一个逗号的地址指针
u8 tempVar = 0; // 临时循环变量
// 如果数据接收成功
if (receDataFrame.isGetData)
{
receDataFrame.isGetData = 0; // 清除接收成功标志位
// for循环解析接收帧
// 总共需要找到7个逗号
for (tempVar = 0;tempVar < 7;tempVar ++)
{
// 第一次循环
if (tempVar == 0)
{
// 寻找第一个逗号
if ((point = strstr(receDataFrame.Frame_Buffer,",")) == NULL)
{
printf ("Prase Errpr!\r\n"); // 解析错误
}
}
else
{
point ++; // 防止重复找到同一个逗号
// 寻找下一个逗号
// 注意strstr函数的输入变量,是从上一个逗号之后开始找下一个逗号
if ((nextPoint = strstr(point,",")) != NULL)
{
// 存储信息
switch (tempVar)
{
case 1: // UTC时间
memcpy(receDataFrame.UTCTime,point,nextPoint - point);
break;
case 2: // 数据有效标识
memcpy(receDataFrame.UsefullFlag,point,nextPoint - point);
break;
case 3: // 纬度
memcpy(receDataFrame.latitude,point,nextPoint - point);
break;
case 4: // 纬度方向
memcpy(receDataFrame.N_S,point,nextPoint - point);
break;
case 5: // 经度
memcpy(receDataFrame.longitude,point,nextPoint - point);
break;
case 6: // 经度方向
memcpy(receDataFrame.E_W,point,nextPoint - point);
break;
}
point = nextPoint; // 更新上一个逗号地址指针
receDataFrame.isParseEnd = TRUE; // 数据解析完成
// 数据有效
if (receDataFrame.UsefullFlag[0] == 'A')
{
receDataFrame.isUsefull = TRUE;
printf ("Data is usefull!\r\n");
}
else if (receDataFrame.UsefullFlag[0] == 'V')
{
receDataFrame.isUsefull = FALUSE;
printf ("Data is invalid!\r\n");
}
}
else
{
printf ("Prase Errpr!\r\n"); // 解析错误
}
}
}
}
}
四、经纬度转换方法介绍
通过上面的接收解析,我们能够获取到ATGM336H输出的经纬度信息,但是如果我们想要拿这个信息在地图上搜索我们的定位结果是否准确的话,还需要经过一步转换。
举个例子,比如我们得到的经纬度信息是
1234.5678,N,1234.5678,E
转换方法为
转换结果 = 12 + 34.5678 / 60
毕设特供
由于完整代码较长,为了方便大家学习和使用,我已经将ATGM336H基础资料包和高级应用程序(OLED显示经纬度与UTC时间日期程) 的源码打包整理好了。大家可以关注文末GZ号——>后台私信【】 获取。