主程序
- #include<reg52.h>
- #include<stdio.h>
- #include<string.h>
- #include"GPS.H"
- #include"LCD.H"
- #include"DISPLAY.H"
- char xdata rev_buf[80]; //接收緩存
- uchar xdata rev_start=0; //接收開始標志
- uchar xdata rev_stop=0; //接收停止標志
- uchar xdata gps_flag=0; //GPS處理標志
- uchar xdata change_page=0; //換頁顯示標志
- uchar xdata num=0;
- void Uart_Init(void)
- {
- TMOD=0x21;//0010 0001
- PCON=0X00;
- TH0=0x3c;
- TL0=0xb0;
- TH1=0xFA;//1111 1010
- TL1=0xFA;//1111 1010
- TR1=1; //開啟定時器1
- REN=1; //允許接收數據
- SM0=0;
- SM1=1;
- TI=0;
- RI=0;
- EA=1;//開總中斷
- ES=1;//串口1中斷允許
- ET0=1;//定時器1中斷允許
- }
- void main(void)//主函數
- {
- uchar error_num=0;
- Lcd_Init();//初始化LCD
- GPS_Init();//初始化GPS
- rev_stop=0;
- REV_NO;
- while(1)
- {
- if(rev_stop) //如果接收完一行
- {
- TR0=1; //開啟定時器
- REV_YES;
- if(GPS_RMC_Parse(rev_buf,&GPS)) //解析GPRMC
- {
- RMC_YES;
- GPS_DisplayOne(); //顯示GPS信息
- error_num=0;
- gps_flag=0;
- rev_stop=0;
- }
- else
- {
- error_num++;
- if(error_num>=20) //如果數據無效超過20次
- {
- RMC_NO;
- error_num=20;
- GPS_Init(); //返回初始化
- }
- gps_flag=0;
- rev_stop=0;
- REV_NO;
- }
- }
- }
- void timer0(void)interrupt 1
- {
- static uchar count=0;
- TH0=0x3c;
- TL0=0xb0;
- count++;
- if(count==200) //2*5秒鐘
- {
- count=0;
- change_page++; //換頁
- if(change_page==10)
- change_page=0;
- }
- }
- void Uart_Receive(void)interrupt 2
- {
- uchar ch;
- ES=0;
- if(RI)
- {
- ch = SBUF;
- if ((ch==')&&(gps_flag==0)) //如果收到字符‘,便開始接收
- {
- rev_start=1;
- rev_stop=0;
- }
- if(rev_start==1) //標志位為1,開始接收
- {
- rev_buf[num++]=ch; //字符存到數組中
- if(ch=='\n') //如果接收到換行
- {
- rev_buf[num]='\0';
- rev_start=0;
- rev_stop=1;
- gps_flag=1;
- num=0;
- }
- }
- }
- RI=0; //RI清0,重新接收
- ES=1;
- }
- }
- LCD
- #ifndef _LCD_H_
- #define _LCD_H_
-
- #include"LCD.H"
- void clr_screen()
- {
- Lcd_WriteCmd(0x34); //擴充指令操作
- delay(5);
- Lcd_WriteCmd(0x30); //基本指令操作
- delay(5);
- Lcd_WriteCmd(0x01); //清屏
- delay(5);
- }
- void Lcd_WriteCmd(uchar cmd)
- {
- LCD_RS=0;
- LCD_RW=0;
- LCD_EN=0;
- _nop_();
- _nop_();
- P0 = cmd;
- DelayNOP();
- LCD_EN=1;
- DelayNOP();
- LCD_EN=0;
- }
- void Lcd_WriteDat(uchar dat)
- {
- LCD_RS = 1;
- LCD_RW = 0;
- LCD_EN = 0;
- P0 = dat;
- DelayNOP();
- LCD_EN = 1;
- DelayNOP();
- LCD_EN = 0;
- }
- void Lcd_Init(void)
- {
- Lcd_PSB = 1; //并口方式
- Lcd_WriteCmd(0x34); //擴充指令操作
- delay(5);
- Lcd_WriteCmd(0x30); //基本指令操作
- delay(5);
- Lcd_WriteCmd(0x0C);//顯示開,關光標
- delay(5);
- Lcd_WriteCmd(0x01);//清除LCD的顯示內容
- delay(5);
- }
- void Lcd_SetPos(uchar X,uchar Y)
- {
- uchar pos;
- if(X==0)
- {X=0x80;}
- else if(X==1)
- {X=0x90;}
- else if(X==2)
- {X=0x88;}
- else if (X==3)
- {X=0x98;}
- pos = X+Y ;
- Lcd_WriteCmd(pos); //顯示地址
- }
- void Lcd_DispLine(uchar line, uchar pos, uchar *str)
- {
- int i = 0;
- Lcd_SetPos(line, pos);
- while (str[i] != '\0')
- {
- Lcd_WriteDat(str[i]);
- i++;
- }
- }
-
- GPS
- #ifndef _GPS_H_
- #define _GPS_H_
-
-
-
- #include "GPS.h"
- #include "LCD.h"
- #include <string.h>
- uchar code init1[] = {"GPS 顯示終端 "};
- uchar code init3[] = {"GPS 初始化......"};
- uchar code init4[] = {"搜索定位衛星...."};
- static uchar GetComma(uchar num,char *str);
- static double Get_Double_Number(char *s);
- static float Get_Float_Number(char *s);
- static void UTC2BTC(DATE_TIME *GPS);
- void GPS_Init(void)
- {
- Lcd_DispLine(0,0, init1);
- Lcd_DispLine(1,0, init3);
- Lcd_DispLine(2,0, init4);
- }
- int GPS_RMC_Parse(char *line,GPS_INFO*GPS)
- {
- uchar ch, status, tmp;
- float lati_cent_tmp, lati_second_tmp;
- float long_cent_tmp, long_second_tmp;
- char *buf = line;
- ch = buf[5];
- status = buf[GetComma(2, buf)];
- if (ch == 'C') //如果第五個字符是 C , ($GPRMC)
- {
- if (status == 'A') //如果數據有效,則分析
- {
- GPS-> NS = buf[GetComma(4, buf)];
- GPS_EW = buf[GetComma(6, buf)];
- GPS->latitude = Get_Double_Number(&buf[GetComma(3,buf)]);
- GPS->longitude = Get_Double_Number(&buf[GetComma(5,buf)]);
- GPS->latitude_Degree = (int)GPS->latitude/100; //分離緯度
- lati_cent_tmp = (GPS->latitude - GPS->latitude_Degree * 100);
- GPS->latitude_Cent = (int)lati_cent_tmp;
- lati_second_tmp = (lati_cent_tmp - GPS->latitude_Cent) * 60;
- GPS->latitude_Second = (int)lati_second_tmp;
- GPS->longitude_Degree = (int)GPS->longitude/100; //分離經度
- long_cent_tmp = (GPS->longitude - GPS->longitude_Degree * 100);
- GPS->longitude_Cent = (int)long_cent_tmp;
- long_second_tmp = (long_cent_tmp - GPS->longitude_Cent) * 60;
- GPS->longitude_Second = (int)long_second_tmp;
- GPS->D.hour = (buf[7] - '0') * 10 + (buf[8] - '0');//時間
- GPS->D.minute = (buf[9] - '0') * 10 + (buf[10] - '0');
- GPS->D.second = (buf[11] - '0') * 10 + (buf[12] - '0');
- tmp = GetComma(9, buf);
- GPS->D.day = (buf[tmp + 0] - '0') * 10 + (buf[tmp + 1] - '0'); //日期
- GPS->D.month = (buf[tmp + 2] - '0') * 10 + (buf[tmp + 3] - '0');
- GPS->D.year = (buf[tmp + 4] - '0') * 10 + (buf[tmp + 5] - '0')+2000;
- UTC2BTC(&GPS->D);
- return 1;
- }
- }
- return 0;
- }
- int GPS_GGA_Parse(char *line,GPS_INFO *GPS)
- {
- uchar ch, status;
- char *buf = line;
- ch = buf[4];
- status = buf[GetComma(2, buf)];
- if (ch == 'G') //$GPGGA
- {
- if (status != ',')
- {
- return 1;
- }
- }
- return 0;
- }
- static float Str_To_Float(char *buf)
- {
- float rev = 0;
- float dat;
- int integer = 1;
- char *str = buf;
- int i;
- while(*str != '\0')
- {
- switch(*str)
- {
- case '0':
- dat = 0;
- break;
- case '1':
- dat = 1;
- break;
- case '2':
- dat = 2;
- break;
- case '3':
- dat = 3;
- break;
- case '4':
- dat = 4;
- break;
- case '5':
- dat = 5;
- break;
- case '6':
- dat = 6;
- break;
- case '7':
- dat = 7;
- break;
- case '8':
- dat = 8;
- break;
- case '9':
- dat = 9;
- break;
- case '.':
- dat = '.';
- break;
- }
- if(dat == '.')
- {
- integer = 0;
- i = 1;
- str ++;
- continue;
- }
- if( integer==1 )
- {
- rev = rev*10 + dat;
- }
- else
- {
- rev = rev + dat/(10 * i);
- i = i * 10 ;
- }
- str ++;
- }
- return rev;
- }
- static float Get_Float_Number(char *s)
- {
- char buf[10];
- uchar i;
- float rev;
- i=GetComma(1, s);
- i = i-1;
- strncpy(buf, s, i);
- buf[i] = 0;
- rev=Str_To_Float(buf);
- return rev;
- }
- static double Str_To_Double(char *buf)
- {
- double rev = 0;
- double dat;
- int integer = 1;
- char *str = buf;
- int i;
- while(*str != '\0')
- {
- switch(*str)
- {
- case '0':
- dat = 0;
- break;
- case '1':
- dat = 1;
- break;
- case '2':
- dat = 2;
- break;
- case '3':
- dat = 3;
- break;
- case '4':
- dat = 4;
- break;
- case '5':
- dat = 5;
- break;
- case '6':
- dat = 6;
- break;
- case '7':
- dat = 7;
- break;
- case '8':
- dat = 8;
- break;
- case '9':
- dat = 9;
- break;
- case '.':
- dat = '.';
- break;
- }
- if(dat == '.')
- {
- integer = 0;
- i = 1;
- str ++;
- continue;
- }
- if( integer == 1 )
- {
- rev = rev * 10 + dat;
- }
- else
- {
- rev = rev + dat/(10 * i);
- i = i * 10 ;
- }
- str ++;
- }
- return rev;
- }
- static double Get_Double_Number(char *s)
- {
- char buf[10];
- uchar i;
- double rev;
- i=GetComma(1, s);
- i = i - 1;
- strncpy(buf, s, i);
- buf[i] = 0;
- rev=Str_To_Double(buf);
- return rev;
- }
- static uchar GetComma(uchar num,char *str)
- {
- uchar i,j = 0;
- int len=strlen(str);
- for(i = 0;i < len;i ++)
- {
- if(str[i] == ',')
- j++;
- if(j==num)
- return i + 1;
- }
- return 0;
- }
- static void UTC2BTC(DATE_TIME *GPS)
- {
- GPS->second ++;
- if(GPS->second > 59)
- {
- GPS->second = 0;
- GPS->minute ++;
- if(GPS->minute > 59)
- {
- GPS->minute = 0;
- GPS->hour ++;
- }
- }
- GPS->hour = GPS->hour + 8;
- if(GPS->hour > 23)
- {
- GPS->hour -= 24;
- GPS->day += 1;
- if(GPS->month==2||
- GPS->month==4||
- GPS->month==6||
- GPS->month==9||
- GPS->month==11)
- {
- if(GPS->day>30)
- {
- GPS->day=1;
- GPS->month++;
- }
- }
- else
- {
- if(GPS->day > 31)
- {
- GPS->day = 1;
- GPS->month ++;
- }
- }
- if(GPS->year % 4 == 0 )
- {
- if(GPS->day > 29 && GPS->month == 2)
- {
- GPS->day = 1;
- GPS->month ++;
- }
- }
- else
- {
- if(GPS->day > 28 &&GPS->month == 2)
- {
- GPS->day = 1;
- GPS->month ++;
- }
- }
- if(GPS->month > 12)
- {
- GPS->month -= 12;
- GPS->year ++;
- }
- }
- }
- void Int_To_Str(int x,char *Str)
- {
- int;
- char *Ptr.Buf[5];
- int i = 0;
- Ptr = Str;
- if(x < 10) // 當整數小于 10時 , 轉化為 "0x" 的格式
- {
- *Ptr ++ = '0';
- *Ptr ++ = x+0x30;
- }
- else
- {
- while(x > 0)
- {
- t = x % 10;
- x = x / 10;
- Buf[i++] = t+0x30; // 通過計算把數字轉化成 ASCII 碼形式
- }
- i -- ;
- for(;i >= 0;i --) // 將得到的字符串倒序
- {
- *(Ptr++) = Buf[i];
- }
- }
- *Ptr = '\0';
- }
-
- #endif
-
- 顯示模塊
- #ifndef _DISPLAY_H_
- #define _DISPLAY_H_
- #include "DISPLAY.H"
- uchar code beiwei[] = "北緯 ";
- uchar code nanwei[] = "南緯 ";
- uchar code dongjing[] = "東經 ";
- uchar code xijing[] = "西經 ";
- uchar code date[] = " 年 月 日 ";
- void Show_Float(float fla, uchar x, uchar y);
- void GPS_DispTime(void)
- {
- uchar i = 0;
- uchar ch;
- char time[5];
- Lcd_DispLine(0, 0, date); //年月日;
- Int_To_Str(GPS.D.year,time); //將年轉換成字符串,存在 time 中
- Lcd_SetPos(0, 0); //設置顯示地址
- if(strlen(time)==4) //判斷接收數據是否有效,有效則顯示
- {
- i = 0;
- while(time[i]!= '\0')
- {
- ch = time[i++];
- Lcd_WriteDat(ch); //顯示年
- }
- }
- Int_To_Str(GPS.D.month,time);
- Lcd_SetPos(0, 3);
- if(strlen(time)==2)
- {
- i = 0;
- while(time[i]!= '\0')
- {
- ch =time[i++];
- Lcd_WriteDat(ch);
- }
- }
- Int_To_Str(GPS.D.day,time);
- Lcd_SetPos(0, 5);
- if(strlen(time)==2)
- {
- i = 0;
- while(time[i]!= '\0')
- {
- ch =time[i++];
- Lcd_WriteDat(ch);
- }
- }
- Int_To_Str(GPS.D.hour,time);
- Lcd_SetPos(1, 1);
- if(strlen(time)==2)
- {
- i = 0;
- while(time[i] != '\0')
- {
- ch =time[i++];
- Lcd_WriteDat(ch);
- }
- }
- Lcd_WriteDat('');
- Lcd_WriteDat(':');
- Int_To_Str(GPS.D.minute,time);
- Lcd_SetPos(1, 3);
- if(strlen(time)==2)
- {
- i = 0;
- while(time[i]!= '\0')
- {
- ch =time[i++];
- Lcd_WriteDat(ch);
- }
- }
- Lcd_WriteDat(' ');
- Lcd_WriteDat(':');
- Int_To_Str(GPS.D.second,time);
- Lcd_SetPos(1, 5);
- if(strlen(time)==2)
- {
- i = 0;
- while(time[i]!= '\0')
- {
- ch =time[i++];
- Lcd_WriteDat(ch);
- }
- }
- }
- void GPS_DisplayOne(void)
- {
- uchar ch, i;
- char info[10];
- ET0=0;
- clr_screen();
- Lcd_WriteCmd(0x01); //清屏
- GPS_DispTime(); //顯示日期,時間
- if (GPS.NS == 'N') //判斷是北緯還是南緯
- Lcd_DispLine(2, 0, beiwei);
- else if(GPS.NS == 'S')
- Lcd_DispLine(2, 0, nanwei);
- if (GPS.EW == 'E') //判斷是東經還是西經
- Lcd_DispLine(3, 0, dongjing);
- else if (GPS.EW == 'W')
- Lcd_DispLine(3, 0, xijing);
- Int_To_Str(GPS.latitude_Degree,info); //緯度
- if(strlen(info)==2)
- { //只有正常顯示緯度,才顯示緯分
- i = 0;
- while(info[i] != '\0')
- {
- ch = info[i++];
- Lcd_WriteDat(ch);
- }
- Lcd_WriteDat(' ');
- Lcd_WriteDat(' ');
- Lcd_WriteDat(0xA1);
- Lcd_WriteDat(0xE3);
- Int_To_Str(GPS.latitude_Cent,info); //緯分
- if(strlen(info)==2)
- { //只有正常顯示緯分,才顯示緯秒
- i = 0;
- while(info[i]!= '\0')
- {
- ch = info[i++];
- Lcd_WriteDat(ch);
- }
- Lcd_WriteDat(0xA1);
- Lcd_WriteDat(0xE4);
- Int_To_Str(GPS.latitude_Second,info); //緯秒
- if(strlen(info)==2)
- {
- i = 0;
- while(info[i]!='\0')
- {
- ch = info[i++];
- Lcd_WriteDat(ch);
- }
- }
- }
- }
- Int_To_Str(GPS.longitude_Degree,info); //經度
- if(strlen(info)==3)
- { //只有正常顯示經度,才顯示經分
- Lcd_DispLine(3, 2, info);
- Lcd_WriteDat(' ');
- Lcd_WriteDat(0xA1);
- Lcd_WriteDat(0xE3);
- Int_To_Str(GPS.longitude_Cent,info); //經分
- if(strlen(info)==2)
- { //只有正常顯示經度,才顯示經分
- Lcd_DispLine(3, 5, info);
- Lcd_WriteDat(0xA1);
- Lcd_WriteDat(0xE4);
- Int_To_Str(GPS.longitude_Second,info); //經秒
- if(strlen(info)==2)
- { //只有正常顯示經分,才顯示經秒
- Lcd_DispLine(3, 7, info);
- }
- }
- }
- ET0=1;
- }
- void Show_Float(float fla, uchar x, uchar y)
- {
- int integar;
- char Info[10],ch;
- uchar i;
- Lcd_SetPos(x, y);
- integar = (int)fla;
- Int_To_Str(fla,Info); //顯示整數部分
- i = 0;
- while(Info[i]!='\0')
- {
- ch=Info[i++];
- Lcd_WriteDat(ch);
- }
- Lcd_WriteDat('.'); //顯示小數點
- fla = fla-integar; //顯示小數部分
- fla = fla*10; // 顯示 0.1
- integar = (int)fla;
- fla = fla - integar; // 改變 fla 的值 , 使 fla 總是小于 1
- ch = integar + 0x30;
- Lcd_WriteDat(ch);
- fla = fla*10; // 顯示 0.01
- integar = (int)fla;
- fla = fla - integar; // 改變 fla 的值 , 使 fla 總是小于 1
- ch = integar + 0x30 ;
- Lcd_WriteDat(ch);
- }
- #endif
復制代碼 |