找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 15720|回复: 10
收起左侧

最简GPS数据接收程序

  [复制链接]
ID:73833 发表于 2015-6-2 16:33 | 显示全部楼层 |阅读模式
本帖最后由 dingmingzhou 于 2015-7-14 14:20 编辑

写在前面的话:一段时间以来,以8051为对象学单片机。有写感受,写出来和大家共商酌。一开始我也是从流水灯、数码管、1602、12864一路赶来,感觉单片机这玩意,就是“SWRD”这几下子:S(Set):设置--设置寄存器、变量……;W(Wrte):就是写数据写命令;R(Read):就是读数据;D(display):就是显示.也没神魔大意思,但是,遵从规则--器件和C语言规则是必须的,头疼人的时候,都是这“规则”闹得,把他拿下,多半就艳阳天了。
最近俺看上TFT彩屏了,还没研究出个啥来,不多啰嗦,估计也离不开 SWRD这几下子。
      GPS,没接触前,感觉这东西可是一个“高、大、上”的东西。神妙莫测,没出下手----卫星在天上呢!其实有了GPS模块,研究了一下材料(2天呀),没想到,这东西比DS18B20\DS1302都好搞---就是串口以4800(或9600)比特率输出一串串格式化的ASCII串,且每秒钟更新一次。呵呵。处理这个字符串基本有两种法子:一是:”下载“整串,在进行复制、截取、转换;二是”单抠“有用的、想要的东西。鉴于51单片机片内RAM的拮据、处理浮点数的囧态,下面贴上来的程序是按第二种法子做的。说明如下:
1、只”抠“经纬度及方向、海拔、速度、时间、日期、方位角这几项
2、定义单项的字符数组,分别赋值,并规整成 通常的格式,以便显示时,顺序显示字符数组元素。
3、本程序仅是数据包解析部分,显示函数没写,想着把TFT搞懂了,显在那上边,过一把瘾。
4、程序是按照我自己的理解去写的、也去参考别人的。或有BUG多多,不反对拍砖。
程序清单

评分

参与人数 1黑币 +4 收起 理由
qjzyx + 4 赞一个!

查看全部评分

回复

使用道具 举报

