GPS.c
上传用户:orange__li
上传日期:2022-06-08
资源大小:5k
文件大小:15k
- //**********************************标注定义********************************//
- //**********************************标注定义********************************//
- #include <reg52.h> // 引用标准库的头文件
- #include <stdio.h>
- #include <absacc.h>
- #include <intrins.H>
- //****************************配置GPS函数声明*******************************//
- //GPS数据存储数组
- unsigned char JD[10]={"00000.0000"}; //经度
- unsigned char JD_a='*'; //经度方向
- unsigned char WD[9]={"0000.0000"}; //纬度
- unsigned char WD_a='*'; //纬度方向
- unsigned char time[6]={"000000"}; //时间
- unsigned char date[6]={"000000"}; //日期
- unsigned char speed[5]; //速度
- unsigned char high[6]; //高度
- unsigned char angle[5]; //方位角
- unsigned char use_sat[2]={"00"}; //使用的卫星数
- unsigned char total_sat[2]={"00"}; //天空中总卫星数
- //串口中断需要的变量
- unsigned char seg_count; //逗号计数器
- unsigned char dot_count; //小数点计数器
- unsigned char byte_count; //位数计数器
- unsigned char cmd_number; //命令类型
- unsigned char mode; //0:结束模式,1:命令模式,2:数据模式
- volatile unsigned char buf_full; //1:整句接收完成,相应数据有效。0:缓存数据无效。
- unsigned char cmd[5]; //命令类型存储数组
- //显示需要的变量
- unsigned char dsp_count; //刷新次数计数器
- unsigned char time_count;
- uchar code datas1[] = {"欢迎使用GPS"};
- uchar code datas2[] = {"白云学院电子系"};
- uchar code datas3[] = {"06电子信息本科班"};
- uchar code datas4[] = {"曾宪敏"};
- //**********************************初始化串口********************************//
- //**********************************初始化串口********************************//
- void UART_Init()
- {
- SCON=0x50; // UART工作于模式1, REN=1
- TMOD=0x20 ; // Timer1 工业于模式2
- PCON |= 0x80; // SMOD1 = 1
- TH1=0xF3; // 波特率9600 bps
- TL=0xF3; // 波特率9600 bps
- EA=1
- ES= 1; //串口中断使能
- TR1= 1; // 启动Timer1
- }
- //**********************************LCD模块********************************//
- //**********************************LCD模块********************************//
- #define uchar unsigned char
- #define uint unsigned int
- //延时约2us
- void delayUs()
- {
- _nop_();_nop_();
- }
- //延时a ms
- void delayMs(uint a)
- {
- uint i, j;
- for(i = a; i > 0; i--)
- for(j = 100; j > 0; j--);
- }
-
- //检测LCD是否处于忙状态, 若忙返回1, 空闲返回0
- bit checkBusy()
- {
- bit busy;
- RS = 0;
- RW = 1;
- E = 1;
- delayUs();
- busy = (bit)(LCD_DATA&0x80);
- E = 0;
- return busy;
- }
-
- //等待LCD到空闲
- void LCDwait()
- {
- while(checkBusy());
- }
-
- //写命令
- void LCDwriteCmd(uchar cmd)
- {
- LCDwait();
- RS = 0;
- RW = 0;
- E = 0;
- delayUs();
- LCD_DATA = cmd;
- delayUs();
- E = 1;
- delayUs();
- E = 0;
- }
-
- //写数据
- void LCDwriteData(uchar dat)
- {
- LCDwait();
- RS = 1;
- RW = 0;
- E = 0;
- delayUs();
- LCD_DATA = dat;
- delayUs();
- E = 1;
- delayUs();
- E = 0;
- }
-
- //初始化LCD
- void LCDinit()
- {
- PSB = 1; //并口方式
- LCDwriteCmd(0x30); //基本指令, 扩充指令为34H
- delayMs(10);
- LCDwriteCmd(0x0c); //显示开, 关光标
- delayMs(10);
- LCDwriteCmd(0x01); //清屏
- delayMs(10);
- }
-
- void display(uchar x, uchar y,uchar *str)
- {
- uchar p;
- uchar i = 0;
- switch(x)
- {
- case 0: p = 0x80; break; //第一行开始地址
- case 1: p = 0x90; break; //第二行
- case 2: p = 0x88; break; //第三行
- case 3: p = 0x98; break; //第四行
- }
- p += y;
- LCDwriteCmd(p);
- while(str[i] != ' ')
- {
- LCDwriteData(str[i++]);
- }
- }
- /*---------------------------------------------------------
- GPS模块串口接收程序:串口函数
- ---------------------------------------------------------*/
- void GPS_INT() //interrupt 4
- {
- uchar i;
- RI=0;
- if(SBUF=='$') //判断是否为$GPRMC语句
- {
- gpsnum=0;
- gpsres=1; //开始接收
- return;
- }
- if(SBUF=='*' && gpsres==1) //接收完数据后的处理
- {
- gpsnum=0; //复位为第0个数据
- gpsres=0; //停止接收
- ////////修正时间数据为北京时间,24小时制
- if(gpstime[0] <0x32)
- {
- i=gpstime[1]+0x08; //小时个位+8,转为北京时间
- if(i>=0x3a)
- {
- i=i-0x0a;
- gpstime[0]=gpstime[0]+0x01;
- if(gpstime[0]==0x32&&i>=0x34)
- {gpstime[0]=0x30;i=i-0x04;}
- }
- }
- else
- {
- i=gpstime[1]+0x04;
- gpstime[0]=0x30;
- }
- gpstime[1]=i;
- return;
- }
- //////////////////////////////////////////
- if(gpsres==1)
- {
- if(SBUF==',') //逗号后为下一个数据
- {gpsnum++;return;}
- switch(gpsnum) //判断数据类型,然后存储起来
- {
- case 0:{*gpsptime=SBUF;gpsptime++;}break;
- case 1:{*gpspstatus=SBUF;gpspstatus++;}break;
- case 2:{*gpspweidu=SBUF;gpspweidu++;}break;
- case 3:{*gpspnors=SBUF;gpspnors++;}break;
- case 4:{*gpspjingdu=SBUF;gpspjingdu++;}break;
- case 5:{*gpspeorw=SBUF;gpspeorw++;}break;
- case 6:{}break;
- case 7:{}break;
- case 8:{*gpspdate=SBUF;gpspdate++;}break;
- case 9:{}break;
- default:
- {
- *gpsptime=gpstime; //复位各数据指针
- *gpspstatus=gpsstatus;
- *gpspweidu=gpsweidu;
- *gpspnors=gpsnors;
- *gpspjingdu=gpsjingdu;
- *gpspeorw=gpseorw;
- *gpspdate=gpsdate;
- }break;
- }
- }
- }
- //USART 初始化
- void init_USART(void)
- {
- UCSRC = (1<<URSEL) | 0x06; //异步,8位数据,无奇偶校验,一个停止位,无倍速
- UBRRL= (F_CPU/9600/16-1)%256; //UBRR= (F_CPU/(BAUDRATE*16))-1;
- UBRRH= (F_CPU/9600/16-1)/256;
- UCSRA = 0x00; //使能接收中断,使能接收,使能发送
- UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN)
- sei(); //总中断允许
- volatile unsigned char high_num,a_num,s_num;
- void init_set(void);
- void sys_init(void);
- unsigned char week(unsigned char year, unsigned char mon, unsigned char day);
- int main(void)
- {
- unsigned char i;
- unsigned char Bhour=0,Bday=0,Bmonth=0;
- unsigned int Byear=0;
- sys_init();
- while(1){
- if(buf_full==0) //无GPS信号时
- {
- dsp_count++;
- _delay_ms(10);
- if(dsp_count>=200){
- CLEAN_SCREEN(); //清屏
- display(0,0,PSTR("No GPS CONNECT.."),0);
- while(buf_full==0);
- CLEAN_SCREEN();
- dsp_count=0;
- }
- }
- else{ //有GPS信号时
- if(buf_full|0x01){ //GGA语句
- display(0,0,JD_a,0); //显示经度
- for(i=0;i<3;i++){
- display(0,(i+1)*6,JD[i],0);
- }
- display(0,24,'.',0);
- for(i=3;i<10;i++){
- display(0,(i+2)*6,JD[i],0);
- }
- display(1,0,WD_a,0); //显示纬度
- for(i=0;i<2;i++){
- display(1,(i+2)*6,WD[i],0);
- }
- display(1,24,'.',0);
- for(i=2;i<9;i++){
- display(1,(i+3)*6,WD[i],0);
- }
- display(2,96,use_sat[0],0); //显示接收卫星数
- display(2,102,use_sat[1],0);
- display(2,108,'/',0);
- display(2,0,PSTR("HI:"),0);
- if(high_num<6) //高度显示
- {
- for(i=0;i<(6-high_num);i++)
- {
- display(2,(3+i)*6,0x20,0);
- }
- }
- for(i=0;i<high_num;i++)
- {
- display(2,(9-high_num+i)*6,high[i],0);
- }
- display(2,54,PSTR("m U/T:"),0);
- buf_full&=~0x01;
- dsp_count=0;
- }
- if(buf_full|0x02){ //GSV语句
- display(2,114,total_sat[0],0);
- display(2,120,total_sat[1],0);
- buf_full&=~0x02;
- dsp_count=0;
- }
- if(buf_full|0x04)
- {
- display(0,78,PSTR("AG:"),0);//方位角显示
- if(a_num<5)
- {
- for(i=0;i<(5-a_num);i++)
- {
- display(0,(16+i)*6,0x20,0);
- }
- }
- for(i=0;i<a_num;i++)
- {
- display(0,(21-a_num+i)*6,angle[i],0);
- }
- display(1,78,PSTR("SP:"),0); //速度显示
- if(s_num<5)
- {
- for(i=0;i<(5-s_num);i++)
- {
- display(1,(16+i)*6,0x20,0);
- }
- }
- for(i=0;i<s_num;i++)
- {
- display(1,(21-s_num+i)*6,speed[i],0);
- }
- buf_full&=~0x04;
- dsp_count=0;
- }
- if(buf_full|0x08){
- if(Bhour!=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA){
- Bhour=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA; //北京时间转换
- Bday=(date[0]-0x30)*10+date[1]-0x30;
- Bmonth=(date[2]-0x30)*10+date[3]-0x30;
- Byear=(date[4]-0x30)*10+date[5]-0x30+2000;
- if(Bhour>=24){ //如果小时数大于24
- Bhour-=24; //小时数减24
- Bday++; //日期数加1
- switch(Bday //判断日期
- case 29: //普通年的2月份
- if((!((Byear%400==0)||((Byear%4==0)&&(Byear%100!=0)))&&(Bmonth==2))){
- Bday=1;
- Bmonth++;
- }
- break
- case 30: //如果是闰年的2月
- if(((Byear%400==0)||((Byear%4==0)&&(Byear%100!=0)))&&(Bmonth==2)){
- Bday=1;
- Bmonth++;
- }
- break;
- case 31:
- if((Bmonth==4)||(Bmonth==6)||(Bmonth==9)||(Bmonth==11)){
- Bday=1;
- Bmonth++;
- }
- break;
- case 32:
- Bday=1;
- Bmonth++;
- if(Bmonth>=13){
- Byear++;
- Bmonth=1;
- }
- break;
- }
- }
- }
- display(3,0,'2',0);
- display(3,6,'0',0);
- display(3,12,(Byear%100)/10+0x30,0);
- display(3,18,Byear%10+0x30,0);
- display(3,24,'/',0);
- display(3,30,Bmonth/10+0x30,0);
- display(3,36,Bmonth%10+0x30,0);
- display(3,42,'/',0);
- display(3,48,Bday/10+0x30,0);
- display(3,54,Bday%10+0x30,0);
-
- switch(week(Byear%100,Bmonth,Bday)){
- case 0:
- display(3,120,PSTR("7"),0);
- break;
- case 1:
- display(3,120,PSTR("1"),0);
- break;
- case 2:
- display(3,120,PSTR("2"),0);
- break;
- case 3:
- display(3,120,PSTR("3"),0);
- break;
- case 4:
- display(3,120,PSTR("4"),0);
- break;
- case 5:
- display(3,120,PSTR("5"),0);
- break;
- case 6:
- display(3,120,PSTR("6"),0);
- break;
- }
- if(Bhour/10!=0)
- {
- display(3,66,Bhour/10+0x30,0);
- NUM1632_DISP(4,0,Bhour/10,0);
- }
- else
- {
- display(3,66,0x20,0);
- NUM1632_DISP(4,0,11,0);
- }
- display(3,72,Bhour%10+0x30,0);
- display(3,78,':',0);
- display(3,84,time[2],0);
- display(3,90,time[3],0);
- display(3,96,':',0);
- display(3,102,time[4],0);
- display(3,108,time[5],0);
-
- NUM1632_DISP(4,1,Bhour%10,0);
- NUM1632_DISP(4,2,10,0);
- NUM1632_DISP(4,3,time[2]-0x30,0);
- NUM1632_DISP(4,4,time[3]-0x30,0);
- NUM1632_DISP(4,5,10,0);
- NUM1632_DISP(4,6,time[4]-0x30,0);
- NUM1632_DISP(4,7,time[5]-0x30,0);
-
- buf_full&=~0x08;
- dsp_count=0;
- }
- }
- }
- }
- //计算星期
- unsigned char week(unsigned char year, unsigned char mon, unsigned char day)
- {
- const prog_uchar Weekdays[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
- // 31 28 31 30 31 30 31 31 30 31 30
- return (6-1 + (year>>2) + year + Weekdays[mon-1] + day + (((year & 3) || mon > 2)? 1 : 0)) % 7;
- //完整的计算星期的公式:
- //(year>>2) - (year / 100) + (year/400) + year +
- // Weekdays[mon-1] + day + ((!isLeap(year) || mon > 2)? 1 : 0)) % 7;
- }
- //串口接收中断
- SIGNAL(SIG_UART_RECV) //串口接收中断服务程序
- {
- unsigned char tmp;
- tmp=UDR;
- 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;
- case 4:
- buf_full|=0x08;
- 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;
- high_num=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;
- a_num=0;
- s_num=0;
- }
- }
- }
- else if(cmd[2]=='Z'){
- if(cmd[3]=='D'){
- if(cmd[4]=='A'){
- cmd_number=4;
- 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 7: //定位使用的卫星数
- if(byte_count<2){
- use_sat[byte_count=tmp;
- }
- break;
- case 9: //高度处理
- if(byte_count<6){
- high[byte_count]=tmp;
- high_num++;
- }
- 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 7: //速度处理
- if(byte_count<5){
- speed[byte_count]=tmp;
- s_num++;
- }
- break;
- case 8: //方位角处理
- if(byte_count<5){
- angle[byte_count]=tmp;
- a_num++;
- }
- break;
- }
- break;
- case 4: //类型4数据接收.GPZDA
- switch(seg_count){
- case 1:
- if(byte_count<6){ //时间处理
- time[byte_count]=tmp;
- }
- break;
- case 2:
- if(byte_count<2){
- date[byte_count]=tmp;
- }
- break;
- case 3:
- if(byte_count<2){
- date[byte_count+2]=tmp;
- }
- break;
- case 4:
- if((byte_count<4)&&(byte_count>1)){
- date[byte_count+2]=tmp;
- }
- break;
- }
- break;
- }
- }
- byte_count++; //接收数位加1
- break;
- }
- }
- /**********************************主函数模块********************************/
- //**********************************主函数模块********************************//
- void main()
- {
-
- LCDinit(); //初始化LCD
- LCDwriteCmd(0x01);
- //显示开始信息
- display(0, 1,datas1);
- display(1, 0,datas2);
- display(2, 0,datas3);
- display(3, 3,datas4);
- delayMs(1000);
- LCDwriteCmd(0x01);
- display(1,0,"GPS定位中。。。");
- delayMs(1000);
-
- UART_Init(); // 初始化串口
- EA = 1;
-
- DisableAllOut();
- EnableGPRMC();
- LCDwriteCmd(0x01);
- GPS_INT() ;
- display(0,0,gpsdate);
- display(1,0,gpstime);
- display(2,0,gpsjingdu);
- display(3,0,gpsweidu);
- delayMs(1000); // 延时1s
- //REN = 1; // REN = 1,开始接收数据
- //while(1);
- }