1、AN1303 ATK-NEO-6M GPS 模块使用 本应用 文档 (AN1303 , 对 应 战舰 STM32 开发板 扩展 实验 3 /MiniSTM32 开发板 扩展实验 23 ) 将教 大家 如何 在 ALIENTEK STM32 开 发板 上使 用 ATK-NEO-6M GPS 模块 ( 注意, 本文档同 时适用 ALIENTEK 战舰和 MiniSTM32 两款开发板) ,并 实现 GPS 定位 。 本文档 分为 如下 几部 分: 1 , ATK-NEO-6M GPS 模块 简介 2 , 硬件连 接 3 , 软件实 现 4 , 验证 1、ATK-NEO-6M GPS 模块 简介 A
2、TK-NEO-6M 模 块,是 ALIENTEK 生产 的一 款高 性能 GPS 模块 ,模 块核 心采用 UBLOX 公 司的 NEO-6M 模 组, 具有 50 个 通道 , 追 踪灵 敏度 高达-161dBm , 测量 输出 频率 最 高可 达 5Hz 。 ATK-NEO-6M 模块 自带 高性 能无源 陶瓷 天线 (无 需再 购买昂 贵的 有源 天线 了) , 兼容 3.3V 和 5V 单片 机系 统, 并自 带可 充电后 备电 池( 支持 温启 动或热 启动 ) 。 ATK-NEO-6M 模块 非常 小巧 (25.5mm*31mm ) ,模 块 通过 4 个 2.54mm 间距 的
3、排针与 外 部连接 ,模 块外 观如 图 1.1 所 示: 图 1.1 ATK-NEO-6M 模块 外观图 图 1.1 中 ,从 右到 左, 依 次为模 块引出的 PIN1PIN4 脚, 各引 脚的 详细 描述 如表 1.1 所 示: 序号 名称 说明 1 RXD 模块串口接收脚(TTL 电平, 不能直接接 RS232 电平! ),可接单片机的 TXD 2 TXD 模块串口发送脚(TTL 电平, 不能直接接 RS232 电平! ),可接单片机的 RXD 3 GND 地 4 VCC 电源(2.7V5.0V ) 表 1.1 ATK-NEO-6M 模块 各 引脚功 能描 述 另 外 , 模 块 自
4、带 了 一 个 状 态 指 示 灯 :PPS 。 该 指 示 灯 连 接 在 UBLOX NEO-6M 模组的 TIMEPULSE 端 口, 该端 口 的输出 特性 可以 通过 程序 设置 。PPS 指示 灯, 在默 认条件 下 (没 经 过程序 设置 ) , 有 2 个 状态 : 1 , 常亮, 表示 模块 已开 始工 作,但 还未 实现 定位 。 2 , 闪烁(100ms 灭,900ms 亮) , 表示 模块 已经 定位 成 功。 这样, 通 过 PPS 指示 灯, 我们就 可以 很方 便的 判断 模块的 当前 状态 ,方 便大 家使用 。 ATK-NEO-6M 模块 默认 采 用 NME
5、A-0183 协 议输 出 GPS 定位数 据, 并可 以通 过 UBX 协议 对模块 进行 配置 ,NMEA-0183 协议 详细 介绍 请参 考 ATK-NEO-6M 用户 手册.pdf ,UBX 配置 协议, 请参 考 u-blox6_ReceiverDescriptionProtocolSpec_GPS.G6-SW-10018-C.pdf 。 通过 ATK-NEO-6M GPS 模块, 任何 单片 机 (3.3V/ 5V 电 源) 都 可以 很方 便的 实现 GPS 定位, 当然他 也可 以连 接电 脑, 利用电 脑软 件实 现定 位 。ATK-NEO-6M-V12 GPS 模 块 的
6、原理 图如 图 1.2 所示 : 图 1.2 ATK-NEO-6M GPS 模 块原理 图 2、 硬件 连接 本实验 功能 简介 : 通过 串 口 2 连接 ATK-NEO-6M GPS 模块 , 然 后通 过液 晶显 示 GPS 信息, 包括精 度、 纬度 、高 度、 速度、 用于 定位 的卫 星数 、可见 卫星 数 、UTC 时 间 等信息 。同 时, 可以通 过 USMART 工具 , 设置 GPS 模块的 刷新 速率 (最大 支持 5Hz 刷 新) 和 时钟脉 冲的 配 置。另 外, 通过 KEY0 按键 ,可以 开启 或关 闭 NMEA 数据的 上传 (即 输出 到串 口 1 ,方
7、便开 发调试 ) 。 所要用 到的 硬件 资源 如下 : 1 , 指示 灯 DS0 2 , KEY0 按键 3 , 串口 1 、 串口 2 4 , TFTLCD 模块 5 , ATK-NEO-6M GPS 模块 接下来 , 我 们看 看 ATK-NEO-6M GPS 模 块同 ALIENTEK STM32 开 发板 的连 接, 前面 我们介 绍了 ATK-NEO-6M 模块 的 接口, 我们 通过 杜邦 线连 接模块 和开 发板 的相 应端 口, 连 接关 系如 表 2.1 所 示: ATK-NEO-6M GPS 模块与开 发板连接关系 ATK-NEO-6M GPS 模块 VCC GND TX
8、D RXD ALIENTEK STM32 开发板 3.3V/ 5V GND PA3 PA2 表 2.1 ATK-NEO-6M 模块 同 ALIENTEK STM32 开发 板连 接关系 表 表中 ATK-NEO-6M GPS 模块 的 VCC , 因为 我们 的模 块是可 以 3.3V 或 5V 供 电 的,所 以 可 以接开 发板 的 3.3V 电 源, 也可以 接开 发板 的 5V 电源 ,这个 随便 大家 自己 选择 。 模块与 开发 板的 连接 是很 简单, 不过 这里 特别 提醒 大家: 1 , 请把 GPS 模块放到窗户边/ 阳台,否则可能收不 到 GPS 信号。 2 , 如果想在
9、室内开发, 可 以 考虑使用 ALIENTEK 提供的 蓝牙串口模块 (ATK-HC05 ) , 这 样,我们可以将 GPS 放到 户外/ 窗口,而仍然 在室内 进行程序的调试开发 。 3 , 如果使用的是战舰板 , 请 把战舰 STM32 开发板 P9 端口的 PA2 、 PA3 与 48T 、 48R 的 跳线帽拔了! ! 否则开 发板 可能会检测不到 ATK-HC05 模块。 3、 软件 实现 本实验( 注:这 里仅 以战 舰板代码 为例进 行介 绍,MiniSTM32 开发 板 对应 代 码 几乎 一 模一样 ,详 见 MiniSTM32 开发板 扩展 实验 23) ,我 们在扩展 例
10、程 1 :ATK-HC05 蓝牙串口 模块实验 的 基础 上修 改, 在 HARDW ARE 文 件夹 里 面新建 一个 GPS 文件 夹, 并新 建 gps.c , gps.h 两个 文 件。 然后 在工程 HARDW ARE 组里 面添 加 gps.c , 并在 工程 添加 gps.h 的头 文件 包含路 径。 在 gps.c 里面 ,我 们输 入如 下代码 : #include “gps.h“ #include “led.h“ #include “delay.h“ #include “usart2.h“ #include “stdio.h“ #include “stdarg.h“ #in
11、clude “string.h“ #include “math.h“ / 从 buf 里面 得到 第 cx 个 逗号所 在的 位置 / 返回值:00XFE, 代表 逗号 所在位 置的 偏移. / 0XFF, 代表不存在 第 cx 个逗 号 u8 NMEA_Comma_Pos(u8 *buf,u8 cx) u8 *p=buf; while(cx) if(*buf=*|*bufz)return 0XFF; / 遇到* 或非法字符,则 不存 在第 cx 个 逗号 if(*buf=,)cx-; buf+; return buf-p; /mn 函数 / 返回值:mn 次方. u32 NMEA_Pow(u
12、8 m,u8 n) u32 result=1; while(n-)result*=m; return result; /str 转换为数字,以, 或者* 结束 /buf: 数字存储 区 /dx: 小数点 位数, 返回 给调 用函数 / 返回值: 转 换后 的数 值 int NMEA_Str2num(u8 *buf,u8*dx) u8 *p=buf; u32 ires=0,fres=0; u8 ilen=0,flen=0,i; u8 mask=0; int res; while(1) / 得到整数 和小 数 的长度 if(*p=-)mask|=0X02;p+;/ 是负数 if(*p=,|(*p=
13、*)break;/ 遇到结 束了 if(*p=.)mask|=0X01;p+;/ 遇到小数 点了 else if(*p9|(*p5)flen=5; / 最多取 5 位小 数 *dx=flen; / 小数点位 数 for(i=0;iflen;i+) / 得到小数 部分 数据 fres+=NMEA_Pow(10,flen-1-i)*(bufilen+1+i-0); res=ires*NMEA_Pow(10,flen)+fres; if(mask return res; / 分析 GPGSV 信息 /gpsx:nmea 信息结构 体 /buf: 接收到 的 GPS 数据 缓 冲区首 地址 void
14、NMEA_GPGSV_Analysis(nmea_msg *gpsx,u8 *buf) u8 *p,*p1,dx; u8 len,i,j,slx=0; u8 posx; p=buf; p1=(u8*)strstr(const char *)p,“$GPGSV“); len=p17-0; / 得到 GPGSV 的 条数 posx=NMEA_Comma_Pos(p1,3); / 得到可见 卫星 总数 if(posx!=0XFF)gpsx-svnum=NMEA_Str2num(p1+posx, for(i=0;islmsgslx.num=NMEA_Str2num(p1+posx, / 得到卫星 编号
15、 else break; posx=NMEA_Comma_Pos(p1,5+j*4); if(posx!=0XFF)gpsx-slmsgslx.eledeg=NMEA_Str2num(p1+posx, / 得到卫星 仰角 else break; posx=NMEA_Comma_Pos(p1,6+j*4); if(posx!=0XFF)gpsx-slmsgslx.azideg=NMEA_Str2num(p1+posx, / 得到卫星 方位 角 else break; posx=NMEA_Comma_Pos(p1,7+j*4); if(posx!=0XFF)gpsx-slmsgslx.sn=NME
16、A_Str2num(p1+posx, / 得到卫星 信噪 比 else break; slx+; p=p1+1;/ 切换 到下 一个 GPGSV 信息 / 分析 GPGGA 信息 /gpsx:nmea 信息结构 体 /buf: 接收到 的 GPS 数据 缓 冲区首 地址 void NMEA_GPGGA_Analysis(nmea_msg *gpsx,u8 *buf) u8 *p1,dx; u8 posx; p1=(u8*)strstr(const char *)buf,“$GPGGA“); posx=NMEA_Comma_Pos(p1,6); / 得到 GPS 状态 if(posx!=0XFF
17、)gpsx-gpssta=NMEA_Str2num(p1+posx, posx=NMEA_Comma_Pos(p1,7); / 得到用于 定位 的卫 星数 if(posx!=0XFF)gpsx-posslnum=NMEA_Str2num(p1+posx, posx=NMEA_Comma_Pos(p1,9); / 得到海拔 高度 if(posx!=0XFF)gpsx-altitude=NMEA_Str2num(p1+posx, / 分析 GPGSA 信息 /gpsx:nmea 信息结构 体 /buf: 接收到 的 GPS 数据 缓 冲区首 地址 void NMEA_GPGSA_Analysis(
18、nmea_msg *gpsx,u8 *buf) u8 *p1,dx; u8 posx; u8 i; p1=(u8*)strstr(const char *)buf,“$GPGSA“); posx=NMEA_Comma_Pos(p1,2); / 得到定位 类型 if(posx!=0XFF)gpsx-fixmode=NMEA_Str2num(p1+posx, for(i=0;ipossli=NMEA_Str2num(p1+posx, else break; posx=NMEA_Comma_Pos(p1,15); / 得到 PDOP 位 置精 度因 子 if(posx!=0XFF)gpsx-pdop
19、=NMEA_Str2num(p1+posx, posx=NMEA_Comma_Pos(p1,16); / 得到 HDOP 位置 精度 因 子 if(posx!=0XFF)gpsx-hdop=NMEA_Str2num(p1+posx, posx=NMEA_Comma_Pos(p1,17); / 得到 VDOP 位置 精度 因 子 if(posx!=0XFF)gpsx-vdop=NMEA_Str2num(p1+posx, / 分析 GPRMC 信息 /gpsx:nmea 信息结构 体 /buf: 接收到 的 GPS 数据 缓 冲区首 地址 void NMEA_GPRMC_Analysis(nmea
20、_msg *gpsx,u8 *buf) u8 *p1,dx; u8 posx; u32 temp; float rs; p1=(u8*)strstr(const char *)buf,“$GPRMC“); posx=NMEA_Comma_Pos(p1,1); / 得到 UTC 时间 if(posx!=0XFF) temp=NMEA_Str2num(p1+posx,/ 得到 UTC 时间 gpsx-utc.hour=temp/10000; gpsx-utc.min=(temp/100)%100; gpsx-utc.sec=temp%100; posx=NMEA_Comma_Pos(p1,3);
21、/ 得到纬度 if(posx!=0XFF) temp=NMEA_Str2num(p1+posx, gpsx-latitude=temp/NMEA_Pow(10,dx+2); / 得到 rs=temp%NMEA_Pow(10,dx+2); / 得到 gpsx-latitude=gpsx-latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx)/60; / 转换为 posx=NMEA_Comma_Pos(p1,4); / 南纬还是 北纬 if(posx!=0XFF)gpsx-nshemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,5);
22、 / 得到经度 if(posx!=0XFF) temp=NMEA_Str2num(p1+posx, gpsx-longitude=temp/NMEA_Pow(10,dx+2); / 得到 rs=temp%NMEA_Pow(10,dx+2); / 得到 gpsx-longitude=gpsx-longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx)/60; posx=NMEA_Comma_Pos(p1,6); / 东经还是 西经 if(posx!=0XFF)gpsx-ewhemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,9); /
23、 得到 UTC 日期 if(posx!=0XFF) temp=NMEA_Str2num(p1+posx, / 得到 UTC 日期 gpsx-utc.date=temp/10000; gpsx-utc.month=(temp/100)%100; gpsx-utc.year=2000+temp%100; / 分析 GPVTG 信息 /gpsx:nmea 信息结构 体 /buf: 接收到 的 GPS 数据 缓 冲区首 地址 void NMEA_GPVTG_Analysis(nmea_msg *gpsx,u8 *buf) u8 *p1,dx; u8 posx; p1=(u8*)strstr(const
24、 char *)buf,“$GPVTG“); posx=NMEA_Comma_Pos(p1,7); / 得到地面 速率 if(posx!=0XFF) gpsx-speed=NMEA_Str2num(p1+posx, if(dxspeed*=NMEA_Pow(10,3-dx); / 确保扩大 1000 倍 / 提取 NMEA-0183 信息 /gpsx:nmea 信息 结构 体 /buf: 接收到 的 GPS 数据 缓 冲区首 地址 void GPS_Analysis(nmea_msg *gpsx,u8 *buf) NMEA_GPGSV_Analysis(gpsx,buf); /GPGSV 解析
25、 NMEA_GPGGA_Analysis(gpsx,buf); /GPGGA 解析 NMEA_GPGSA_Analysis(gpsx,buf); /GPGSA 解析 NMEA_GPRMC_Analysis(gpsx,buf); /GPRMC 解析 NMEA_GPVTG_Analysis(gpsx,buf); /GPVTG 解析 /GPS 校 验和 计算 /buf: 数据缓存 区首 地址 /len: 数据长度 /cka,ckb: 两个 校验 结果. void Ublox_CheckSum(u8 *buf,u16 len,u8* cka,u8*ckb) u16 i; *cka=0;*ckb=0;
26、for(i=0;ilen;i+) *cka=*cka+bufi; *ckb=*ckb+*cka; / 配置 UBLOX NEO-6 的 时 钟脉冲 输出 /interval: 脉冲间隔 /length: 脉冲宽度 /status: 脉冲配置:1, 高 电平 有效;0, 关闭;-1,低电平 有效. void Ublox_Cfg_Tp(u32 interval,u32 length,signed char status) _ublox_cfg_tp *cfg_tp=(_ublox_cfg_tp *)USART2_TX_BUF; cfg_tp-header=0X62B5; /cfg header c
27、fg_tp-id=0X0706; /cfg tp id cfg_tp-dlength=20; / 数据区长 度为 20 个字 节. cfg_tp-interval=interval; / 脉冲间隔,us cfg_tp-length=length; / 脉冲宽度,us cfg_tp-status=status; / 时钟脉冲 配置 cfg_tp-timeref=0; / 参考 UTC 时间 cfg_tp-flags=0; /flags 为 0 cfg_tp-reserved=0; / 保留位为 0 cfg_tp-antdelay=820; / 天线延时 为 820ns cfg_tp-rfdela
28、y=0; /RF 延时为 0ns cfg_tp-userdelay=0; / 用户延时 为 0ns Ublox_CheckSum(u8*)( while(DMA1_Channel7-CNDTR!=0); / 等待通道 7 传 输完 成 UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_tp);/ 通过 dma 发送出 去 / 配置 UBLOX NEO-6 的 更 新速率 /measrate: 测量时间 间隔 , 单位 为 ms ,最少不 能小 于 200ms (5Hz ) /reftime: 参考时间 ,0=UTC Time ;1=GPS Time
29、 (一 般设置 为 1 ) void Ublox_Cfg_Rate(u16 measrate,u8 reftime) _ublox_cfg_rate *cfg_rate=(_ublox_cfg_rate *)USART2_TX_BUF; if(measrateheader=0X62B5; /cfg header cfg_rate-id=0X0806; /cfg rate id cfg_rate-dlength=6; / 数据区长 度为 6 个 字节. cfg_rate-measrate=measrate;/ 脉冲间隔,us cfg_rate-navrate=1; / 导航速率 (周 期) ,固
30、 定 为 1 cfg_rate-timeref=reftime; / 参考时间 为 GPS 时间 Ublox_CheckSum(u8*)( while(DMA1_Channel7-CNDTR!=0); / 等待通道 7 传 输完 成 UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_rate);/ 通过 dma 发送出 去 这部分 代码 可以 分 为 2 个 部分, 第一 部分 是 NMEA-0183 数据 解析 部分, 另外 一部分 则 是 UBX 协 议控 制部 分。 NMEA-0183 协 议 解 析 部 分 , 这 里 利 用 了 一 个
31、简 单 的 数 逗 号 方 法 来 解 析 。 我 们 知 道 NMEA-0183 协议 都是 以类 似$GPGSV 的 开头 ,然 后 固定输 出格 式, 不论 是否 有数据 输出 , 逗号是 肯定 会有 的 , 而 且 都会以 * 作为 有效 数据 的结尾 , 所以 , 我们 了解 了 NMEA-0183 协议的 数据 格式 ( 在 ATK-NEO-6M 的 用户 手册 有详 细介绍 ) 之后 ,就 可以 通 过数逗 号的 方 法,来 解析 数据 了。 本代 码实现 了 对 NMEA-0183 协议的$GPGGA 、$GPGSA 、$GPGSV 、 $GPRMC 和$GPVTG 等 5 类
32、帧的 解析 ,结 果存 放在 通过 gps.h 定义 的 nmea_msg 结构 体 内 。 UBX 协议 控制 部分 , 此 部 分我们 只实 现 了 NEO-6M 模组常 用的 两个 配置 : 时 钟脉冲 配 置和测 量输 出速 率配 置。 时钟脉 冲配 置通 过 Ublox_Cfg_Tp 实 现, 可以 设置 脉 冲间隔 , 脉 冲 宽度等 信息 。测 量输 出速 率配置 则通过 Ublox_Cfg_Rate 函数 实现 ,通 过该 函 数,可 以设 置 模块的 测量 输出 速率 ,最 快可以 达 到 5Hz 的 测量 输 出速率 。 我们 将 Ublox_Cfg_Rate 和 Ublo
33、x_Cfg_Tp 加入 USMART 控 制, 方便大 家测 试。 另外要 在 usart2.h 里面 , 将 USART2_MAX_RECV_LEN 的 值设置 为 800, 。 然后 在 gps.h 里面 , 我 们 输入如 下代 码: #ifndef _GPS_H #define _GPS_H #include “sys.h“ /GPS NMEA-0183 协议 重 要参数 结构 体定 义 / 卫星信息 typedef struct u8 num; / 卫星编号 u8 eledeg; / 卫星仰角 u16 azideg; / 卫星方位 角 u8 sn; / 信噪比 nmea_slmsg;
34、 /UTC 时间 信息 typedef struct u16 year; / 年份 u8 month;/ 月份 u8 date; / 日期 u8 hour; / 小时 u8 min; / 分钟 u8 sec; / 秒钟 nmea_utc_time; /NMEA0183 协 议解 析后 数据存 放结 构体 typedef struct u8 svnum; / 可见卫星 数 nmea_slmsg slmsg12; / 最多 12 颗卫 星 nmea_utc_time utc; /UTC 时间 u32 latitude; / 纬度 分 扩大 100000 倍, 实际要 除 以 100000 u8 n
35、shemi; / 北纬/ 南纬,N:北纬;S: 南纬 u32 longitude; / 经度 分 扩大 100000 倍, 实际要 除 以 100000 u8 ewhemi; / 东经/ 西经,E: 东经;W: 西经 u8 gpssta; /GPS 状态:0, 未定位;1, 非 差 分定位;2, 差 分定 位;6, 正 在 估算. u8 posslnum; / 用于定位 的卫 星数,012. u8 possl12; / 用于定位 的卫 星编 号 u8 fixmode; / 定位类型:1, 没有 定位;2,2D 定位;3,3D 定位 u16 pdop; / 位置精度 因子 0500, 对 应实际
36、 值 050.0 u16 hdop; / 水平精度 因子 0500, 对 应实际 值 050.0 u16 vdop; / 垂直精度 因子 0500, 对 应实际 值 050.0 int altitude; / 海拔高度, 放大 了 10 倍, 实 际除 以 10. 单位:0.1m u16 speed; / 地面速率, 放大 了 1000 倍, 单位:0.001 公里/小时 nmea_msg; /UBLOX NEO-6M 时 钟脉 冲配置 结构 体 _packed typedef struct u16 header; /cfg header, 固定 为 0X62B5( 小端模 式) u16 id
37、; /CFG TP ID:0X0706 ( 小端 模式) u16 dlength; / 数据长度 u32 interval; / 时钟脉冲 间隔, 单位 为 us u32 length; / 脉冲宽 度,单 位为 us signed char status; / 时钟脉冲 配置:1, 高电 平有 效;0,关闭;-1, 低电平有 效. u8 timeref; / 参考时间:0,UTC 时间;1,GPS 时间;2, 当 地时 间. u8 flags; / 时间脉冲 设置 标志 u8 reserved; / 保留 signed short antdelay; / 天线延时 signed short
38、rfdelay; /RF 延时 signed int userdelay; / 用户延时 u8 cka; / 校验 CK_A u8 ckb; / 校验 CK_B _ublox_cfg_tp; /UBLOX NEO-6M 刷 新速 率配置 结构 体 _packed typedef struct u16 header; /cfg header, 固定 为 0X62B5( 小端模 式) u16 id; /CFG RATE ID:0X0806 ( 小 端模式) u16 dlength; / 数据长度 u16 measrate; / 测量时间 间隔 , 单 位为 ms , 最少 不能 小于 200ms
39、(5Hz ) u16 navrate; / 导航速率 (周 期) ,固 定 为 1 u16 timeref; / 参考时间 :0=UTC Time ;1=GPS Time ; u8 cka; / 校验 CK_A u8 ckb; / 校验 CK_B _ublox_cfg_rate; int NMEA_Str2num(u8 *buf,u8*dx); void GPS_Analysis(nmea_msg *gpsx,u8 *buf); void NMEA_GPGSV_Analysis(nmea_msg *gpsx,u8 *buf); void NMEA_GPGGA_Analysis(nmea_msg
40、 *gpsx,u8 *buf); void NMEA_GPGSA_Analysis(nmea_msg *gpsx,u8 *buf); void NMEA_GPGSA_Analysis(nmea_msg *gpsx,u8 *buf); void NMEA_GPRMC_Analysis(nmea_msg *gpsx,u8 *buf); void NMEA_GPVTG_Analysis(nmea_msg *gpsx,u8 *buf); void Ublox_Cfg_Tp(u32 interval,u32 length,signed char status); void Ublox_Cfg_Rate(
41、u16 measrate,u8 reftime); #endif gps.h 里 面的 内容 ,都 有非 常详细 的备 注, 这里 就不 多说了 。 最后, 在 test.c 里 面, 修改 代码如 下: u8 USART1_TX_BUFUSART2_MAX_RECV_LEN; / 串口 1,发 送缓 存区 nmea_msg gpsx; /GPS 信息 _align(4) u8 dtbuf50; / 打印缓存 器 const u8*fixmode_tbl4=“Fail“,“Fail“,“ 2D “,“ 3D “; /fix mode 字符串 / 显示 GPS 定位 信息 void Gps_Ms
42、g_Show(void) float tp; POINT_COLOR=BLUE; tp=gpsx.longitude; sprintf(char *)dtbuf,“Longitude:%.5f %1c “,tp/=100000,gpsx.ewhemi); / 得到经度 字符 串 LCD_ShowString(30,130,200,16,16,dtbuf); tp=gpsx.latitude; sprintf(char *)dtbuf,“Latitude:%.5f %1c “,tp/=100000,gpsx.nshemi); / 得到纬度 字符 串 LCD_ShowString(30,150,2
43、00,16,16,dtbuf); tp=gpsx.altitude; sprintf(char *)dtbuf,“Altitude:%.1fm “,tp/=10); / 得到高度 字符 串 LCD_ShowString(30,170,200,16,16,dtbuf); tp=gpsx.speed; sprintf(char *)dtbuf,“Speed:%.3fkm/h “,tp/=1000); / 得到速度 字符 串 LCD_ShowString(30,190,200,16,16,dtbuf); if(gpsx.fixmode=3) / 定位 状态 sprintf(char *)dtbuf,
44、“Fix Mode:%s“,fixmode_tblgpsx.fixmode); LCD_ShowString(30,210,200,16,16,dtbuf); sprintf(char *)dtbuf,“Valid satellite:%02d“,gpsx.posslnum); / 用于定位 的卫 星数 LCD_ShowString(30,230,200,16,16,dtbuf); sprintf(char *)dtbuf,“Visible satellite:%02d“,gpsx.svnum%100);/ 可见卫 星数 LCD_ShowString(30,250,200,16,16,dtbu
45、f); sprintf(char *)dtbuf,“UTC Date:%04d/%02d/%02d “,gpsx.utc.year,gpsx.utc.month, gpsx.utc.date); / 显示 UTC 日期 /printf(“year2:%drn“,gpsx.utc.year); LCD_ShowString(30,270,200,16,16,dtbuf); sprintf(char *)dtbuf,“UTC Time:%02d:%02d:%02d “,gpsx.utc.hour,gpsx.utc.min, gpsx.utc.sec); / 显示 UTC 时间 LCD_ShowSt
46、ring(30,290,200,16,16,dtbuf); int main(void) u16 i,rxlen; u16 lenx; u8 key; u8 upload=0; Stm32_Clock_Init(9); / 系统时钟 设置 delay_init(72); / 延时初始 化 uart_init(72,38400); / 串口 1 初 始化 为 38400 USART2_Init(36,38400);/ 初始化 串 口 2 LED_Init(); / 初始化与 LED 连接 的硬 件接口 KEY_Init(); / 初始化与 LED 连接 的硬 件接口 LCD_Init(); /
47、初始化 LCD usmart_dev.init(72); / 初始化 USMART POINT_COLOR=RED; LCD_ShowString(30,20,200,16,16,“ALIENTEK STM32 _“); LCD_ShowString(30,40,200,16,16,“NE0-6M GPS TEST“); LCD_ShowString(30,60,200,16,16,“ATOMALIENTEK“); LCD_ShowString(30,80,200,16,16,“KEY0:Upload NMEA Data SW“); LCD_ShowString(30,100,200,16,1
48、6,“NMEA Data Upload:OFF“); while(1) delay_ms(1); if(USART2_RX_STA/ 得到数据 长度 for(i=0;irxlen;i+)USART1_TX_BUFi=USART2_RX_BUFi; USART2_RX_STA=0; / 启动下一 次接 收 USART1_TX_BUFi=0; / 自动添加 结束 符 GPS_Analysis(/ 分析字符串 Gps_Msg_Show(); / 显示信息 if(upload)printf(“rn%srn“,USART1_TX_BUF); / 接收到的 数据 发送 到串 口 1 key=KEY_Scan(0); if(key=KEY_RI