• STC89C58串口接收GPS信号(GPRMC)读取经纬度,时间。1604液晶(HD44780)显示


     

    /******************************************************************************
    Copyright 2007
    All rights reserved.

    文件名 :gps1602.c
    模块名称:
    功能概要:

    取代版本:0.0.1
    修改人 :
    完成日期:2007.07.27
    升级说明:create
    cpu:stc89c58    晶振频率:11.0592Mhz
    硬件连接:
    ---------------------------------------------------------------
    |DB0-----P0.0 | DB4-----P0.4 | WR-------P2.2 | A0--------P2.1 |
    |DB1-----P0.1 | DB5-----P0.5 | RD-------P2.4 | Vo悬空 |
    |DB2-----P0.2 | DB6-----P0.6 | CS-------P2.5 |
    |DB3-----P0.3 | DB7-----P0.7 | RST-------P2.3 |   
    ---------------------------------------------------------------
    ******************************************************************************/

    #include <reg52.h>
    #include <string.h>

    #define LCM_Data P0
    #define Busy 0x80   //用于检测LCM状态字中的Busy标识
    sbit LCM_RW = P2^2;  //1602定义引脚
    sbit LCM_RS = P2^1;
    sbit LCM_E = P2^5;

    //sbit GPS_SPD=P1^2;
    //sbit SPD_TYPE=P1^3;
    sbit KEY1=P1^1;


    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 date[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);

    void WriteDataLCM(unsigned char WDLCM);
    void WriteCommandLCM(unsigned char WCLCM,BuysC);
    unsigned char ReadDataLCM(void);
    unsigned char ReadStatusLCM(void);
    void LCMInit(void);
    void LCD_cls(void);
    void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
    void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
    void Delay5Ms(void);
    void Delay400Ms(void);
    /******************************************************************************************
    * 函数名称    :
    * 功能描述    :
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    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();            //清屏
                    DisplayListChar(0,0,"No GPS connect..");
                    while(buf_full==0);
                    LCD_cls();   
                    dsp_count=0;
                 }
            }
            else if(lock=='V')   //GPRMC语句
                  {                    //如果未定位
                       DisplayListChar(0,2,"No Positioning");
                       LCD_cls();                  
                  }
                else
                  {                            //如果已定位
                       DisplayOneChar(0,0,JD_a);            //显示经度
                       DisplayOneChar(1,0,' ');
                       for(i=0;i<3;i++)
                       {
                            DisplayOneChar(i+1,0,JD[i]);
                       }
                       DisplayOneChar(4,0,'.');
                       for(i=3;i<10;i++)
                       {
                            DisplayOneChar(i+2,0,JD[i]);
                       }
           DisplayOneChar(0,1,WD_a);            //显示纬度
                       DisplayOneChar(1,1,' ');
                       for(i=0;i<2;i++)
                       {
                            DisplayOneChar(i+2,1,WD[i]);
                       }           
                       DisplayOneChar(4,1,'.');
                       for(i=2;i<9;i++)
                       {
                            DisplayOneChar(i+3,1,WD[i]);
                       }
                       DisplayOneChar(1,2,'2');        //日期2009-03-24
                       DisplayOneChar(2,2,'0');
           DisplayOneChar(3,2,date[4]);
           DisplayOneChar(4,2,date[5]);
           DisplayOneChar(5,2,'-');
                       DisplayOneChar(6,2,date[2]);
                       DisplayOneChar(7,2,date[3]);
           DisplayOneChar(8,2,'-');
           DisplayOneChar(9,2,date[0]);
           DisplayOneChar(10,2,date[1]);
          
         Bhour=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA;
                        if(Bhour>=24)
                        {
                            Bhour-=24;
                        }
                        else if(Bhour<0)
                        {
                            Bhour+=24;
                        }
                    //    DisplayListChar(2,3,"BJT ");
                        DisplayOneChar(1,3,Bhour/10+0x30);
                        DisplayOneChar(2,3,Bhour%10+0x30);
                        DisplayOneChar(3,3,':');
                        DisplayOneChar(4,3,time[2]);
                        DisplayOneChar(5,3,time[3]);
                        DisplayOneChar(6,3,':');
                        DisplayOneChar(7,3,time[4]);
                        DisplayOneChar(8,3,time[5]);
                     //   if(spd_type)
                     //   {
                     //       DisplayListChar(5,3,"km/h A");
                     //   }
                     //   else
                     //   {
                     //       DisplayListChar(5,3,"knot A");
                     //   }
                                              
                     //   if(spd_type)
                     //   {                    //km/h显示
                      //      for(i=0;i<5;i++)
                     //       {
                     //            DisplayOneChar(i,0,speed[i]);
                     //       }
                      //  }
                      //  else
        // {                             //knot显示
                      //      Knots=    (((speed[0]-0x30)*1000
                      //                 +(speed[1]-0x30)*100
                      //                 +(speed[2]-0x30)*10
                      //                 +(speed[4]-0x30))*1000)/1852;
                      //      DisplayOneChar(0,3,Knots/1000+0x30);
                      //      DisplayOneChar(1,3,(Knots%1000)/100+0x30);
                      //      DisplayOneChar(2,3,(Knots%100)/10+0x30);
                      //      DisplayOneChar(3,3,'.');
                      //      DisplayOneChar(4,3,Knots%10+0x30);
                      //   }
                      //   for(i=0;i<5;i++)
                      //   {
                      //     DisplayOneChar(11+i,0,angle[i]);
                      //   }
                    }
                       
                     
                dsp_count=0;
             }
    }

    /******************************************************************************************
    * 函数名称    :
    * 功能描述    :
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    bit chk_key(void)
    {
        if(!KEY1)
         {
            Delay5Ms();
            Delay5Ms();
            if(!KEY1)
             {
                while(!KEY1);
                Delay5Ms();
                Delay5Ms();
                return(1);
             }
         }
        return(0);
    }

    /******************************************************************************************
    * 函数名称    :sys_init
    * 功能描述    :系统初始化
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void sys_init()
    {
      
        SCON = 0x50;     /* SCON: mode 1, 8-bit UART, enable rcvr */
        TMOD = 0x21;     /* TMOD: timer 1, mode 2, 8-bit reload */
        TH1 = 0xfa;            /* TH1: reload value for 4800 baud @ 11.059MHz */

      
        spd_type=1;            //速度单位km/h
       
        TR1 = 1;         /* TR1: timer 1 run */
        LCMInit();        //初始化LCD
        DisplayListChar(0,0,"GPS Monitor V1.2");
        Delay400Ms();
        LCD_cls();
        IE=0x90;            //开总中断、串口中断
    }

    /******************************************************************************************
    * 函数名称    :WriteDataLCM
    * 功能描述    :写数据
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void WriteDataLCM(unsigned char WDLCM)
    {
      ReadStatusLCM(); //检测忙
      LCM_Data = WDLCM;
      LCM_RS = 1;
      LCM_RW = 0;
      LCM_E = 0; //若晶振速度太高可以在这后加小的延时
      LCM_E = 0; //延时
      LCM_E = 1;
    }

    /******************************************************************************************
    * 函数名称    :WriteCommandLCM
    * 功能描述    :写指令
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
    {
      if (BuysC)
      ReadStatusLCM(); //根据需要检测忙
      LCM_Data = WCLCM;
      LCM_RS = 0;
      LCM_RW = 0;
      LCM_E = 0;
      LCM_E = 0;
      LCM_E = 1;
    }

    /******************************************************************************************
    * 函数名称    :ReadStatusLCM
    * 功能描述    :读状态
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    unsigned char ReadStatusLCM(void)
    {
      LCM_Data = 0xFF;
      LCM_RS = 0;
      LCM_RW = 1;
      LCM_E = 0;
      LCM_E = 0;
      LCM_E = 1;
      while (LCM_Data & Busy); //检测忙信号
      return(LCM_Data);
    }
    /******************************************************************************************
    * 函数名称    :LCMInit
    * 功能描述    :LCM初始化
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void LCMInit(void)
    {
         Delay400Ms();
      LCM_Data = 0;
      WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
      Delay5Ms();
      WriteCommandLCM(0x38,0);
      Delay5Ms();
      WriteCommandLCM(0x38,0);
      Delay5Ms();

      WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
      WriteCommandLCM(0x08,1); //关闭显示
      WriteCommandLCM(0x01,1); //显示清屏
      WriteCommandLCM(0x06,1); // 显示光标移动设置
      WriteCommandLCM(0x0C,1); // 显示开及光标设置
    }
    /******************************************************************************************
    * 函数名称    :LCMInit
    * 功能描述    :LCM初始化
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void LCD_cls(void)
    {
      WriteCommandLCM(0x01,0);
      Delay5Ms();
    }
    /******************************************************************************************
    * 函数名称    :DisplayOneChar
    * 功能描述    :按指定位置显示一个字符
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
    {
    //  Y &= 0x1;
      X &= 0xF; //限制X不能大于15,Y不能大于1
           
      switch(Y)
      {

       case 0: 
        X += 0x00; //当要显示第一行时地址码+0x40;
        X += 0x80; //算出指令码
        WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
        WriteDataLCM(DData);
       case 1: 
        X += 0x40; //当要显示第二行时地址码+0x40;
        X += 0x80; //算出指令码
        WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
        WriteDataLCM(DData);
           break;
       case 2:
        X += 0x10; //当要显示第三行时地址码+0x10;
        X += 0x80; //算出指令码
        WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
        WriteDataLCM(DData);
           break;
       case 3:
        X += 0x50; //当要显示第四行时地址码+0x50;
        X += 0x80; //算出指令码
        WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
        WriteDataLCM(DData);
           break;
       
       default: break;
      }
      
    }
    /******************************************************************************************
    * 函数名称    :DisplayListChar
    * 功能描述    :按指定位置显示一串字符  ***原来的遇到空格0x20就不显示***
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
    {
       unsigned char ListLength,j;
       ListLength = strlen(DData);
    //   Y &= 0x1;
       X &= 0xF; //限制X不能大于15,Y不能大于1
        if (X <= 0xF) //X坐标应小于0xF
          {
          for(j=0;j<ListLength;j++)
           {
                  DisplayOneChar(X, Y, DData[j]); //显示单个字符
                  X++;
                 }
           }
    }

    /******************************************************************************************
    * 函数名称    :Delay5M
    * 功能描述    :5ms延时
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void Delay5Ms(void)
    {
       unsigned int TempCyc = 5552;
       while(TempCyc--);
    }
    /******************************************************************************************
    * 函数名称    :Delay400Ms
    * 功能描述    :400ms延时
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    void Delay400Ms(void)
    {
       unsigned char TempCycA = 5;
       unsigned int TempCycB;
       while(TempCycA--)
      {
       TempCycB=7269;
       while(TempCycB--);
      };
    }

    /******************************************************************************************
    * 函数名称    :uart
    * 功能描述    :串口接收中断
    * 参数        :  参数名称: 输入/输出? 类型  描述
    *
    * 返回值      :
    * 作者        :
    * 创建日期    :2006-12-19
    * 全局变量    :
    * 全局静态变量:
    * 局部静态变量:
    *----------------------------------------修改历史------------------------------------------
    * 当前版本    :     修改人:                  修改日期:
    * 修改说明    :
    ******************************************************************************************/
    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]=='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 3:                //类型3数据接收。GPRMC
                                switch(seg_count)
                                {
                                    case 1:
                                        if(byte_count<6)
                                         {                //时间处理
                                            time[byte_count]=tmp;   
                                         }
                                        break;
            case 2:                                //定位判断A or V
                                        if(byte_count<1)
                                         {
                                            lock=tmp;
                                         }
            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;
    }

  • 相关阅读:
    第八次作业
    设计一款给爸爸妈妈用的手机
    第五次作业
    第四次作业(项目分析)
    第二次作业(个人项目实践)
    即时通讯软件的发展演变
    C++用法的学习心得
    JavaScript(变量、作用域和内存问题)
    一、Java和JavaScript
    使用Hyper-V创建虚拟机
  • 原文地址:https://www.cnblogs.com/pulan/p/2921652.html
Copyright © 2020-2023  润新知