|
公布我的GPS源代码
.net论坛的gps气氛挺浓,决定公开最后一版的gps程序源代码。原来没打算公布的原因是,本程序仍然存在不少不足。现在本人已经转向avr了,不打算再搞51了。现在把我的源代码公布出来,希望对用到的人有些帮助。也希望其他朋友能够完善他,并公布给大家使用。 另外建议,如果需要对程序进行更改,希望先仔细理解我的程序的思路,以尽量少走弯路。 对应的电路图、hex文件、和说明文件,见附件的pdf。 本程序的主程序,全部是本人原创完成。4bit的1602驱动,修改于网上的程序,见作者已经不详。 主程序: - /*************************************
- gps解码1602显示程序
- 作者:bg4uvr
- 最后更新:
- 2007.01.27
- 1.2版,改时间由rmc语句解码,取消日期显示
- 2007.01.25
- 1.1版,修正定位后页面不能转换的bug。
- 1.0版,基本功能。
- ***************************************/
- #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;
- */
- //各位见笑了,加密存储开机版权信息。免得被人改目标代码 :d
- 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,Ɗ'^0xab,'u'^0xab,'v'^0xab,'r'^0xab,};
- 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]; //使用的卫星数
- 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; //0:结束模式,1:命令模式,2:数据模式
- unsigned char buf_full; //1:整句接收完成,相应数据有效。0:缓存数据无效。
- unsigned char cmd[5]; //命令类型存储数组
- //显示需要的变量
- unsigned int dsp_count; //刷新次数计数器
- unsigned char time_count;
- bit page;
- bit spd_type;
- 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信号时
- {
- 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信号时
- if(chk_key()){ //检测到按键切换显示
- page=!page;
- lcd_cls();
- }
- if(!page){ //页面1
- if(buf_full|0x01){ //gga语句
- if(lock==Ɔ'){ //如果未定位
- lcd_write_string(0,0,"*---.--.---- ");
- lcd_write_string(0,1,"* --.--.---- ");
- }else{ //如果已定位
- 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++){
- lcd_write_char(i+2,0,jd[i]);
- }
- lcd_write_char(0,1,wd_a); //显示纬度
- lcd_write_char(1,1,' ');
- for(i=0;i<2;i++){
- lcd_write_char(i+2,1,wd[i]);
- }
- lcd_write_char(4,1,'.');
- for(i=2;i<9;i++){
- lcd_write_char(i+3,1,wd[i]);
- } }
- lcd_write_char(14,0,use_sat[0]); //显示接收卫星数
- lcd_write_char(15,0,use_sat[1]);
- buf_full&=~0x01;
- dsp_count=0;
- }
- if(buf_full|0x02){ //gsv语句
- lcd_write_char(14,1,total_sat[0]);
- lcd_write_char(15,1,total_sat[1]);
- buf_full&=~0x02;
- dsp_count=0;
- }
- if(buf_full|0x04){
- buf_full&=~0x04;
- dsp_count=0;
- }
- }
- else{ //页面2
- if(buf_full|0x01){ //gga语句
- buf_full&=~0x01;
- dsp_count=0;
- }
- if(buf_full|0x02){
- buf_full&=~0x02;
- dsp_count=0;
- }
- if(buf_full|0x04){ //rmc语句
- bhour=((time[0]-0x30)*10+time[1]-0x30)+time_area;
- if(bhour>=24){
- bhour-=24;
- }else if(bhour<0){
- bhour+=24;
- }
- lcd_write_string(2,1,"bjt ");
- lcd_write_char(6,1,bhour/10+0x30);
- lcd_write_char(7,1,bhour%10+0x30);
- lcd_write_char(8,1,':');
- lcd_write_char(9,1,time[2]);
- lcd_write_char(10,1,time[3]);
- lcd_write_char(11,1,':');
- lcd_write_char(12,1,time[4]);
- lcd_write_char(13,1,time[5]);
- if(spd_type){
- lcd_write_string(5,0,"km/h a");
- }else{
- lcd_write_string(5,0,"knot a");
- }
- if(lock==Ɔ'){ //如果未定位
- lcd_write_string(0,0,"---.-");
- lcd_write_string(11,0,"---.-");
- }else{ //已经定位
- if(spd_type){ //km/h显示
- for(i=0;i<5;i++){
- lcd_write_char(i,0,speed[i]);
- }
- }else{ //knot显示
- knots= (((speed[0]-0x30)*1000
- +(speed[1]-0x30)*100
- +(speed[2]-0x30)*10
- +(speed[4]-0x30))*1000)/1852;
- lcd_write_char(0,0,knots/1000+0x30);
- lcd_write_char(1,0,(knots%1000)/100+0x30);
- lcd_write_char(2,0,(knots%100)/10+0x30);
- lcd_write_char(3,0,'.');
- lcd_write_char(4,0,knots%10+0x30);
- }
- for(i=0;i<5;i++){
- lcd_write_char(11+i,0,angle[i]);
- }
- }
- buf_full&=~0x04;
- dsp_count=0;
- }
- }
- }
- }
- }
- bit chk_key(void)
- {
- if(!key1){
- delayms(10);
- if(!key1){
- while(!key1);
- delayms(10);
- return(1);
- }
- }
- return(0);
- }
- //系统初始化
- void sys_init() {
- unsigned char i;
- scon = 0x50; /* scon: mode 1, 8-bit uart, enable rcvr */
- tmod = 0x21; /* tmod: timer 1, mode 2, 8-bit reload */
- if(gps_spd){
- th1 = 0xfd; /* th1: reload value for 9600 baud @ 11.059mhz */
- }else{
- th1 = 0xfa; /* th1: reload value for 4800 baud @ 11.059mhz */
- }
- if(spd_type){
- spd_type=1; //速度单位km/h
- }else{
- spd_type=0; //速度单位knot
- }
- tr1 = 1; /* tr1: timer 1 run */
- lcd_init(); //初始化lcd
- lcd_write_string(0,0,"gps monitor v1.2");
- for(i=0;i<16;i++){ //显示版权信息
- lcd_write_char(i,1,info[i]^0xab);
- }
- for(i=1;i<4;i++){
- delayms(250);
- }
- lcd_cls();
- ie=0x90; //开总中断、串口中断
- }
- //串口接收中断
- void uart(void) interrupt 4
- {
- unsigned char tmp;
- if(ri){
- tmp=sbuf;
- switch(tmp){
- case '$':
- cmd_number=0; //命令类型清空
- mode=1; //接收命令模式
- byte_count=0; //接收位数清空
- break;
- case ',':
- seg_count++; //逗号计数加1
- byte_count=0;
- break;
- case '*':
- switch(cmd_number){
- case 1:
- buf_full|=0x01;
- break;
- case 2:
- buf_full|=0x02;
- break;
- case 3:
- buf_full|=0x04;
- break;
- }
- mode=0;
- break;
- default:
- if(mode==1){
- //命令种类判断
- cmd[byte_count]=tmp; //接收字符放入类型缓存
- if(byte_count>=4){ //如果类型数据接收完毕,判断类型
- if(cmd[0]=='g'){
- if(cmd[1]=='p'){
- if(cmd[2]=='g'){
- if(cmd[3]=='g'){
- if(cmd[4]=='a'){
- cmd_number=1;
- mode=2;
- seg_count=0;
- byte_count=0;
- }
- }
- else if(cmd[3]=='s'){
- if(cmd[4]=='v'){
- cmd_number=2;
- mode=2;
- seg_count=0;
- byte_count=0;
- }
- }
- }
- else if(cmd[2]=='r'){
- if(cmd[3]=='m'){
- if(cmd[4]=='c'){
- cmd_number=3;
- mode=2;
- seg_count=0;
- byte_count=0;
- }
- }
- }
- }
- }
- }
- }
- else if(mode==2){
- //接收数据处理
- switch (cmd_number){
- case 1: //类型1数据接收。gpgga
- switch(seg_count){
- case 2: //纬度处理
- if(byte_count<9){
- wd[byte_count]=tmp;
- }
- break;
- case 3: //纬度方向处理
- if(byte_count<1){
- wd_a=tmp;
- }
- break;
- case 4: //经度处理
- if(byte_count<10){
- jd[byte_count]=tmp;
- }
- break;
- case 5: //经度方向处理
- if(byte_count<1){
- jd_a=tmp;
- }
- break;
- case 6: //定位判断
- if(byte_count<1){
- lock=tmp;
- }
- break;
- case 7: //定位使用的卫星数
- if(byte_count<2){
- use_sat[byte_count]=tmp;
- }
- break;
- case 9: //高度处理
- if(byte_count<6){
- high[byte_count]=tmp;
- }
- break;
- }
- break;
- case 2: //类型2数据接收。gpgsv
- switch(seg_count){
- case 3: //天空中的卫星总数
- if(byte_count<2){
- total_sat[byte_count]=tmp;
- }
- break;
- }
- break;
- case 3: //类型3数据接收。gprmc
- switch(seg_count){
- case 1:
- if(byte_count<6){ //时间处理
- time[byte_count]=tmp;
- }
- break;
- case 7: //速度处理
- if(byte_count<5){
- speed[byte_count]=tmp;
- }
- break;
- case 8: //方位角处理
- if(byte_count<5){
- angle[byte_count]=tmp;
- }
- break;
- }
- break;
- }
- }
- byte_count++; //接收数位加1
- break;
- }
- }
- ri=0;
- }
- /*
- $gpgga,024518.00,3153.7225,n,12111.9951,e,1,04,1.48,-00009,m,007,m,,*4c
- $gpgll,3153.7225,n,12111.9951,e,024518.00,a,a*63
- $gpvtg,000.0,t,004.7,m,000.0,n,000.0,k,a*20
- $gpgsa,a,2,04,08,17,20,,,,,,,,,1.48,1.48,0.03*08
- $gpgsv,2,1,08,04,15,231,38,08,29,218,42,11,49,043,,19,09,082,*76
- $gpgsv,2,2,08,27,14,198,29,28,71,316,,17,32,300,36,20,45,124,43*70
- $gprmc,024518.00,a,3153.7225,n,12111.9951,e,000.0,000.0,280107,04.7,w,a*12
- $gpzda,024519.45,28,01,2007,,*62
- $gpgga,024519.00,3153.7225,n,12111.9951,e,1,04,1.48,-00009,m,007,m,,*4d
- $gpgll,3153.7225,n,12111.9951,e,024519.00,a,a*62
- $gpvtg,000.0,t,004.7,m,000.0,n,000.0,k,a*20
- $gpgsa,a,2,04,08,17,20,,,,,,,,,1.48,1.48,0.03*08
- $gpgsv,2,1,08,04,15,231,38,08,29,218,42,11,49,043,,19,09,082,*76
- $gpgsv,2,2,08,27,14,198,29,28,71,316,,17,32,300,36,20,45,124,43*70
- $gprmc,024519.00,a,3153.7225,n,12111.9951,e,000.0,000.0,280107,04.7,w,a*13
- $gpzda,024520.49,28,01,2007,,*64
- $gpgga,024520.00,3153.7225,n,12111.9951,e,1,04,1.48,-00009,m,007,m,,*47
- $gpgll,3153.7225,n,12111.9951,e,024520.00,a,a*68
- $gpvtg,000.0,t,004.7,m,000.0,n,000.0,k,a*20
- $gpgsa,a,2,04,08,17,20,,,,,,,,,1.48,1.48,0.03*08
- $gpgsv,2,1,08,04,15,231,38,08,29,218,42,11,49,043,,19,09,082,*76
- $gpgsv,2,2,08,27,14,198,,28,71,316,,17,32,300,36,20,45,124,43*7b
- $gprmc,024520.00,a,3153.7225,n,12111.9951,e,000.0,000.0,280107,04.7,w,a*19
- $gpzda,024521.45,28,01,2007,,*69
- */
1602的驱动程序 - /*
- sbit lcd_db4= p0^4;
- sbit lcd_db5= p0^5;
- sbit lcd_db6= p0^6;
- sbit lcd_db7= p0^7;
- sbit lcd1602_rs=p2^0;
- sbit lcd1602_rw=p2^1;//实际上没有读lcm,rw脚可以直接接地
- sbit lcd1602_en=p2^2;
- */
- sbit lcd_db4= p1^4;
- sbit lcd_db5= p1^5;
- sbit lcd_db6= p1^6;
- sbit lcd_db7= p1^7;
- sbit lcd1602_rs=p1^3;
- //sbit lcd1602_rw=0;//实际上没有读lcm,rw脚可以直接接地
- sbit lcd1602_en=p1^2;
- void lcd_write_char( unsigned x,unsigned char y,unsigned char dat); //在指定位置显示字符
- void lcd_write_string(unsigned char x,unsigned char y,unsigned char *s);//在指定位置显示字符串
- void lcd_cls(void);//清屏
- void lcd_en_command(unsigned char command);
- void lcd_en_dat(unsigned char temp);
- void lcd_set_xy( unsigned char x, unsigned char y );
- void lcd_init(void);
- void set_lcd(unsigned char io_temp);
- void delayms(unsigned char ms);
- void lcddelay(void);
- unsigned char lcdio;
- void lcd_cls(void)
- {
- lcd_en_command(0x01);
- delayms(2);
- }
- void lcd_en_command(unsigned char command)
- {
- lcd1602_rs=0;
- // lcd1602_rw=0;
- lcd1602_en=0;
- lcdio=(command & 0xf0);
- set_lcd(lcdio);
- lcd1602_en=1;
- lcddelay();
- lcd1602_en=0;
- lcdio=(command & 0x0f)<<4;
- set_lcd(lcdio);
- lcd1602_en=1;
- lcddelay();
- lcd1602_en=0;
- }
- void set_lcd(unsigned char io_temp)
- {
- lcd_db7=io_temp&0x80;
- lcd_db6=io_temp&0x40;
- lcd_db5=io_temp&0x20;
- lcd_db4=io_temp&0x10;
- }
- void lcd_en_dat(unsigned char dat)
- {
- lcd1602_rs=1;
- // lcd1602_rw=0;
- lcd1602_en=0;
- lcdio=(dat & 0xf0);
- set_lcd(lcdio);
- lcd1602_en=1;
- lcddelay();
- lcd1602_en=0;
- lcdio=(dat & 0x0f)<<4;
- set_lcd(lcdio);
- lcd1602_en=1;
- lcddelay();
- lcd1602_en=0;
- }
- void lcd_set_xy( unsigned char x, unsigned char y )
- {
- unsigned char address;
- if (y ==0)
- address = 0x80 + x;
- else
- address = 0xc0 + x;
- lcd_en_command(address);
- }
- void lcd_write_char( unsigned x,unsigned char y,unsigned char dat)
- {
- lcd_set_xy( x, y );
- lcd_en_dat(dat);
- }
- void lcd_write_string(unsigned char x,unsigned char y,unsigned char *s)
- {
- lcd_set_xy( x, y ); //set address
- while (*s) // write character
- {
- lcdio=*s;
- set_lcd(lcdio);
- lcd_en_dat(*s);
- s ++;
- }
- }
- void lcd_init(void)
- {
- lcd_en_command(0x33);
- delayms(20);
- lcd_en_command(0x32);
- delayms(20);
- lcd_en_command(0x08);
- delayms(5);
- lcd_en_command(0x01);
- delayms(5);
- lcd_en_command(0x06);
- delayms(5);
- lcd_en_command(0x0c);
- delayms(5);
- }
- void delayms(unsigned char ms)
- {
- unsigned char i;
- while(ms--)
- {
- for(i = 0; i < 115; i++);
- }
- }
- void lcddelay(void)
- {
- unsigned char i;
- for(i = 0; i < 2; i++);
- }
|