zoukankan      html  css  js  c++  java
  • 51单片机解码GPS 1602显示

    用51单片机解析串口GPS模块发来的信息,在1602液晶显示 ,用51单片机的TXD口接GPS模块的RXD口。程序略做修改并修正了一些错误。
    这是电路原理图。程序是结合我单片机的板子做了修改。 
    就是先焊接一个51单片机最小系统。我的程序中是用的P0口与1602液晶通信。
     

      
     这是做的改进,由原来的串口GPS模块,换成了蓝牙GPS模块。最右边是诺基亚的蓝牙GPS模块,小的四方的板子上蓝牙串口主模块,用来接收蓝牙GPS发出的信号。程序还是原程序。 
     
     
    程序是结合网络资料,自己加已修改。
    因无法上传附件,只有把代码贴 这了。
     
     
     

    //这是1602液晶的驱动头文件,文件名为1602.h
     
     /*
    LCD1602驱动,兼容LCD2402
    */
    sbit LCD_DB0= P0^0;
    sbit LCD_DB1= P0^1;
    sbit LCD_DB2= P0^2;
    sbit LCD_DB3= P0^3;
    sbit LCD_DB4= P0^4;
    sbit LCD_DB5= P0^5;
    sbit LCD_DB6= P0^6;
    sbit LCD_DB7= P0^7;
    sbit LCD1602_RS=P1^0;
    sbit LCD1602_RW=P1^1; 
    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(unsigned char bw);
    void SET_LCD(unsigned char IO_temp);
    void delayms(unsigned char ms);
    void lcddelay(void);
    unsigned char LCDIO; 
    unsigned char BitWidth;
    void LCD_cls(void)
    {
     LCD_en_command(0x01); //0x01 清屏
        delayms(2);
    }
    void LCD_en_command(unsigned char command)
    {
     LCD1602_RS=0;   
     LCD1602_RW=0;
     LCD1602_EN=0;
     switch(BitWidth){
       case 4:
      LCDIO=(command & 0xf0);   //取高4位
      break;
       case 8:
      LCDIO=command;
         break;
     }
     SET_LCD(LCDIO);
     LCD1602_EN=1;
     lcddelay();
     LCD1602_EN=0;
     if (BitWidth==4){
      LCDIO=(command & 0x0f)<<4;  //取低4位
      SET_LCD(LCDIO);
      LCD1602_EN=1;
      lcddelay();
      LCD1602_EN=0;
     }
    }
    void SET_LCD(unsigned char IO_temp)
    {   
     //高4位
     LCD_DB7=IO_temp&0x80;
     LCD_DB6=IO_temp&0x40;
     LCD_DB5=IO_temp&0x20;
     LCD_DB4=IO_temp&0x10;
     //低4位
     if (BitWidth==8){
      LCD_DB3=IO_temp&0x08;
      LCD_DB2=IO_temp&0x04;
      LCD_DB1=IO_temp&0x02;
      LCD_DB0=IO_temp&0x01;
     }
    }
    void LCD_en_dat(unsigned char dat)
    {
     LCD1602_RS=1;
     LCD1602_RW=0;
     LCD1602_EN=0;
     switch(BitWidth){
       case 4:
      LCDIO=(dat & 0xf0);   //取高4位
      break;
       case 8:
      LCDIO=dat;
      break;
     }
     SET_LCD(LCDIO);
     LCD1602_EN=1;
     lcddelay();
     LCD1602_EN=0;
      
     if (BitWidth==4){
      LCDIO=(dat & 0x0f)<<4;  //取低4位
      SET_LCD(LCDIO);
      LCD1602_EN=1;
      lcddelay();
      LCD1602_EN=0;
     }
    }
    /*=======================================================
    *1602
    * 输入参数:x、y : 显示字符串的坐标,X:0-15,Y:0-1
    *LCD第一行显示寄存器地址:0X80-0X8F
    *LCD第二行显示寄存器地址:0XC0-0XCF  
    *2404
    *LCD第1行显示地址:1~20(0x80~0x93) 
    *LCD第2行显示地址:1~20(0xc0~0xd3) 
    *LCD第3行显示地址:1~20(0x94~0xa7) 
    *LCD第4行显示地址:1~20(0xd4~0xe7) 
    =======================================================*/ 
    void LCD_set_xy( unsigned char x, unsigned char y )
    {
     unsigned char address;
     if (y ==0) 
        address = 0x80 + x;
     else
       if(y==1) 
      address = 0xC0 + x;
       else
         if(y==2)
        address = 0x94 + x;
      else
        if(y==3)
          address = 0xD4 + 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(unsigned char bw)
    {
     BitWidth=bw;
     switch(BitWidth){
       case 4:
      LCD_en_command(0x33); //
      delayms(20);
      LCD_en_command(0x32); //
      delayms(20);
      break;
          case 8:
      LCD_en_command(0x38); //
      delayms(20);
      LCD_en_command(0x38); //
      delayms(20);
      break;
     }
     LCD_en_command(0x08); //0x08 令显示器off 
     delayms(5);
     LCD_en_command(0x01); //0x01 清屏   清屏指令
     delayms(5);
     LCD_en_command(0x06); //0x06 光标模式设置 进入模式设置指令 写入数据后光标右移
     delayms(5);
     LCD_en_command(0x0c); //0x0c 显示开      令光标,0x0c=不显示,0x0d=显示闪动
     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++);
    }
    
     
     
     
     
     
     
    //这是解码主程序 


     
     
     
     

     
    /*************************************
     GPS解码显示程序,
    ***************************************/
    #include<reg52.h>
    #include "1602.h"
    //#include"math.h"
    //#include <stdlib.h>
    sbit GPS_SPD=P2^1;    //接收波特率设置
    sbit KEY1=P2^0;   //显示内容分屏切换,(T0,T1引脚 的第二功能为计数器。)
    char code TIME_AREA= 8;  //时区
    /***************************************
           这是做的部分更改
    ************************************/
    unsigned long maxspeed,b;
    unsigned int count=0;
    unsigned int a[5];
    unsigned char hspeed[5];
    unsigned int dot_count; //小数点计数器
    //unsigned char x;
    //GPS数据存储数组
    unsigned char JD[10];  //经度
    unsigned char JD_a;  //经度方向
    unsigned char WD[9];  //纬度
    unsigned char WD_a;  //纬度方向
    unsigned char date[6];  //日期
    unsigned char time[6];  //时间
    unsigned char speed[5]={'0','0','0','.','0'};  //速度
    unsigned char high[6];  //高度
    unsigned char angle[5]={'0','0','0','0','0'};  //方位角
    unsigned char use_sat[2]; //使用的卫星数
    unsigned char total_sat[2]; //天空中总卫星数
    unsigned char lock;   //定位状态
    //串口中断需要的变量
    unsigned char seg_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;
    void sys_init(void);
    bit chk_key(void);
    main()
    {
     unsigned char i;
     char Bhour;
     sys_init();
     lock=1;
     use_sat[0]='0';
     use_sat[1]='0';
     total_sat[0]='0';
     total_sat[1]='0';
     while(1){
         if(buf_full==0)    //无GPS信号时
      {
       dsp_count++;
       if(dsp_count>=65000){
        LCD_cls();   //清屏
        LCD_write_string(0,0,"No GPS connect..");
        LCD_write_string(0,1,"Please Check..");
        while(buf_full==0);
        LCD_cls(); 
        dsp_count=0;
       }
      }
      else{      //有GPS信号时
    /*************************************
     最大速度处理
    *************************************/
                         dot_count=0;
           b=0;
                          for(i=0;i<5;i++)
           {
               if(speed!='.')
               dot_count++;
            else
               break ;
           }
           switch(dot_count)
           {
              
           case 1:
                b=((speed[0]-'0')*10+(speed[2]-'0'))*1.852;
             break;
           case 2:
                b=((speed[0]-'0')*100+(speed[1]-'0')*10+(speed[4]-'0'))*1.852;
             break;
           case 3:
                b=((speed[0]-'0')*1000+(speed[1]-'0')*100+(speed[2]-'0')*10+(speed[4]-'0'))*1.852;
             break;
          
            }
                          if(b>maxspeed)
           {
             maxspeed=b;
              }
    
    /*************************************
     最大速度处理
    *************************************/
     
                
       if(chk_key()){    //检测到按键切换显示
        page=!page;
        LCD_cls();
       }
       if(!page){      //页面1
    
                          
        if(buf_full|0x01){    //GGA语句
         if(lock==0){     //如果未定位
          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);
            }
                            LCD_write_char(4,0,'.');
                            for(i=3;i<10;i++)
          {
            LCD_write_char(i+2,0,JD);
            }
          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);
          }
          LCD_write_char(4,1,'.');
                            for(i=2;i<9;i++)
          {
           LCD_write_char(i+3,1,WD);
          }
                
          }
         LCD_write_char(14,1,use_sat[0]);  //显示接收卫星数
         LCD_write_char(15,1,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){
         if(lock==0){     //如果未定位
          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);
           }
                        LCD_write_char(4,0,'.');
                        for(i=3;i<10;i++)
         {
           LCD_write_char(i+2,0,JD);
           }
         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);
         }
         LCD_write_char(4,1,'.');
                        for(i=2;i<9;i++)
         {
          LCD_write_char(i+3,1,WD);
         }
             }
         LCD_write_char(14,0,use_sat[0]);  //显示接收卫星数
         LCD_write_char(15,0,use_sat[1]);
         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_char(0,1,date[4]);
         LCD_write_char(1,1,date[5]);
         LCD_write_char(2,1,date[2]);
         LCD_write_char(3,1,date[3]);
         LCD_write_char(4,1,date[0]);
         LCD_write_char(5,1,date[1]);
         LCD_write_char(8,1,Bhour/10+0x30);
         LCD_write_char(9,1,Bhour%10+0x30);
         LCD_write_char(10,1,':');
         LCD_write_char(11,1,time[2]);
         LCD_write_char(12,1,time[3]);
         LCD_write_char(13,1,':');
         LCD_write_char(14,1,time[4]);
         LCD_write_char(15,1,time[5]);
         LCD_write_string(5,0,"knot A");         
         if(lock=='0'){     //如果未定位
          LCD_write_string(0,0,"---.-");
          LCD_write_string(11,0,"---.-");
         }else{                                                      //已经定位,在此处做的改动。
    /*******************************************************************************/
    
            
           
                               if(count<10)
             { 
                                
                                for(i=0;i<5;i++)
           {   
           LCD_write_char(i,0,speed);//knot显示
           }
           count++;
            }
            else
            {
              if(count>15)
              {  
              count=0;
           }
                               hspeed[0]=maxspeed/1000+0x30;                     //把小数转成字符数组
             hspeed[1]=(maxspeed/100)%10+0x30; 
             hspeed[2]=(maxspeed/10)%10+0x30;
             hspeed[3]='.';
             hspeed[4]= maxspeed%10+0x30;
               
              count++;
           LCD_write_string(5,0,"Km/h A"); 
                                LCD_write_char(0,0,hspeed[0]);
           LCD_write_char(1,0,hspeed[1]); 
           LCD_write_char(2,0,hspeed[2]);
           LCD_write_char(3,0,hspeed[3]);
           LCD_write_char(4,0,hspeed[4]); //最大速度显  */
          }
                             
    /*******************************************************************************/
            for(i=0;i<5;i++){
            LCD_write_char(11+i,0,angle);
          }
         }
         buf_full&=~0x04;
         dsp_count=0;
        }
       }
      }
     }
    }
    bit chk_key(void)
    {
     if(!KEY1){
      delayms(10);
      if(!KEY1){
       while(!KEY1);
       delayms(10);
       return(1);
      }
     }
        LCD_cls();   //清屏
     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 = 0xfa;   /* TH1: reload value for 9600 baud @ 11.059MHz */
     }else{
      TH1 = 0xfd;   /* TH1: reload value for 4800 baud @ 11.059MHz */
     }
     TR1 = 1;   /* TR1: timer 1 run */
     LCD_init(8);  //初始化LCD
     LCD_write_string(0,0," GPS SIRF II 2 ");
     LCD_write_string(0,1," 11-11-23 1342 ");
     
     
     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 2:  //定位判断      
             if(byte_count<1){
               if (tmp=='A') {lock=1;}
               else{
                 lock=0;}
             }
             break;
            case 3:  //纬度处理      
             if(byte_count<9){
              WD[byte_count]=tmp;
             }
             break;
            case 4:  //纬度方向处理      
             if(byte_count<1){
              WD_a=tmp;
             }
             break;
            case 5:  //经度处理      
             if(byte_count<10){
              JD[byte_count]=tmp;
             }
             break;
            case 6:  //经度方向处理      
             if(byte_count<1){
              JD_a=tmp;
             }
             break;
            case 7:  //速度处理      
             if(byte_count<5){
              speed[byte_count]=tmp;
             }
                                   
             break;
            case 8:  //方位角处理      
             if(byte_count<5){
              angle[byte_count]=tmp;
             }
             break;
            case 9:  //方位角处理      
             if(byte_count<6){
              date[byte_count]=tmp;
             }
             break;
           }
           break;
         }
        }
        byte_count++;  //接收数位加1
        break;
      }
     }
     RI=0;
    }

     

  • 相关阅读:
    python的类基础
    python导入模块
    python常用的内置函数
    python基础一数据类型之集合
    python函数-匿名函数
    python的函数(三)
    python的函数(二)
    python的函数(一)
    BZOJ4104:[Thu Summer Camp 2015]解密运算——题解
    BZOJ4033:[HAOI2015]树上染色——题解
  • 原文地址:https://www.cnblogs.com/dreamfactory/p/2585874.html
Copyright © 2011-2022 走看看