找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1380|回复: 0
打印 上一主题 下一主题
收起左侧

STM32单片机AIR551G GPS定位程序

[复制链接]
跳转到指定楼层
楼主
合轴551G模块,移植了正点原子的开发板程序

STM32单片机源程序如下:
  1. #include "gps.h"
  2. #include "led.h"
  3. #include "SysTick.h"                                                           
  4. #include "usart3.h"                                                                    
  5. #include "stdio.h"         
  6. #include "stdarg.h"         
  7. #include "string.h"         
  8. #include "math.h"
  9.          

  10.                                                   
  11. u8 NMEA_Comma_Pos(u8 *buf,u8 cx)
  12. {                             
  13.         u8 *p=buf;
  14.         while(cx)
  15.         {                 
  16.                 if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF;//遇到'*'或者非法字符,则不存在第cx个逗号
  17.                 if(*buf==',')cx--;
  18.                 buf++;
  19.         }
  20.         return buf-p;         
  21. }
  22. //m^n函数
  23. //返回值:m^n次方.
  24. u32 NMEA_Pow(u8 m,u8 n)
  25. {
  26.         u32 result=1;         
  27.         while(n--)result*=m;   
  28.         return result;
  29. }
  30. //str转换为数字,以','或者'*'结束
  31. //buf:数字存储区
  32. //dx:小数点位数,返回给调用函数
  33. //返回值:转换后的数值
  34. int NMEA_Str2num(u8 *buf,u8*dx)
  35. {
  36.         u8 *p=buf;
  37.         u32 ires=0,fres=0;
  38.         u8 ilen=0,flen=0,i;
  39.         u8 mask=0;
  40.         int res;
  41.         while(1) //得到整数和小数的长度
  42.         {
  43.                 if(*p=='-'){mask|=0X02;p++;}//是负数
  44.                 if(*p==','||(*p=='*'))break;//遇到结束了
  45.                 if(*p=='.'){mask|=0X01;p++;}//遇到小数点了
  46.                 else if(*p>'9'||(*p<'0'))        //有非法字符
  47.                 {        
  48.                         ilen=0;
  49.                         flen=0;
  50.                         break;
  51.                 }        
  52.                 if(mask&0X01)flen++;
  53.                 else ilen++;
  54.                 p++;
  55.         }
  56.         if(mask&0X02)buf++;        //去掉负号
  57.         for(i=0;i<ilen;i++)        //得到整数部分数据
  58.         {  
  59.                 ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');
  60.         }
  61.         if(flen>5)flen=5;        //最多取5位小数
  62.         *dx=flen;                         //小数点位数
  63.         for(i=0;i<flen;i++)        //得到小数部分数据
  64.         {  
  65.                 fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0');
  66.         }
  67.         res=ires*NMEA_Pow(10,flen)+fres;
  68.         if(mask&0X02)res=-res;                  
  69.         return res;
  70. }                                                                  
  71. //分析GPGSV信息    可见卫星信息
  72. //gpsx:nmea信息结构体
  73. //buf:接收到的GPS数据缓冲区首地址
  74. void NMEA_GPGSV_Analysis(nmea_msg *gpsx,u8 *buf)
  75. {
  76.         u8 *p,*p1,dx;
  77.         u8 len,i,j,slx=0;
  78.         u8 posx;            
  79.         p=buf;
  80.         p1=(u8*)strstr((const char *)p,"$GPGSV");
  81.         len=p1[7]-'0';                                                                //得到GPGSV的条数
  82.         posx=NMEA_Comma_Pos(p1,3);                                         //得到可见卫星总数
  83.         if(posx!=0XFF)gpsx->svnum=NMEA_Str2num(p1+posx,&dx);
  84.         for(i=0;i<len;i++)
  85.         {         
  86.                 p1=(u8*)strstr((const char *)p,"$GPGSV");  
  87.                 for(j=0;j<4;j++)
  88.                 {         
  89.                         posx=NMEA_Comma_Pos(p1,4+j*4);
  90.                         if(posx!=0XFF)gpsx->slmsg[slx].num=NMEA_Str2num(p1+posx,&dx);        //得到卫星编号
  91.                         else break;
  92.                         posx=NMEA_Comma_Pos(p1,5+j*4);
  93.                         if(posx!=0XFF)gpsx->slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx);//得到卫星仰角
  94.                         else break;
  95.                         posx=NMEA_Comma_Pos(p1,6+j*4);
  96.                         if(posx!=0XFF)gpsx->slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角
  97.                         else break;
  98.                         posx=NMEA_Comma_Pos(p1,7+j*4);
  99.                         if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx);        //得到卫星信噪比
  100.                         else break;
  101.                         slx++;           
  102.                 }   
  103.                  p=p1+1;//切换到下一个GPGSV信息
  104.         }   
  105. }
  106. //分析BDGSV信息
  107. //gpsx:nmea信息结构体
  108. //buf:接收到的GPS数据缓冲区首地址
  109. void NMEA_BDGSV_Analysis(nmea_msg *gpsx,u8 *buf)
  110. {
  111.         u8 *p,*p1,dx;
  112.         u8 len,i,j,slx=0;
  113.         u8 posx;            
  114.         p=buf;
  115.         p1=(u8*)strstr((const char *)p,"$BDGSV");
  116.         len=p1[7]-'0';                                                                //得到BDGSV的条数
  117.         posx=NMEA_Comma_Pos(p1,3);                                         //得到可见北斗卫星总数
  118.         if(posx!=0XFF)gpsx->beidou_svnum=NMEA_Str2num(p1+posx,&dx);
  119.         for(i=0;i<len;i++)
  120.         {         
  121.                 p1=(u8*)strstr((const char *)p,"$BDGSV");  
  122.                 for(j=0;j<4;j++)
  123.                 {         
  124.                         posx=NMEA_Comma_Pos(p1,4+j*4);
  125.                         if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_num=NMEA_Str2num(p1+posx,&dx);        //得到卫星编号
  126.                         else break;
  127.                         posx=NMEA_Comma_Pos(p1,5+j*4);
  128.                         if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_eledeg=NMEA_Str2num(p1+posx,&dx);//得到卫星仰角
  129.                         else break;
  130.                         posx=NMEA_Comma_Pos(p1,6+j*4);
  131.                         if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角
  132.                         else break;
  133.                         posx=NMEA_Comma_Pos(p1,7+j*4);
  134.                         if(posx!=0XFF)gpsx->beidou_slmsg[slx].beidou_sn=NMEA_Str2num(p1+posx,&dx);        //得到卫星信噪比
  135.                         else break;
  136.                         slx++;           
  137.                 }   
  138.                  p=p1+1;//切换到下一个BDGSV信息
  139.         }   
  140. }
  141. //分析GNGGA信息
  142. //gpsx:nmea信息结构体
  143. //buf:接收到的GPS数据缓冲区首地址
  144. void NMEA_GNGGA_Analysis(nmea_msg *gpsx,u8 *buf)
  145. {
  146.         u8 *p1,dx;                        
  147.         u8 posx;   
  148.         p1=(u8*)strstr((const char *)buf,"$GNGGA");
  149.         posx=NMEA_Comma_Pos(p1,6);                                                                //得到GPS状态
  150.         if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);        
  151.         posx=NMEA_Comma_Pos(p1,7);                                                                //得到用于定位的卫星数
  152.         if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx);
  153.         
  154.         posx=NMEA_Comma_Pos(p1,8);                                                                //水平位置精度
  155.         if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);
  156.         
  157.         posx=NMEA_Comma_Pos(p1,9);                                                                //得到海拔高度  
  158.         if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);  
  159. }
  160. //分析GNGSA信息
  161. //gpsx:nmea信息结构体
  162. //buf:接收到的GPS数据缓冲区首地址
  163. void NMEA_GNGSA_Analysis(nmea_msg *gpsx,u8 *buf)
  164. {
  165.         u8 *p1,dx;                        
  166.         u8 posx;
  167.         u8 i;   
  168.         p1=(u8*)strstr((const char *)buf,"$GNGSA");
  169.         posx=NMEA_Comma_Pos(p1,2);                                                                //得到定位类型
  170.         if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx);        
  171.         for(i=0;i<12;i++)                                                                                //得到定位卫星编号
  172.         {
  173.                 posx=NMEA_Comma_Pos(p1,3+i);                                         
  174.                 if(posx!=0XFF)gpsx->possl[i]=NMEA_Str2num(p1+posx,&dx);
  175.                 else break;
  176.         }                                 
  177.         posx=NMEA_Comma_Pos(p1,15);                                                                //得到PDOP位置精度因子
  178.         if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx);  
  179.         posx=NMEA_Comma_Pos(p1,16);                                                                //得到HDOP位置精度因子
  180.         if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);  
  181.         posx=NMEA_Comma_Pos(p1,17);                                                                //得到VDOP位置精度因子
  182.         if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx);  
  183. }
  184. //分析GNRMC信息
  185. //gpsx:nmea信息结构体
  186. //buf:接收到的GPS数据缓冲区首地址
  187. void NMEA_GNRMC_Analysis(nmea_msg *gpsx,u8 *buf)
  188. {
  189.         u8 *p1,dx;                        
  190.         u8 posx;     
  191.         u32 temp;           
  192.         float rs;  
  193.         p1=(u8*)strstr((const char *)buf,"$GNRMC");//"$GNRMC",经常有&和GNRMC分开的情况,故只判断GPRMC.
  194.         posx=NMEA_Comma_Pos(p1,1);                                                                //得到UTC时间
  195.         if(posx!=0XFF)
  196.         {
  197.                 temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx);                 //得到UTC时间,去掉ms
  198.                 gpsx->utc.hour=temp/10000;
  199.                 gpsx->utc.min=(temp/100)%100;
  200.                 gpsx->utc.sec=temp%100;                  
  201.         }        
  202.         posx=NMEA_Comma_Pos(p1,3);                                                                //得到纬度
  203.         if(posx!=0XFF)
  204.         {
  205.                 temp=NMEA_Str2num(p1+posx,&dx);                          
  206.                 gpsx->latitude=temp/NMEA_Pow(10,dx+2);        //得到°
  207.                 rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
  208.                 gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为°
  209.         }
  210.         posx=NMEA_Comma_Pos(p1,4);                                                                //南纬还是北纬
  211.         if(posx!=0XFF)gpsx->nshemi=*(p1+posx);                                         
  212.          posx=NMEA_Comma_Pos(p1,5);                                                                //得到经度
  213.         if(posx!=0XFF)
  214.         {                                                                                                  
  215.                 temp=NMEA_Str2num(p1+posx,&dx);                          
  216.                 gpsx->longitude=temp/NMEA_Pow(10,dx+2);        //得到°
  217.                 rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
  218.                 gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为°
  219.         }
  220.         posx=NMEA_Comma_Pos(p1,6);                                                                //东经还是西经
  221.         if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);        
  222.    posx=NMEA_Comma_Pos(p1,7);              //获取地面速度
  223.         if(posx!=0XFF)gpsx->lspeed=*(p1+posx);        
  224.         
  225.         posx=NMEA_Comma_Pos(p1,9);                                                                //得到UTC日期
  226.         if(posx!=0XFF)
  227.         {
  228.                 temp=NMEA_Str2num(p1+posx,&dx);                                                 //得到UTC日期
  229.                 gpsx->utc.date=temp/10000;
  230.                 gpsx->utc.month=(temp/100)%100;
  231.                 gpsx->utc.year=2000+temp%100;                  
  232.         }
  233. }
  234. //分析GNVTG信息
  235. //gpsx:nmea信息结构体
  236. //buf:接收到的GPS数据缓冲区首地址
  237. void NMEA_GNVTG_Analysis(nmea_msg *gpsx,u8 *buf)
  238. {
  239.         u8 *p1,dx;                        
  240.         u8 posx;   
  241.         p1=(u8*)strstr((const char *)buf,"$GNVTG");                                                         
  242.         posx=NMEA_Comma_Pos(p1,7);                                                                //得到地面速率
  243.         if(posx!=0XFF)
  244.         {
  245.                 gpsx->speed=NMEA_Str2num(p1+posx,&dx);
  246.                 if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx);                                  //确保扩大1000倍
  247.         }
  248. }  
  249. //提取NMEA-0183信息
  250. //gpsx:nmea信息结构体
  251. //buf:接收到的GPS数据缓冲区首地址
  252. void GPS_Analysis(nmea_msg *gpsx,u8 *buf)
  253. {
  254.         NMEA_GPGSV_Analysis(gpsx,buf);        //GPGSV解析
  255.         NMEA_BDGSV_Analysis(gpsx,buf);        //BDGSV解析
  256.         NMEA_GNGGA_Analysis(gpsx,buf);        //GNGGA解析         
  257.         NMEA_GNGSA_Analysis(gpsx,buf);        //GPNSA解析
  258.         NMEA_GNRMC_Analysis(gpsx,buf);        //GPNMC解析
  259.         NMEA_GNVTG_Analysis(gpsx,buf);        //GPNTG解析
  260. }

  261. /**********************************
  262. 功能:发送数据到GPS模块
  263. 日期:2022.12.14
  264. 参数:cmd AT命令
  265. 返回值: 无
  266. *****************************/
  267. void SendAtToGps(u8 *cmd)
  268. {
  269.   while (*cmd !='\0')
  270.         {
  271.          USART_SendData(USART3,*cmd++);
  272.                 while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==Bit_RESET);
  273.         }
  274. }


  275. /****************************
  276. 功能:检查GPS模块应答是否符合预期
  277. 日期:2022.12.14
  278. 参数:str 正确应答
  279. 返回值:无
  280. ***************************/
  281. u8 GpsAckChack(u8 *str)
  282. {
  283. //u8 str[225];
  284.         delay_ms(500);
  285. if(USART3_RX_STA !=0)
  286. {
  287.    USART3_RX_STA=0;
  288.          if(strstr ((const char*)USART3_RX_BUF,(const char*)str))
  289.          {
  290.            memset(USART3_RX_BUF,0, sizeof USART3_RX_BUF);  //符合预期
  291.                  return 0;
  292.          }
  293.          else
  294.          {
  295.          memset(USART3_RX_BUF,0, sizeof USART3_RX_BUF);  //不符合预期
  296.                  return 1;
  297.                  //清空数组
  298.          }
  299. }
  300. else
  301. {
  302. memset(USART3_RX_BUF,0, sizeof USART3_RX_BUF);  
  303.          return  1;
  304. }  
  305. }

  306. /*********************************************
  307. 功能:GPS模块初始化
  308. 日期:2022.12.14
  309. 参数: 无
  310. 返回值:无
  311. *********************************************/

  312. void Gps_Init()
  313. {
  314.         cmd1:SendAtToGps (ColdStart); //发送冷启动指令
  315.         delay_ms(50);
  316.         if(!GpsAckChack ("$GNTXT,GK9701*7E..$GNTXT,HW:V190"));
  317.                 else goto cmd1;
  318.         cmd2:SendAtToGps (GPSL1L5); //全系统模式
  319.         delay_ms(50);
  320.         if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190"))  ;
  321.           else goto  cmd2;
  322.         cmd3:SendAtToGps(OpenSBAS);    //开启SBAS 功能
  323.              delay_ms(50);        
  324.                          if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190"))  ;
  325.              else goto  cmd3;
  326.         cmd4:SendAtToGps(delay1sNMEA); //配置输出 NMEA 消息的间隔 1s
  327.        delay_ms(50);        
  328.              if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190"))  ;
  329.              else goto  cmd4;
  330.         cmd5:SendAtToGps(EnableRMC);   //设置 NMEA 语句输出使能  使能RMC
  331.        delay_ms(50);        
  332.              if (!GpsAckChack("$GNTXT,GK9701*7E..$GNTXT,HW:V190"))  ;
  333.              else goto  cmd5;

  334.                          SendAtToGps(MoreFast);//加速定位信息

  335. }
复制代码


Keil代码下载:
AIR551G.7z (6.28 MB, 下载次数: 18)

评分

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

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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