用单片机处理GPS数据---程序实例
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
程序实例
/************************************* GPS 解码 1602 显示程序
最后更新:
2007.01.27 1.2 版,改时间由 RMC 语句解码,取消日期显示
2007.01.25 1.1 版,修正定位后页面不能转换的 BUG。 1.0 版,基本功能。
***************************************/
<10>:NMEA 波特率设置。 <11>:速度过滤参数。 <12>:秒脉冲模式。 <13>:秒脉冲脉宽设置。 <14>:默认值。
排除掉对本系统无作用的管脚,实际上我们只需要用到 GARMINGPS25LP 的 Pin4和 Pin5,具体连接概图如下:
图2:单片机与 GARMINGPS25LP 硬件接口 再让我们回过头来看看显示的硬件部分设计,在开始设计前有必要对图形液晶模块的工作方式做一个简要的 说明。一个字符要在液晶模块上显示出来必须经过三个基本的控制操作: 1. 向液晶控制芯片写指令代码。 2. 象液晶控制芯片写显示数据。 3. 读显示数据。 而且在这一过程中,液晶控制器必须处于空闲状态,否则只可以对其进行读状态操作。 了这些代码我们就可以很简单的完成字符的液晶显示了,接下来是设计的最后部分,即 GARMINGPS25LP 与单片机的软件接口。 这一部分的流程如下图:
{
dsp_count++;
if(dsp_count>=65000){
LCD_cls();
//清
LCD_write_string(0,0,"No GPS connect.."); while(buf_full==0); LCD_cls(); dsp_count=0; } }
else{
//
有 GPS 信号时
//经度 //经度方向
//纬度 //纬度方向 //时间 //速度 //高度 //方位角 //使用的卫星数
unsigned char total_sat[2]; unsigned char lock;
//天空中总卫星数 //定位状态
//串口中断需要的变量 unsigned char seg_count; unsigned char dot_count; unsigned char byte_count; unsigned char cmd_number; unsigned char mode; 模式,2:数据模式 unsigned char buf_full; 有效。0:缓存数据无效。 unsigned char cmd[5];
1. GPS 标准数据(GGA)
$GPGGA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,M,<10>,M,<11>,<12>,*hh<CR><LF> <1>:UTC 当地时间,时分秒格式。 <2>:纬度,ddmm.mmmm 格式。 <3>:纬度半球,N 或者 S。 <4>:经度,ddmm.mmmm 格式。 <5>:经度半球,E 或者 W。 <6>:GPS 质量参数。 <7>:可用卫星数,00~12。 <8>:水平精度,0.5~99.9。 <9>:天线上下平均海拔,-999.9~99999.9 米。 <10>:海拔高度,-999.9~9999.9 米。 <11>:差分 GPS 数据传输间隔时间,单位秒,在非差分模式下为空。 <12>:差分基准站 ID,非差分为空。 2. 推荐最小 GPS/TRANSIT 数据(RMC) $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh<CR><LF> <1>:UTC 当地时间,时分秒格式。 <2>:工作状态,A=可用;V=接收器警报,不可用。 <3>:纬度,ddmm.mmmm 格式。 <4>:纬度半球,N 或者 S。 <5>:经度,ddmm.mmmm 格式。 <6>:经度半球,E 或者 W。 <7>:对地速度,000.0~999.9 节。 <8>:对地航向,000.0°~359.9° <9>:UTC 当地时wk.baidu.com,ddmmyy 格式。 <10>:磁变。 <11>:磁变方向。 <12>:工作模式,A=自主,D=差分,E=评估,N=数据无效。 3.3D 速度信息(PGRMV) $PGRMV,<1>,<2>,<3>*hh<CR><LF> <1>:真实东向速度。 <2>:真实北向速度。 <3>:垂直速度。 4. 出语句激活/屏蔽语句(PGRMO) $PGRMO<1>,<2>*hh<CR><LF> <1>:目标语句名。 <2>:目标语句状态参数。 5. GPS 板设置语句(PGRMC) $PGRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>,<14>*hh<CR><LF> <1>:工作模式。 <2>:海拔高度。 <3>~<8>:地球数据索引。 <9>:差分模式参数。
图5:主程序流程 在处理主程序前,有必要先将串口中断服务程序先给出,具体代码如下: serial() interrupt 4 using 1 { RI=0; If(SBUF==0x24) /*判断是否有 GPS 数据到来。 0x24为西文字符$的 ASCII 码。 { record=1; i=0; igps=0; Numbercoma=0; } if(record==1) { if(SBUF==0x2c){numbercoma++;} if(numbercoma==1) /*因 UTC 紧跟在第一个逗号后,故记录到第一个逗号后就开始记录时间数据。 { stringgps[igps]=SBUF; igps++; } if(SBUF==’*’) /*判断 GPRMC 数据是否结束。
#include <reg2051.h> #include "1602.h"
sbit GPS_SPD=P1^1; sbit SPD_TYPE=P1^0; sbit KEY1=P3^7;
/* sbit GPS_SPD=P1^4; sbit KEY1=P1^6; sbit SPD_TYPE=P1^5; */
{ stringgps[igps]=’\0’; /*为字符串添加结束标志。 j=0; len2=spintf(stringgps,”%s”,stringgps+1); NDIG=sprintf(BUFFER,”k1:%d”,k1); Show(); If(len2!=0) { uint numgps=atoi(stringgps); } numgps=0; numbercoma=0; record=0; igps=0; } } } 这里我们可以看出,单片机仅会记录第一个逗号后的数据(数据被存在数据缓冲区 BUFFER 中,即 UTC 本地 时间数据,因此在主程序中我们需要考虑的问题就是触发串口中断,并将收到的数据送液晶显示。 主程序的代码如下: #include <stdio.h> #include <absacc.h> #include <reg51.h> #define uchar unsigned char #define uint unsigned int void INITIAL(void); /*显示初始化。 void CLEAR(void); /*清屏。 void locate(uchar page,uchar column); /*定义初始显示内容。 void show(void); char data BUFFER[15]; uchar data NDIG; int xdata sumup=0; uchar idata stringgps[8]; uint k,i,j,k1; uint record,number; uint igps; uint numbercoma; uint len1,len2,len3; uint numgps;
if(chk_key()){
//
检测到按键切换显示
page=!page;
LCD_cls();
}
if(!page){
//页面 1
if(buf_full|0x01){
//GGA 语句
if(lock=='0'){
//如果未定位
LCD_write_string(0,0,"*---.--.---- ");
--.--.---- ");
unsigned
char
code
info[]={
'D'^0xab,'e'^0xab,'s'^0xab,'i'^0xab,'g'^0xab,'n'^0xab,'
'^0xab,'b'^0xab,
'y'^0xab,'
'^0xab,'B'^0xab,'G'^0xab,'4'^0xab,'U'^0xab,'V'^0xab,'R'^0xab,};
void main(void) { TMOD=0x20; /*串口初始化。 TL1=0xfd; TH1=0xfd; SCON=0x50; PCON=0x00; IE=0x90; TR1=1; P1_0=0; INITIAL(); /*显示初始化。 CLEAR(); Locate(3,4); NDIG=sprintf(BUFFER,”sumup=rdy”); Show(); Sumup=12345; Locate(2,4); NDIG=sprintf(BUFFER,”sumup=%d”,sumup); Show(); } for(;;) { locate(0,2); NDIG=sprintf(BUFFER,”k1=%d”,k1); Show(); } } 从主程序代码不太容易看出代码的执行结果,但通过前面的流程图我们就很好理解这一代码了。主程序在开 始执行后会对液晶模块和串口中断进行初始化。随后单片机会进入死循环直到 GARMINGPS25LP 的数据触发 串口中断。串口中断服务程序会对接收到的数据进行必要的转换处理并最终送液晶模块显示。实际使用中 GARMINGPS25LP 是以固定的频率不断发送数据的,故实际的液晶显示内容为不断刷新的时间内容。这样就 达到了我们的设计目的。如果数据刷新过快导致时间显示不稳定,可以考虑加入延时丢弃部分数据包。 这篇文章主要讨论的是 GPS 时钟的设计,故对于 LCD 和单片机的周边电路并没有进行详细的讨论。本设计 的程序规模并不大,完全可以采用内置 ROM 的单片机实现,故系统在管脚资源上是相当宽裕的,必要的话 还可以通过外部扩展引入键盘。
char code TIME_AREA= 8;
//时区
//GPS 数据存储数组 unsigned char JD[10]; unsigned char JD_a; unsigned char WD[9]; unsigned char WD_a; unsigned char time[6]; unsigned char speed[5]; unsigned char high[6]; unsigned char angle[5]; unsigned char use_sat[2];
//刷新次数计数器
void sys_init(void); bit chk_key(void);
main() {
unsigned char i; char Bhour; unsigned int Knots; sys_init();
信号时 屏
while(1){ if(buf_full==0)
//无 GPS
//逗号计数器 //小数点计数器 //位数计数器
//命令类型 //0:结束模式,1:命令
//1:整句接收完成,相应数据
//命令类型存储数组
//显示需要的变量 unsigned int dsp_count; unsigned char time_count; bit page; bit spd_type;
}else{ //如果已定位
LCD_write_string(0,1,"*
LCD_write_char(0,0,JD_a);
//显示经度 for(i=0;i<3;i++){
LCD_write_char(i+1,0,JD[i]);
} LCD_write_char(4,0,'.'); for(i=3;i<10;i++){