ID:73833 发表于 2015-6-2 17:27 | 显示全部楼层
本帖最后由 dingmingzhou 于 2015-7-14 14:23 编辑
  1. #include<reg52.h>
  2. #define  uchar unsigned char
  3. #define  uint unsigned int
  4. /***********GPS数据存储数组***********/
  5. uchar JD[10]; //经度准备存为***.**.**. 形式,
  6. uchar JD_a; //经度方向
  7. uchar WD[9];  //纬度准备存为**.**.**.形式,
  8. uchar WD_a; //纬度方向
  9. uchar date[9];//日期准备存为**-**-** 形式
  10. uchar time[9];//时间准备存为**:**:** 形式。
  11. uchar speed[6];//速度准备存为        ***.*形式
  12. uchar high[8];//高度准备存为        ****.* 形式
  13. uchar angle[6]; //方位角准备存为  ***.* 形式
  14. bit lock; //定位状态  0 ,1
  15. /*********串口中断及数据处理需要的变量***********/
  16. uchar tmp;                //串口数据缓冲
  17. uchar seg_count; //逗号计数器
  18. uchar byte_count; //位数计数器
  19. uchar cmd_number; //命令类型 0:无效;1:GGA;2:RMC
  20. uchar mode;       //0:结束模式,1:命令模式,2:数据模式
  21. uchar buf_full=0; //设定语句接收完成,相应数据有效。0:无效。
  22. uchar cmd[5];      //命令内容存储数组
  23. /******************        系统初始化*************/
  24. void sys_init()        
  25. {
  26.         SCON = 0x50;  /*  定时器1 M0=0,M1=1,REN=1 */
  27.         TMOD = 0x20;  /* TMOD: 定时器1模式2自动重装*/  
  28.         TH1 = 0xfa;  /* 11.0592MHZ 波特率4800*/               
  29.         TL1 = 0xfa;
  30.         ES=1;
  31.         TR1=1;   
  32.         EA=1;                                         
  33.   }
  34. /******************        显示函数*************/
  35. void display()
  36. {
  37. ;
  38. }
  39. /******************        主函数********************/
  40. main()
  41. {
  42.      uchar Bhh,Bdd,Bmm,Byy;         //格伦威治时间转换为北京时间变量
  43.      unsigned long mn;         //定义经度纬度局部变量   
  44.           uint mnn;            
  45.      sys_init();         //系统初始化        
  46.          while(1)
  47.          {                     
  48.           switch(tmp)         //传来的数据(即ASCII码,一个ASCII码是8位,一个字节)进行对号入座
  49.             {
  50.              case ':        //起始符
  51.                                cmd_number=0; //命令类型清空        
  52.                                mode=1;       //接收命令模式  0:结束模式,1:命令模式,2:数据模式
  53.                                byte_count=0; //接收位数清空,位数计数器=0;标记一种(如高度、速度等)数据多少位
  54.                        break;            
  55.                                 
  56.                  case ',':                   //分隔符,它分隔各种数据
  57.                                    seg_count++; //逗号计数加1        ,一个”,”号前是一个有效数据
  58.                                    byte_count=0; //接收位数清空
  59.                        break;
  60.              case '*':                   //一旦遇到*, 如下处理:
  61.                                switch(cmd_number)         //命令类型共2种???
  62.                                    {
  63.                                     case 1: {buf_full|=0x01; break;}//或上的0x01标志第1种命令                                                                                                                                                                                                                    
  64.                                                 case 2: {buf_full|=0x04; break;}//或上的0x04标志第2种命令                                                                 
  65.                                    }
  66.                                    mode=0;  //结束模式
  67.                                         while(buf_full==0x05)  //如果GGA和RMC语句都解析完成。
  68.                                           {
  69.                                                   EA=0; REN=0;        //        显示时关中断和串口接收,                                 
  70.                                                   buf_full=0;                 //为下一个循环做准备
  71.                                                   display();         //显示函数。
  72.                                                     EA=1; REN=1;        // 显示完成再打开中断和串口。
  73.                                            }
  74.                             break; //跳出 switch(tmp)去重新寻找“$”符号。
  75.              default:          //到这里是tmp不等于“*”和“,”及“$”的情况下。                                       
  76.                         if(mode==1)           //判断命令种类
  77.                         {               
  78.                            cmd[byte_count]=tmp; //接收字符放入类型缓存
  79.                            if(byte_count>=4)         //如果类型数据接收完毕,只判断语句名
  80.                            {                                 
  81.                                  if((cmd[2]=='G')&&(cmd[3]=='G')&&(cmd[4]=='A'))
  82.                                    {
  83.                                     cmd_number=1;           //GGA
  84.                                         mode=2;
  85.                                         seg_count=0;
  86.                                         byte_count=0;         
  87.                                    }
  88.                                  if((cmd[2]=='R')&&(cmd[3]=='M')&&(cmd[4]=='C'))
  89.                                     {
  90.                                       cmd_number=2;         //RMC
  91.                                           mode=2;
  92.                                           seg_count=0;
  93.                                           byte_count=0;
  94.                                     }
  95.                            }                                                
  96.                         }else if(mode==2)
  97.                                    {        
  98.                             switch (cmd_number)         
  99.                               {
  100.                                   case 1: //接收GPGGA                                                                           
  101.                                                  if((seg_count==9)&&(byte_count<7))high[byte_count]=tmp;//高度是7位                                                
  102.                                                                    high[byte_count+1] ='\0';   //高度输出的位数不固定,但byte_count+1个元素一定应该加'\0'.
  103.                                                                  break;         //跳出        switch (cmd_number)        
  104.                                   case 2: //接收GPRMC
  105.                                                 switch(seg_count)
  106.                                                                         {
  107.                                                    case 1: //UTC时间暂存
  108.                                                           if(byte_count<6)time[byte_count]=tmp;
  109.                                                                                           break;                 
  110.                                                    case 2: //定位判断
  111.                                                           if(byte_count<1)          //状态
  112.                                                             { if (tmp=='A') lock=1;        else  lock=0; }                                             
  113.                                                                                            break;
  114.                                                    case 3: //纬度处理小数点后的数据
  115.                                                            if(byte_count<9)WD[byte_count]=tmp;
  116.                                                                                               if(byte_count==8)
  117.                                                                                                    {
  118.                                                                                                    mn=((WD[5]-'0')*1000+(WD[6]-'0')*100+(WD[7]-'0')*10+(WD[8]-'0'))*60;        //仅处理4位小数位
  119.                                                                                                    mnn=mn/10000;
  120.                                                                                                    WD[3]=WD[2];
  121.                                                                                                    WD[4]=WD[3];
  122.                                                                                                    WD[2]='.';
  123.                                                                                                    WD[5]='.';
  124.                                                                                                    WD[6]= mnn/10+'0';
  125.                                                                                                    WD[7]= mnn%10+'0';
  126.                                                                                                    WD[8]= '\0';
  127.                                                                                                   }
  128.                                                                                            break;
  129.                                                    case 4: //纬度方向处理
  130.                                                            if(byte_count<1)WD_a=tmp;
  131.                                                                                     
  132.                                                                                            break;
  133.                                                    case 5: //经度处理小数点后的数据
  134.                                                            if(byte_count<10) JD[byte_count]=tmp;
  135.                                                                                        if(byte_count==9)
  136.                                                                                                    {
  137.                                                                                                    mn=((JD[6]-'0')*1000+(JD[7]-'0')*100+(JD[8]-'0')*10+(JD[9]-'0'))*60;        //仅处理4位小数位        
  138.                                                                                                    mnn=mn/10000;                                                                                                                                                                                                      
  139.                                                                                                    JD[4]=JD[3];
  140.                                                                                                    JD[5]=JD[4];
  141.                                                                                                    JD[3]='.';
  142.                                                                                                    JD[6]='.';
  143.                                                                                                    JD[7]=mnn/10+'0';
  144.                                                                                                    JD[8]=mnn%10+'0';
  145.                                                                                                    JD[9]='\0';
  146.                                                                                                   }
  147.                                                                                            break;
  148.                                                    case 6: //经度方向处理
  149.                                                            if(byte_count<1)JD_a=tmp;         
  150.                                                                                        
  151.                                                                                            break;
  152.                                                    case 7: //速度是格式输出 //本量程处理于540节以下即1000公里/小时以内,一位小数点。
  153.                                                            if(byte_count<5)speed[byte_count]=tmp;
  154.                                                                                        if(byte_count==4)
  155.                                                                                             {
  156.                                                                                                     mn=((speed[0]-'0')*1000+(speed[1]-'0')*100+(speed[2]-'0')*10+(speed[4]-'0'))*185;
  157.                                                                                                     mnn=mn/100;                // 此时速度仍然被扩大了10倍。
  158.                                                                                                         if(mnn/1000==0)speed[0]=0x20;                           //高位消隐
  159.                                                                                                                             else  speed[0]=mnn/1000+'0';
  160.                                                                                                         if((mnn/1000==0)&&((mnn%1000 )/100)==0)speed[1]=0x20;//高位消隐
  161.                                                                                                                             else  speed[1]=(mnn%1000 )/100+'0';
  162.                                                                                                         if(((mnn/1000==0)&&((mnn%1000 )/100)==0)&&((mnn%100)/10==0))speed[2]=0x20; //高位消隐
  163.                                                                                                                            else  speed[2]=(mnn%100)/10+'0';
  164.                                                                                                                                                 
  165.                                                                                                         speed[4]=mnn%10+'0';        //  小数位         
  166.                                                                                                                      speed[5]='\0';
  167.                                                                                             }
  168.                                                                                            break;                 
  169.                                                    case 8: //方位角处理
  170.                                                            if(byte_count<5) angle[byte_count]=tmp;
  171.                                                                                                angle[5]='\0';
  172.                                                                                            break;
  173.                                                    case 9: //日期处理
  174.                                                            if(byte_count<6)date[byte_count]=tmp;         
  175.                                                                                            if( byte_count==5)
  176.                                                                                                     {
  177.                                                                                                     Bhh=((time[0]-'0')*10+time[1]-'0')+8;//加8小时转换北京时间 加8小时会影响日期,故需调整
  178.                                                                                                     Bdd=(date[0]-'0')*10+(date[1]-'0');                                    
  179.                                                                                                     Bmm=(date[2]-'0')*10+(date[3]-'0');         
  180.                                                                                                     Byy=(date[4]-'0')*10+(date[5]-'0');
  181.                                                                                                    if(Bhh>23)
  182.                                                                                                      {
  183.                                                                                                            Bhh-=24;
  184.                                                                                                    Bdd+=1;
  185.                                                                                                                   if(Bmm==2&&Bmm==4&&Bmm==6&&Bmm==9&&Bmm==11)
  186.                                                                                                                         {
  187.                                                                                                                           if(Bdd>30){Bdd=1; Bmm++;}

  188.                                                                                                                          } else        if(Bdd>31){ Bdd=1; Bmm++;}               
  189.                
  190.                                                                                                               if(Byy % 4 == 0 )
  191.                                                                             {
  192.                                                                  if(Bdd > 29 && Bmm ==2){ Bdd=1;Bmm++; } //闰年的二月是29天
  193.         
  194.                                                                  } else if(Bdd>28 &&Bmm ==2){Bdd=1;Bmm++;}
  195.         
  196.                                                                                                           if(Bmm>12){Bmm-=12;Byy++;}
  197.                                                                                                   }  
  198.                                                                                                /*以下重新整理time[]和date[]数组*/
  199.                                                                                                          time[0]=Bhh/10+'0';        //把日期数组整理成 hh:mm:ss
  200.                                                                                                         time[1]=Bhh%10+'0';         
  201.                                                                                                         time[3]=time[2];        
  202.                                                                                                         time[4]=time[3];
  203.                                                                                                         time[2]=':';        
  204.                                                                                                         time[6]=time[4];        
  205.                                                                                                         time[7]=time[5];                 
  206.                                                                                                         time[5]=':';        
  207.                                                                                                         time[8]='\0';

  208.                                                                                                         date[0]=Byy/10+'0';//把日期数组整理成 yy-mo-dd
  209.                                                                                                         date[1]=Byy%10+'0';
  210.                                                                                                         date[2]='-';
  211.                                                                                                         date[3]=Bmm/10+'0';
  212.                                                                                                         date[4]=Bmm%10+'0';
  213.                                                                                                         date[5]='-';        
  214.                                                                                                         date[6]=Bdd/10+'0';
  215.                                                                                                         date[7]=Bdd%10+'0';
  216.                                                                                                         date[8]='\0';
  217.                                                                                                   }
  218.                                                                                     break;
  219.                                                           default:        break;
  220.                                                                     }
  221.                                        break;        //跳出        switch (cmd_number)        
  222.                                     }
  223.                                  }
  224.                         byte_count++; //接收数位加1
  225.                         break; //跳出 switch(tmp)                              
  226.                 }
  227.            
  228.     }
  229. }           
  230. /******************        中断服务函数*************/
  231. void uart(void) interrupt 4          //串口接收中断
  232.   {        
  233.          tmp=SBUF;                           
  234.          RI=0;  
  235.   }        
  236. /********************************************/
复制代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的积分奖励!

查看全部评分

回复

使用道具 举报

ID:264279 发表于 2017-12-20 15:25 | 显示全部楼层
这个就是拿液晶屏能显示的程序吗
回复

使用道具 举报

ID:253767 发表于 2017-12-22 15:20 | 显示全部楼层
学习了
回复

使用道具 举报

ID:265683 发表于 2017-12-23 15:13 | 显示全部楼层
可不可以把原工程发上来呀
回复

使用道具 举报

ID:88269 发表于 2018-1-27 16:31 | 显示全部楼层
正要学习这方面的东西
回复

使用道具 举报

ID:266116 发表于 2018-1-28 11:48 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:88269 发表于 2018-1-30 09:22 | 显示全部楼层
好资料,学习一下,谢谢分享
回复

使用道具 举报

ID:162136 发表于 2018-2-5 23:52 | 显示全部楼层
学习了,总结的在理。
回复

使用道具 举报

ID:43383 发表于 2019-1-5 14:35 | 显示全部楼层
只有GPS天线搞出来才高大上,有模块不是什么问题
回复

使用道具 举报

ID:239793 发表于 2019-1-14 19:33 | 显示全部楼层
第一个CASE 为什么会报错
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表