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;
}

原文地址:https://www.cnblogs.com/pulan/p/2921652.html