淘宝上有2手的100元左右,转贴个汇编的程序,
gps卫星定位导航系统 51单片机资料
一、gps接受的数据(在pc串口上的显示)(3月1日)
$gpgga,000002.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*7d
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gprmc,000002.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*0f
$gpgga,000003.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*7c
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gprmc,000003.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*0e
$gpgga,000004.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*7b
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gprmc,000004.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*09
$gpgga,000005.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*7a
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gprmc,000005.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*08
$gpgga,000006.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*79
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gpgsv,1,1,01,03,00,000,00*4b
$gprmc,000006.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*0b
$gpgga,000007.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*78
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gprmc,000007.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*0a
$gpgga,000008.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*77
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gprmc,000008.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*05
$gpgga,000009.999,0000.0000,n,00000.0000,e,0,00,50.0,0.0,m,0.0,m,0.0,0000*76
$gpgsa,a,1,,,,,,,,,,,,,50.0,50.0,50.0*05
$gprmc,000009.999,v,0000.0000,n,00000.0000,e,0.00,,270920,,*04
*******************************************************************二、文中涉及gprmc特定精简资料信息的采集,分析如下:
$gprmc、 <1>、 <2>、<3>、<4>、<5>、<6>、<7>、<8>、<9>、<10>、<11>、*hh<cr><lf>
$gprmc,204700,a,3403.868,n,11709.432,w,001.9,336.9,170698,013.6,e*6e
例:$gprmc,112720.000,a,3639.2868,n,11659.8396,e,,,200305,,*12
$gprmc,235958.999,v,0000.0000,n,00000.0000,e,0.00,,260920,,*0c
区域 名称 例 单位 说明
1 信息id $gprmc rmc协议开始
2 utc时间 112720.000 格林威治
3 状态 a (资料有效)
4 纬度 3639.2868 纬度信息
5 南/北半球指示 n n为北半球
6 经度 11659.8396 经度信息
7 东/西半球指示 e 东半球
8 速度
9 方向
10 日期 200305
11 磁极变量度
三.串口工作原理
stc89c51单片机只有一个uart异步串行通信接口,而在此设计中,不但要求系统提供一个工作在9600bps的串行口与gtm-900进行数据的交换,而且还需要一个串行口工作在4800bps采集gps设备传送回来的数据和一个串行口工作在9600bps发送内码给语音芯片xf-s3011。根据上述需要,除了单片机的串行口与gtm-900连接进行高速稳定的数据交换进行控制外,还需要用单片机的i/o口模拟一个工作在4800bps的串行口和一个工作在9600bps的串行口。
我在编程时,应用了中断口线0模拟了一个接受串口。应用了定时器t0进行了一位的等待时间。
异步通信是字符的同步传输技术。在异步通讯中,传输的数据以字符(character)为单位。当发送一个字符代码时,字符前面要加一个“起始”信号,其长度为一位,极性为“0”,即空号(space)状态;规定在线路不传输数据时全部为“1”,即传号(mark)状态。字符后面要加一个“停止”信号,其长度为1,1.5,或2位,极性为“1”。字符本身的长度为5~8位数据,视传输的数据格式而定。
例如:
起始位占用一位(低电平0),表示字符开始,传送的数据(或字符)用ascii码表示时,其长度为8位,最后为停止位(高电平1),用来表示字符传送结束,上述字符格式通常作为一个串行帧,属于“n,8,1”帧格式。起始位和停止位用来区分字符,传送时,字符可以连续发送,也可以断续发送。不发送字符时线路保持“1” 状态。字符发送的顺序为先低位后高位。
串行通信中,波特率(band rate)定义为每秒钟传送二进制码的位数(亦称比特数),单位是bps(bit per second),即 位/秒 。波特率是串行通信的重要指标,用于表示数据传输的速度。波特率越高,数据传输速度越快,但和字符的实际传输速率不同,字符的实际传输速率是指每秒钟内所传字符帧的帧数,与字符帧格式有关,如果数据传送的波特率为4800bps,采用n,8,1帧格式(10位),则每秒传送字节为480个字,而字节中每一位传送时间即为波特率的倒数。
t=1/4800=0.208ms
在此,必须强调 “时序” 和 “格式” ,这两者决定rs-232通信的关键。无论是发送还是接收,其传输的数据都要符合这两项规定。所谓的rs-232通信,实际就是一些规定格式的高低电平的传递,而单片机正是处理这些电平的有利工具,这就是为单片机使用i/o端口模拟串口提供了基本的依据。
3.3 nmea-0183协议
gr-85模块支持nmea-0183输出格式,波特率默认值为4800bps,1个起始位,8个数据位,1个停止位,无奇偶校验,数据代码为ascii码字符。nmea-0183是美国海洋电子协会为海用电子设备制定的标准格式,目前广泛使用v2.0版本。由于该格式为ascii码字符串,比较直观和易于处理,在许多编程语言中都可以直接进行判别、分离,以提取用户所需要的数据。gm-305系列接收机可输出6句语句,其中较常用的4种为gga, gsv, rmc, vtg,不同的语句传送不同的信息:
gga位置测定系统定位资料(global positioning system fix data)
gsv 导航卫星资料(gnss satellites in view)
rmc导航卫星特定精简资料(recommended minimum specific gnss data)
vtg 方向及速度等相关资料(course over ground and ground speed)
文中涉及gprmc特定精简资料信息的采集,详细的分析如下:
$gprmc、<1>、<2>、<3>、<4>、<5>、<6>、<7>、<8>、<9>、<10>、<11>、*hh<cr><lf>
例:$gprmc,112720.000,a,3639.2868,n,11659.8396,e,,,200305,,*12
区域 名称 例 单位 说明
1 信息id $gprmc rmc协议开始
2 utc时间 112720.000 格林威治
3 状态 a (资料有效)
4 纬度 3639.2868 纬度信息
5 南/北半球指示 n n为北半球
6 经度 11659.8396 经度信息
7 东/西半球指示 e 东半球
8 速度
9 方向
10 日期 200305
11 磁极变量度
上面例子中我们可读出位置信息:
北纬36度39.2868分,东经116度59.8396分
格林威治时间:11点27分20秒
日期:2005年3月20日
四、 gps数据的接收
gps接收机只要处于工作状态就会源源不断地把接收并计算出的gps导航定位信息通过串口传送到单片机中。其发送到单片机的数据主要由帧头、帧尾和帧内数据组成,根据数据帧的不同,帧头也不相同,主要有"$gpgga"、"$gpgsa"、"$ gpgsv"以及"$gprmc"等。这些帧头标识了后续帧内数据的组成结构,各帧均以回车符和换行符作为帧尾标识一帧的结束。对于通常的情况,用户所需要的定位数据如经纬度、速度、时间等均可以从“$gprmc”帧中获取得到。
;检测到$gprmc,字符串---------------------
判断完我们所需要的帧头,其帧头后面的信息就是我们所需要的数据,单片机要将其接收并存放在ram中,以便后面的程序调用。
4.3gps数据的提取
gps接收到的数据存放在ram中,它只是一长串字节流,这些信息在没有经过分类提取之前是无法加以利用的。因此,必须通过程序将各个字段的信息从缓存字节流中提取出来,将其转化成有实际意义的数据,为后面的程序提供卫星定位信息。
例如,接收到的gps数据为:
$gprmc,112720.000,a,3639.2868,n,11659.8396,e,,,200305,,*12
将其存放于30h开始的单元中:
$gprmc,235958.999,v,0000.0000,n,00000.0000,e,0.00,,260920,,*0c
$gprmc,204700,a,3403.868,n,11709.432,w,001.9,336.9,170698,013.6,e*6e
20h 21h 22h 23h 24h 25h 26h 27h 28h 29h 2ah 2bh 2ch 2dh 2eh 2fh 30h
2 3 5 9 5 8 . 9 9 9 v 0 0 0 0 . 0
utc时间 无效 纬度信息
31h 32h 33h 34h 35h 36h 37h 38h 39h 3ah 3bh 3ch 3dh 3eh 3fh 40h 41h
0 0 0 , n 0 0 0 0 . 0 0 0 0 , e ,
纬度信息 南/北半球指示 经度信息 东/西半球指示
42h 43h 44h 45h 46h 47h 48h 49h 4ah 4bh 4ch 4dh 4eh 4fh 50h 51h 52h
0 0 1 . 9 , 3 3 6 . 9 , 1 7 0 6 9
速度信息 方向 日期
53h
8
程序代码:
;*******************************************************************************************
;单位:山东源浩信息技术有限公司
;功能:gps接受、数据存储程序
;日期:2006年3月3日
;********************************************************************************************
;数据存储在了30h-63h中
;*********************标志位定义*****************************************************
fg_receive_frame bit 00h ; 帧头接受完毕标志位
fg_receive_over bit 01h ;数据接受完成的标志位
;*******************标志位定义完成***************************************************
;********************寄存器定义******************************************************
receive_frame_count data 64h ;接受帧头中字符的计数器
receive_data_adress data 65h ;接受数据的存储地址单元
;*****************寄存器定义完成*****************************************************
;********************口线定义********************************************************
a_rxd bit p3.2 ;定义a_rxd为外部中断int0(引脚p3.2);
;******************口线定义完成******************************************************
;********************程序开始***************************************************
org 0000h
reset: ajmp main
org 0003h ;外部中断int0的入口地址
ajmp i0_gps4800;
nop;
nop;
;org 000bh;定时器t0的中断入口地址
;org 0013h;外部中断int1的入口地址
;org 001bh;定时器t1的中断入口地址
;org 0023h;串口的中断入口地址
org 0100h
;*********************gps4800接收的中断处理**************************************
i0_gps4800:
clr ex0 ;关中断int0
lcall gps4800 ;调用gps4800子程序
jb fg_receive_over,i0_gps4800_next;判断fg_receive_over,当数据接收完标志为1时跳到i0_gps4800_next
;否则,开中断int0
setb ex0
jmp i0_gps4800_reti
i0_gps4800_next:
clr ex0
i0_gps4800_reti:
reti ;中断返回
;*********************int0中断口处理完成*****************************************
;***********************gps接受子程序***********************************************
gps4800:
l_rec_frame_0:
jb fg_receive_frame,start1;判断帧头接收标志位,若为1,则开始接收数据(start1)
mov a,receive_frame_count ;将帧头接收到的正确字节个数给a
cjne a,#0,l_rec_frame_1 ;判断a是否为0,若是,则接收第1个字节;否则跳入l_rec_frame_1
lcall r_byte ;模拟串口接收一个字节
cjne a,#24h,start0 ;判断是否是'$',若是则继续接收帧头;否则跳入start0
inc receive_frame_count ;将帧头接收字节个数加1
ljmp gps4800_ret ;程序返回
l_rec_frame_1:
cjne a,#1,l_rec_frame_2 ;判断a是否为1,若是,则接收第2个字节;否则跳入l_rec_frame_2
lcall r_byte
cjne a,#47h,start0 ;判断是否是'g',若是则继续接收帧头;否则跳入start0
inc receive_frame_count
ljmp gps4800_ret
l_rec_frame_2:
cjne a,#2,l_rec_frame_3 ;判断a是否为2,若是,则接收第3个字节;否则跳入l_rec_frame_3
lcall r_byte
cjne a,#050h,start0 ;判断是否是'p',若是则继续接收帧头;否则跳入start0
inc receive_frame_count
ljmp gps4800_ret
l_rec_frame_3:
cjne a,#3,l_rec_frame_4 ;判断a是否为3,若是,则接收第4个字节;否则跳入l_rec_frame_4
lcall r_byte
cjne a,#052h,start0 ;判断是否是'r',若是则继续接收帧头;否则跳入start0
inc receive_frame_count
ljmp gps4800_ret
l_rec_frame_4:
cjne a,#4,l_rec_frame_5 ;判断a是否为4,若是,则接收第个5字节;否则跳入l_rec_frame_5
lcall r_byte
cjne a,#04dh,start0 ;判断是否是'm',若是则继续接收帧头;否则跳入start0
inc receive_frame_count
ljmp gps4800_ret
l_rec_frame_5:
cjne a,#5,l_rec_frame_6 ;判断a是否为5,若是,则接收第6个字节;否则跳入l_rec_frame_6
lcall r_byte
cjne a,#043h,start0 ;判断是否是'c',若是则继续接收帧头;否则跳入start0
inc receive_frame_count
ljmp gps4800_ret
l_rec_frame_6:
cjne a,#6,start0 ;判断a是否为6,若是,则接收第7个字节;否则跳入start0
lcall r_byte
cjne a,#02ch,start0 ;判断是否是',',若是则继续接收帧头;否则跳入start0
setb fg_receive_frame ;置fg_data_rec为1,表示'$gprmc,'已经接收完毕
mov receive_frame_count,#0 ;将帧头接收计数器清零
mov receive_data_adress,#30h ;将存储接收数据的地址给receive_data_adress
ljmp gps4800_ret ;程序返回
start1:
mov r0, receive_data_adress
lcall r_byte
mov @r0,a ;将数据放入ram对应单元中去
inc receive_data_adress ;将数据地址加1,为存储下一个数据做好准备
mov a,receive_data_adress
cjne a,#64h,gps4800_ret ;判断数据是否接收完成
clr fg_receive_frame ;
setb fg_receive_over ;若接收完成,则将帧头标志清零,将数据接收完成标志置1
ljmp gps4800_ret
start0: mov receive_frame_count,#00h ;若没有接收完'$gprmc,'则将帧头接收字节数清零
gps4800_ret:
ret
;***********************************************************************************************************
;********************模拟串口接受一个字节的程序r_byte*******************************************************
r_byte:
clr tf0
jb a_rxd,$
mov tl0,#35h
setb tr0 ;打开定时器t0
jnb tf0,$ ;等待起始位结束
mov r7,#08h ;起始位结束后开始接收串行的数据
r_loop:
jnb tf0,$
clr tf0
mov c,a_rxd ;将a_rxd的状态读到a中
rrc a
mov tl0,#3bh ;定时器置初值
djnz r7,r_loop ;循环接收八位字节
jnb a_rxd,$ ; 等待停止位
clr tr0
ret
;**************************模拟串口接受一个字节的程序完成*****************************************************
main:
mov sp, #70h;
anl tmod, #0f0h
orl tmod, #02h ;设置定时器t0工作在方式2
anl tcon, #0feh;
orl tcon, #01h ;设置外部中断int0为跳沿触发方式;
mov receive_frame_count,#0 ;对帧头接收字节个数计数器清零
clr fg_receive_frame ;对帧头接收标志清零
clr fg_receive_over ;对数据接收完标志清零
mov th0,#40h
mov tl0,#40h
;每一位的延续时间t=1/4800=2.08*(10-4)s;定时器记数次数n=t/t=192
;t=1/(11059200/12)s,所以定时器初值=256-192=64=40h
setb ex0 ;打开外部中断int0
setb ea ;打开中断
next1: jmp $
end