MSP430与ATK-NEO-6M GPS模块

[复制链接]
 楼主| nbnhnjnm 发表于 2019-2-27 18:47 | 显示全部楼层 |阅读模式
近短时间在网上买了一个GPS模块,正好正在学习MSP430单片机,于是决心将GPS模块与MSP430结合起来,同时将代码贴出来,发现网上搜到好多资料都要注册才能下载,有些还要钱。自己动脑,才能自娱自乐。
一、测试篇   
刚拿到ATK-NEO-6M这个型号的GPS模块,有点不大相信,近100块的东西居然只有3cm那么大一点。之前在网上下载了相关的资料,第一次快速测试肯定是借助电脑,正好msp430开发板上有max232模块,直接将GPS模块的TX接max232的TX,RX同样。PC端安装u-center,u-center 是由ublox 公司提供的GPS 评估软件,功能十分强大,可以对我们的ATK-NEO-6M GPS 模块进行全面的测试。安装好后,点击连接/断开按钮,选择你的串口号,一般测试都是选择自动配置按钮,也就是那个魔法样式的按钮,单击后会自己配置波特率,如果正常通讯的话,在最右下角的状态栏会显示黄色,当GPS模块已经定位成功的话,会在界面上显示当前的基本信息,如经度,纬度等。想查看接收到的原本信息,按F8键即可显示。我测试后工作正常,在屋里基本能搜到9颗卫星信号。

二、开发篇
刚拿到GPS模块,感觉要是开发起来会很麻烦,后来经过实验,其实很简单,因为卖家提供的资料已经足够开发。句段的分析函数都已提供,我们只需将接口写好即可。接下来先看看我的硬件环境。
硬件环境:MPS430开发板,FYD12864LCD显示屏,USB转串口线,ATK-NEO-6M GPS模块
软件环境:IAR集成开发环境,串口调试工具,Secure CRT
实现目标:MSP430通过串口2接收到GPS信息,显示在LCD上,同时通过串口1发送接收到的数据到PC。

1. 先把msp430的句段分析部分调通。
思路:将厂商提过的GPS语句分析部分代码移植过来,串口手动发送GPS数据,分析完后在LCD上显示。
将厂商提供的GPS语句分析代码贴出,(在此仅作为参考学习只用)
GPS.h
  1. <font size="2">#ifndef __GPS_H
  2. #define __GPS_H

  3. #include <math.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>

  7. #include "../inc/uart.h"

  8. //GPS NMEA-0183协议重要参数结构体定义
  9. //卫星信息
  10. typedef struct  
  11. {                                                                                    
  12.         uchar num;                //卫星编号
  13.         uchar eledeg;        //卫星仰角
  14.         uint azideg;        //卫星方位角
  15.         uchar sn;                //信噪比                  
  16. }nmea_slmsg;  
  17. //UTC时间信息
  18. typedef struct  
  19. {                                                                                    
  20.         uint year;        //年份
  21.         uchar month;        //月份
  22.         uchar date;        //日期
  23.         uchar hour;         //小时
  24.         uchar min;         //分钟
  25.         uchar sec;         //秒钟
  26. }nmea_utc_time;             
  27. //NMEA 0183 协议解析后数据存放结构体
  28. typedef struct  
  29. {                                                                                    
  30.         uchar svnum;                        //可见卫星数
  31.         nmea_slmsg slmsg[12];                //最多12颗卫星
  32.         nmea_utc_time utc;                //UTC时间
  33.         int latitude;                        //纬度 分扩大100000倍,实际要除以100000
  34.         uchar nshemi;                        //北纬/南纬,N:北纬;S:南纬                                  
  35.         int longitude;                        //经度 分扩大100000倍,实际要除以100000
  36.         uchar ewhemi;                        //东经/西经,E:东经;W:西经
  37.         uchar gpssta;                        //GPS状态:0,未定位;1,非差分定位;2,差分定位;6,正在估算.                                  
  38.         uchar posslnum;                        //用于定位的卫星数,0~12.
  39.         uchar possl[12];                        //用于定位的卫星编号
  40.         uchar fixmode;                        //定位类型:1,没有定位;2,2D定位;3,3D定位
  41.         uint pdop;                        //位置精度因子 0~500,对应实际值0~50.0
  42.         uint hdop;                        //水平精度因子 0~500,对应实际值0~50.0
  43.         uint vdop;                        //垂直精度因子 0~500,对应实际值0~50.0

  44.         int altitude;                        //海拔高度,放大了10倍,实际除以10.单位:0.1m         
  45.         uint speed;                        //地面速率,放大了1000倍,实际除以10.单位:0.001公里/小时         
  46. }nmea_msg;
  47. ////////////////////////////////////////////////////////////////////////////////////////////////////        
  48. //UBLOX NEO-6M 时钟脉冲配置结构体
  49. typedef struct  
  50. {                                                                                    
  51.         uint header;                        //cfg header,固定为0X62B5(小端模式)
  52.         uint id;                                //CFG TP ID:0X0706 (小端模式)
  53.         uint dlength;                        //数据长度
  54.         int interval;                        //时钟脉冲间隔,单位为us
  55.         int length;                        //脉冲宽度,单位为us
  56.         signed char status;                //时钟脉冲配置:1,高电平有效;0,关闭;-1,低电平有效.                          
  57.         uchar timeref;                        //参考时间:0,UTC时间;1,GPS时间;2,当地时间.
  58.         uchar flags;                        //时间脉冲设置标志
  59.         uchar reserved;                        //保留                          
  60.         signed short antdelay;                 //天线延时
  61.         signed short rfdelay;                //RF延时
  62.         signed int userdelay;                  //用户延时       
  63.         uchar cka;                                //校验CK_A                                                                   
  64.         uchar ckb;                                //校验CK_B                                                                  
  65. }_ublox_cfg_tp;
  66. //UBLOX NEO-6M 刷新速率配置结构体
  67. typedef struct  
  68. {                                                                                    
  69.         uint header;                        //cfg header,固定为0X62B5(小端模式)
  70.         uint id;                                //CFG RATE ID:0X0806 (小端模式)
  71.         uint dlength;                        //数据长度
  72.         uint measrate;                        //测量时间间隔,单位为ms,最少不能小于200ms(5Hz)
  73.         uint navrate;                        //导航速率(周期),固定为1
  74.         uint timeref;                        //参考时间:0=UTC Time;1=GPS Time;
  75.         uchar cka;                                //校验CK_A                                                                   
  76.         uchar ckb;                                //校验CK_B                                                                  
  77. }_ublox_cfg_rate;
  78.                                  
  79. int NMEA_Str2num(uchar *buf,uchar*dx);
  80. void GPS_Analysis(nmea_msg *gpsx,uchar *buf);
  81. void NMEA_GPGSV_Analysis(nmea_msg *gpsx,uchar *buf);
  82. void NMEA_GPGGA_Analysis(nmea_msg *gpsx,uchar *buf);
  83. void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uchar *buf);
  84. void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uchar *buf);
  85. void NMEA_GPRMC_Analysis(nmea_msg *gpsx,uchar *buf);
  86. void NMEA_GPVTG_Analysis(nmea_msg *gpsx,uchar *buf);
  87. void Ublox_Cfg_Tp(int interval,int length,signed char status);
  88. void Ublox_Cfg_Rate(uint measrate,uchar reftime);

  89. #endif  /* __GPS_H  */</font>
gps.c
  1. #include "../inc/gps.h"

  2. /*******************************************
  3. 函数名称:NMEA_Comma_Pos
  4. 功    能:从buf里面得到第cx个逗号所在的位置
  5. 参    数:
  6. 返回值  :0~0XFE,代表逗号所在位置的偏移
  7.           0XFF,代表不存在第cx个逗号
  8. ********************************************/
  9. uchar NMEA_Comma_Pos(uchar *buf,uchar cx)
  10. {                             
  11.         uchar *p=buf;
  12.         while(cx)
  13.         {                 
  14.                 if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF;//遇到'*'或者非法字符,则不存在第cx个逗号
  15.                 if(*buf==',')cx--;
  16.                 buf++;
  17.         }
  18.         return buf-p;         
  19. }

  20. /*******************************************
  21. 函数名称:NMEA_Pow
  22. 功    能:m^n函数
  23. 参    数:
  24. 返回值  :m^n次方.
  25. ********************************************/
  26. int NMEA_Pow(uchar m,uchar n)
  27. {
  28.         int result=1;         
  29.         while(n--)result*=m;   
  30.         return result;
  31. }

  32. /*******************************************
  33. 函数名称:NMEA_Str2num
  34. 功    能:str转换为数字,以','或者'*'结束
  35. 参    数:buf:数字存储区;dx:小数点位数,返回给调用函数
  36. 返回值  :转换后的数值
  37. ********************************************/
  38. int NMEA_Str2num(uchar *buf,uchar*dx)
  39. {
  40.         uchar *p=buf;
  41.         int ires=0,fres=0;
  42.         uchar ilen=0,flen=0,i;
  43.         uchar mask=0;
  44.         int res;
  45.         while(1) //得到整数和小数的长度
  46.         {
  47.                 if(*p=='-'){mask|=0X02;p++;}    //是负数
  48.                 if(*p==','||(*p=='*'))break;    //遇到结束了
  49.                 if(*p=='.'){mask|=0X01;p++;}    //遇到小数点了
  50.                 else if(*p>'9'||(*p<'0'))        //有非法字符
  51.                 {       
  52.                         ilen=0;
  53.                         flen=0;
  54.                         break;
  55.                 }       
  56.                 if(mask&0X01)flen++;
  57.                 else ilen++;
  58.                 p++;
  59.         }
  60.         if(mask&0X02)buf++;        //去掉负号
  61.         for(i=0;i<ilen;i++)        //得到整数部分数据
  62.         {  
  63.                 ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');
  64.         }
  65.         if(flen>5)flen=5;        //最多取5位小数
  66.         *dx=flen;                 //小数点位数
  67.         for(i=0;i<flen;i++)        //得到小数部分数据
  68.         {  
  69.                 fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0');
  70.         }
  71.         res=ires*NMEA_Pow(10,flen)+fres;
  72.         if(mask&0X02)res=-res;                  
  73.         return res;
  74. }                                                                   

  75. /*******************************************
  76. 函数名称:NMEA_GPGSV_Analysis
  77. 功    能:分析GPGSV信息
  78. 参    数:gpsx:nmea信息结构体;buf:接收到的GPS数据缓冲区首地址
  79. 返回值  :
  80. ********************************************/
  81. void NMEA_GPGSV_Analysis(nmea_msg *gpsx,uchar *buf)
  82. {
  83.         uchar *p,*p1,dx;
  84.         uchar len,i,j,slx=0;
  85.         uchar posx;            
  86.         p=buf;
  87.         p1=(uchar*)strstr((const char *)p,"$GPGSV");
  88.         len=p1[7]-'0';                                                        //得到GPGSV的条数
  89.         posx=NMEA_Comma_Pos(p1,3);                                         //得到可见卫星总数
  90.         if(posx!=0XFF)gpsx->svnum=NMEA_Str2num(p1+posx,&dx);
  91.         for(i=0;i<len;i++)
  92.         {         
  93.                 p1=(uchar*)strstr((const char *)p,"$GPGSV");  
  94.                 for(j=0;j<4;j++)
  95.                 {          
  96.                         posx=NMEA_Comma_Pos(p1,4+j*4);
  97.                         if(posx!=0XFF)gpsx->slmsg[slx].num=NMEA_Str2num(p1+posx,&dx);        //得到卫星编号
  98.                         else break;
  99.                         posx=NMEA_Comma_Pos(p1,5+j*4);
  100.                         if(posx!=0XFF)gpsx->slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx);//得到卫星仰角
  101.                         else break;
  102.                         posx=NMEA_Comma_Pos(p1,6+j*4);
  103.                         if(posx!=0XFF)gpsx->slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//得到卫星方位角
  104.                         else break;
  105.                         posx=NMEA_Comma_Pos(p1,7+j*4);
  106.                         if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx);        //得到卫星信噪比
  107.                         else break;
  108.                         slx++;          
  109.                 }   
  110.                 p=p1+1;//切换到下一个GPGSV信息
  111.         }   
  112. }

  113. /*******************************************
  114. 函数名称:NMEA_GPGGA_Analysis
  115. 功    能:分析GPGGA信息
  116. 参    数:gpsx:nmea信息结构体;buf:接收到的GPS数据缓冲区首地址
  117. 返回值  :
  118. ********************************************/
  119. void NMEA_GPGGA_Analysis(nmea_msg *gpsx,uchar *buf)
  120. {
  121.         uchar *p1,dx;                         
  122.         uchar posx;   
  123.         p1=(uchar*)strstr((const char *)buf,"$GPGGA");
  124.         posx=NMEA_Comma_Pos(p1,6);                                                                //得到GPS状态
  125.         if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);       
  126.         posx=NMEA_Comma_Pos(p1,7);                                                                //得到用于定位的卫星数
  127.         if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx);
  128.         posx=NMEA_Comma_Pos(p1,9);                                                                //得到海拔高度
  129.         if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);  
  130. }

  131. /*******************************************
  132. 函数名称:NMEA_GPGSA_Analysis
  133. 功    能:分析GPGSA信息
  134. 参    数:gpsx:nmea信息结构体;buf:接收到的GPS数据缓冲区首地址
  135. 返回值  :
  136. ********************************************/
  137. void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uchar *buf)
  138. {
  139.         uchar *p1,dx;                         
  140.         uchar posx;
  141.         uchar i;   
  142.         p1=(uchar*)strstr((const char *)buf,"$GPGSA");
  143.         posx=NMEA_Comma_Pos(p1,2);                                                                //得到定位类型
  144.         if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx);       
  145.         for(i=0;i<12;i++)                                                                                //得到定位卫星编号
  146.         {
  147.                 posx=NMEA_Comma_Pos(p1,3+i);                                         
  148.                 if(posx!=0XFF)gpsx->possl[i]=NMEA_Str2num(p1+posx,&dx);
  149.                 else break;
  150.         }                                  
  151.         posx=NMEA_Comma_Pos(p1,15);                                                                //得到PDOP位置精度因子
  152.         if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx);  
  153.         posx=NMEA_Comma_Pos(p1,16);                                                                //得到HDOP位置精度因子
  154.         if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);  
  155.         posx=NMEA_Comma_Pos(p1,17);                                                                //得到VDOP位置精度因子
  156.         if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx);  
  157. }

  158. /*******************************************
  159. 函数名称:NMEA_GPRMC_Analysis
  160. 功    能:分析GPRMC信息
  161. 参    数:gpsx:nmea信息结构体;buf:接收到的GPS数据缓冲区首地址
  162. 返回值  :
  163. ********************************************/
  164. void NMEA_GPRMC_Analysis(nmea_msg *gpsx,uchar *buf)
  165. {
  166.         uchar *p1,dx;                         
  167.         uchar posx;     
  168.         int temp;          
  169.         float rs;  
  170.         p1=(uchar*)strstr((const char *)buf,"$GPRMC");
  171.         posx=NMEA_Comma_Pos(p1,1);                                                                //得到UTC时间
  172.         if(posx!=0XFF)
  173.         {
  174.                 temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx);                 //得到UTC时间,去掉ms
  175.                 gpsx->utc.hour=temp/10000;
  176.                 gpsx->utc.min=(temp/100)%100;
  177.                 gpsx->utc.sec=temp%100;                  
  178.         }                                                    
  179.         posx=NMEA_Comma_Pos(p1,3);                                                                //得到纬度
  180.         if(posx!=0XFF)
  181.         {
  182.                 temp=NMEA_Str2num(p1+posx,&dx);                          
  183.                 gpsx->latitude=temp/NMEA_Pow(10,dx+2);        //得到°
  184.                 rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
  185.                 gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为°
  186.         }
  187.         posx=NMEA_Comma_Pos(p1,4);                                                                //南纬还是北纬
  188.         if(posx!=0XFF)gpsx->nshemi=*(p1+posx);                                         
  189.         posx=NMEA_Comma_Pos(p1,5);                                                                //得到经度
  190.         if(posx!=0XFF)
  191.         {                                                                                                  
  192.                 temp=NMEA_Str2num(p1+posx,&dx);                          
  193.                 gpsx->longitude=temp/NMEA_Pow(10,dx+2);        //得到°
  194.                 rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
  195.                 gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为°
  196.         }
  197.         posx=NMEA_Comma_Pos(p1,6);                                                                //东经还是西经
  198.         if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);                 
  199.         posx=NMEA_Comma_Pos(p1,9);                                                                //得到UTC日期
  200.         if(posx!=0XFF)
  201.         {
  202.                 temp=NMEA_Str2num(p1+posx,&dx);                                                 //得到UTC日期
  203.                 gpsx->utc.date=temp/10000;
  204.                 gpsx->utc.month=(temp/100)%100;
  205.                 gpsx->utc.year=2000+temp%100;                  
  206.         }
  207. }

  208. /*******************************************
  209. 函数名称:NMEA_GPVTG_Analysis
  210. 功    能:分析GPVTG信息
  211. 参    数:gpsx:nmea信息结构体;buf:接收到的GPS数据缓冲区首地址
  212. 返回值  :
  213. ********************************************/
  214. void NMEA_GPVTG_Analysis(nmea_msg *gpsx,uchar *buf)
  215. {
  216.         uchar *p1,dx;                         
  217.         uchar posx;   
  218.         p1=(uchar*)strstr((const char *)buf,"$GPVTG");                                                         
  219.         posx=NMEA_Comma_Pos(p1,7);                                                                //得到地面速率
  220.         if(posx!=0XFF)
  221.         {
  222.                 gpsx->speed=NMEA_Str2num(p1+posx,&dx);
  223.                 if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx);                                  //确保扩大1000倍
  224.         }
  225. }  

  226. /*******************************************
  227. 函数名称:GPS_Analysis
  228. 功    能:提取NMEA-0183信息
  229. 参    数:gpsx:nmea信息结构体;buf:接收到的GPS数据缓冲区首地址
  230. 返回值  :
  231. ********************************************/
  232. void GPS_Analysis(nmea_msg *gpsx,uchar *buf)
  233. {
  234.         NMEA_GPGSV_Analysis(gpsx,buf);        //GPGSV解析
  235.         NMEA_GPGGA_Analysis(gpsx,buf);        //GPGGA解析        
  236.         NMEA_GPGSA_Analysis(gpsx,buf);        //GPGSA解析
  237.         NMEA_GPRMC_Analysis(gpsx,buf);        //GPRMC解析
  238.         NMEA_GPVTG_Analysis(gpsx,buf);        //GPVTG解析
  239. }

  240. /*******************************************
  241. 函数名称:Ublox_CheckSum
  242. 功    能:GPS校验和计算
  243. 参    数:buf:数据缓存区首地址;len:数据长度;cka,ckb:两个校验结果.
  244. 返回值  :
  245. ********************************************/
  246. void Ublox_CheckSum(uchar *buf,uint len,uchar* cka,uchar*ckb)
  247. {
  248.         uint i;
  249.         *cka=0;*ckb=0;
  250.         for(i=0;i<len;i++)
  251.         {
  252.                 *cka=*cka+buf[i];
  253.                 *ckb=*ckb+*cka;
  254.         }
  255. }

  256. /*******************************************
  257. 函数名称:Ublox_Cfg_Tp
  258. 功    能:配置UBLOX NEO-6的时钟脉冲输出
  259. 参    数:interval:脉冲间隔
  260.           length:脉冲宽度
  261.           status:脉冲配置:1,高电平有效;0,关闭;-1,低电平有效.
  262. 返回值  :
  263. ********************************************/
  264. void Ublox_Cfg_Tp(int interval,int length,signed char status)
  265. {/*
  266.         _ublox_cfg_tp *cfg_tp=(_ublox_cfg_tp *)USART2_TX_BUF;
  267.         cfg_tp->header=0X62B5;                //cfg header
  268.         cfg_tp->id=0X0706;                        //cfg tp id
  269.         cfg_tp->dlength=20;                        //数据区长度为20个字节.
  270.         cfg_tp->interval=interval;        //脉冲间隔,us
  271.         cfg_tp->length=length;                //脉冲宽度,us
  272.         cfg_tp->status=status;                   //时钟脉冲配置
  273.         cfg_tp->timeref=0;                        //参考UTC 时间
  274.         cfg_tp->flags=0;                        //flags为0
  275.         cfg_tp->reserved=0;                         //保留位为0
  276.         cfg_tp->antdelay=820;            //天线延时为820ns
  277.         cfg_tp->rfdelay=0;                    //RF延时为0ns
  278.         cfg_tp->userdelay=0;            //用户延时为0ns
  279.         Ublox_CheckSum((uchar*)(&cfg_tp->id),sizeof(_ublox_cfg_tp)-4,&cfg_tp->cka,&cfg_tp->ckb);
  280.         while(DMA1_Channel7->CNDTR!=0);        //等待通道7传输完成   
  281.         UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_tp));        //通过dma发送出去
  282.   */
  283. }

  284. /*******************************************
  285. 函数名称:Ublox_Cfg_Rate
  286. 功    能:配置UBLOX NEO-6的更新速率            
  287. 参    数:measrate:测量时间间隔,单位为ms,最少不能小于200ms(5Hz)
  288.           reftime:参考时间,0=UTC Time;1=GPS Time(一般设置为1)
  289. 返回值  :
  290. ********************************************/
  291. void Ublox_Cfg_Rate(uint measrate,uchar reftime)
  292. {/*
  293.         _ublox_cfg_rate *cfg_rate=(_ublox_cfg_rate *)USART2_TX_BUF;
  294.         if(measrate<200)return;                //小于200ms,直接退出
  295.         cfg_rate->header=0X62B5;        //cfg header
  296.         cfg_rate->id=0X0806;                 //cfg rate id
  297.         cfg_rate->dlength=6;                 //数据区长度为6个字节.
  298.         cfg_rate->measrate=measrate;//脉冲间隔,us
  299.         cfg_rate->navrate=1;                //导航速率(周期),固定为1
  300.         cfg_rate->timeref=reftime;         //参考时间为GPS时间
  301.         Ublox_CheckSum((uchar*)(&cfg_rate->id),sizeof(_ublox_cfg_rate)-4,&cfg_rate->cka,&cfg_rate->ckb);
  302.         while(DMA1_Channel7->CNDTR!=0);        //等待通道7传输完成   
  303.         UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_rate));//通过dma发送出去
  304.   */
  305. }


以上为GPS相关代码,下面为MSP430相关代码
uart.h
  1. #ifndef _UART_H_
  2. #define _UART_H_

  3. #include <msp430f149.h>

  4. void UartInit(void);
  5. void SendData(uchar dat);
  6. void SendByte(uchar *pData);
  7. void SendString(char *s);

  8. #endif        /* __UART_H */

uart.c
  1. #include "../inc/uart.h"

  2. void UartInit(void)
  3. {
  4.   //串口1配置
  5.   P3DIR |= BIT4;            //p3.4设为输出
  6.   P3SEL |= BIT4 + BIT5;     //P3.4,5设置为TXD/RXD       
  7.   ME1 |= UTXE0 + URXE0;     //enable tx and rx
  8.   UCTL0 = 0x00;             //reset as 0
  9.   UCTL0 |= CHAR;            //8 bit transfer       
  10.   UTCTL0 = 0x00;            //reset as 0
  11.   UTCTL0 |= SSEL0;          //select aclk(8M)
  12.   UBR00 = 0x03;
  13.   UBR10 = 0x00;             //波特率为  9600(ACLK为8MHz)
  14.   UMCTL0 = 0x4A;
  15.   UCTL0 &= ~SWRST;          // reset UART       
  16.   IE1 |= URXIE0;            // enable rx inerrupt
  17.   
  18.   //串口2配置
  19.   P3DIR |= BIT6;            //p3.6设为输出
  20.   P3SEL |= BIT6 + BIT7;     //P3.6,7设置为TXD/RXD       
  21.   ME2 |= URXE1 + UTXE1;     //enable tx and rx
  22.   UCTL1 = 0x00;             //reset as 0
  23.   UCTL1 |= CHAR;            //8 bit transfer       
  24.   UTCTL1 = 0x00;            //reset as 0
  25.   UTCTL1 |= SSEL0;          //select mclk
  26.   UBR01 = 0x03;
  27.   UBR11 = 0x00;             //波特率为  9600(ACLK为8MHz)
  28.   UMCTL1 = 0x4A;
  29.   UCTL1 &= ~SWRST;          // reset UART       
  30.   IE2 |= URXIE1;            // enable rx inerrupt
  31. }

  32. void SendData(unsigned char dat)
  33. {
  34.   TXBUF0 = dat;
  35.   while(!(IFG1 & UTXIFG0));
  36.   //IFG1 &= ~(UTXIFG0);
  37. }

  38. void SendString(char *s)
  39. {
  40.   while(*s){
  41.     SendData(*s++);
  42.   }
  43. }

  44. void SendByte(uchar *pData)
  45. {
  46.   uchar i;
  47.   for(i = 0; i < 8; i++){
  48.     SendData(pData[i]);
  49.   }
  50. }

该串口操作为配置串口1和串口2波特率都为9600(之前看了GPS模块的应用手册,发现默认的波特率为38400

,但我将430的波特率设为38400发现接收到的数据为乱码,于是干脆直接将GPS的波特率设为9600,我直接将模块上的R5电阻取了,终于接收到正常的数据.)
main.c
  1. #include <msp430f149.h>
  2. #include "inc/lcd_fyd12864.h"
  3. #include "inc/uart.h"
  4. #include "inc/gps.h"

  5. uchar Welcom1[] = "欢迎来到嵌入式";
  6. uchar Welcom2[] = "*************";
  7. uchar Welcom3[] = "版主:******";
  8. uchar Welcom4[] = "DIY 实验室";

  9. uchar latitude[] = "Lat: ";
  10. uchar longitude[] = "Long: ";
  11. uchar elevation[] = "Ele: ";
  12. uchar currTime[]  = "Time: ";

  13. uchar RxBuf[300], TxBuf[300];
  14. uchar RxLen = 0;
  15. uchar RxTempLen = 0;
  16. uchar rev_flag = 0;
  17. char dtbuf[50];
  18. nmea_msg gpsx;

  19. void main()
  20. {
  21.   volatile uint i;
  22.   WDTCTL = WDTPW + WDTHOLD;                                        //关闭看门狗

  23.   BCSCTL1 &= ~XT2OFF;                       // XT2= HF XTAL
  24.   do
  25.   {
  26.   IFG1 &= ~OFIFG;                           // Clear OSCFault flag
  27.   for (i = 0xFF; i > 0; i--);               // Time for flag to set
  28.   }
  29.   while ((IFG1 & OFIFG));                   // OSCFault flag still set?
  30.   //MCLK=8M,SCLK=1M
  31.   BCSCTL2 |= SELM_2 + SELS + DIVS_3;        // MCLK= XT2 (safe)
  32.   
  33.   UartInit();
  34.   Delay_ms(500);

  35.   LCDReset();
  36.   DisplayString(1, 0, Welcom1);
  37.   DisplayString(1, 1, Welcom2);
  38.   DisplayString(1, 2, Welcom3);
  39.   DisplayString(1, 3, Welcom4);
  40.   Delay_ms(2000);
  41.   LCDClear();
  42.   Delay_ms(1000);
  43. /*
  44.   DisplayString(0, 0, latitude);
  45.   DisplayString(0, 1, longitude);
  46.   DisplayString(0, 2, elevation);
  47.   DisplayString(0, 3, currTime);
  48. */  
  49.   SendString("**************\n");
  50.   _EINT();
  51.   while(1){
  52.      //SendString("UART0 test!\n");
  53.          if(rev_flag == 1){
  54.                 int i,len = 0;
  55.                 len = RxLen;
  56.                 for(i = 0; i < len; i++)
  57.                         TxBuf[i] = RxBuf[i];
  58.                 RxLen = 0;
  59.                 TxBuf[i] = 0;
  60.                 GPS_Analysis(&gpsx,TxBuf);
  61.                 Show_GPS_Info(gpsx);
  62.                 SendString(TxBuf);
  63.          }
  64.      //Delay_ms(1000);
  65.   }
  66. }

  67. void Show_GPS_Info(nmea_msg gpsx)
  68. {
  69.   float tp;
  70.   //得到经度字符串
  71.   tp=gpsx.longitude;          
  72.   sprintf((char *)dtbuf,"Long:%.5f %1c",tp/=100000,gpsx.ewhemi);
  73.   DisplayString(0, 0, dtbuf);
  74.   //得到纬度字符串
  75.   tp=gpsx.latitude;          
  76.   sprintf((char *)dtbuf,"Lat:%.5f %1c",tp/=100000,gpsx.nshemi);
  77.   DisplayString(0, 1, dtbuf);
  78.   //得到高度字符串
  79.   tp=gpsx.altitude;          
  80.   sprintf((char *)dtbuf,"Alt:%.1fm",tp/=10);
  81.   DisplayString(0, 2, dtbuf);
  82.   //显示UTC时间
  83.   sprintf((char *)dtbuf,"UTC:%02d:%02d:%02d",gpsx.utc.hour,gpsx.utc.min,gpsx.utc.sec);
  84.   DisplayString(0, 3, dtbuf);
  85. }

  86. #pragma vector = UART0RX_VECTOR
  87. __interrupt void UART0RxISR(void)
  88. {
  89.   //接收来自串口的数据
  90.   while(!(IFG1 & UTXIFG0));
  91.   RxBuf[RxTempLen++] = RXBUF0;
  92.   while(RxBuf[RxTempLen-1] == '\n'){
  93.         RxLen = RxTempLen;
  94.         RxTempLen = 0;
  95.         rev_flag = 1;
  96.   }
  97. }

  98. #pragma vector = UART1RX_VECTOR
  99. __interrupt void UART1RxISR(void)
  100. {
  101.   //接收来自串口的数据
  102.   while(!(IFG2 & UTXIFG1));
  103.   P2OUT = RXBUF1;
  104. }

其中,有关LCD显示部分在其他博文中会详细说到.
将程序烧到430后,上电,打开串口调试工具,发送文本如下:
$GPGGA,023543.00,2308.28715,N,11322.09875,E,1,06,1.49,41.6,M,-5.3,M,,*7D
就会收到发回来的数据跟发送的一样,同时LCD上显示海拔为41.6m.
说明能对数据接受并进行正确处理了。

后面要做的便是将串口0的接收中断代码复制到串口1接收中断代码即可。
同样上电,这时LCD可显示信息,但显示的数据都为0,说明GPS还没有定位成功。等2~3分钟左右,GPS模块上的指示灯开始闪烁时,这时从LCD上可看到当前的经度、纬度、高度、UTC时间,同时用ScuetCRT连接,可看到430发回来接受到的原始数据。
下图为实验的结果,时间显示稍微有点问题,因为没有转换还是其他。不过忙了几天终于将GPS弄好了,下一步将编写linux驱动。。。下面晒一下成果^-^.

补充:
之前忙于工作,现在回头看看,发现对收到的数据进行分析显示后结果不对,很有可能是数据溢出导致,通过串口1发送到PC的数据可以看到,收到GPS模块的数据是正确的。唯一可能的是在数据进行分析时出错。果然,追踪到gps.c中可以看到,对数据处理的数据超大,而msp430的int只为16位,最大值为65536,所以在对数据进行装载时肯定会溢出。这也是今天上班偶尔看看才发现的。回去后将所用的int类型替换为long型,应该就正确了,期待回去后验证。。。。

原贴链接:https://www.cnblogs.com/lixiaoming90/p/3438015.html

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| nbnhnjnm 发表于 2019-2-27 18:48 | 显示全部楼层
昨天回去修改一下代码,将以前的uint类型替换为ulong,烧写后结果显示正确。同时在以前的基础上修改显示部分,按按键后显示另外的信息。

修改后的main.cpp如下:
main.c
  1. #include <msp430f149.h>
  2. #include "inc/lcd_fyd12864.h"
  3. #include "inc/uart.h"
  4. #include "inc/gps.h"

  5. uchar Welcom1[] = "欢迎来到嵌入式";
  6. uchar Welcom2[] = "************";
  7. uchar Welcom3[] = "版主:*******";
  8. uchar Welcom4[] = "DIY 实验室";

  9. uchar latitude[] = "Lat: ";
  10. uchar longitude[] = "Long: ";
  11. uchar elevation[] = "Ele: ";
  12. uchar currTime[]  = "Time: ";
  13. const uchar *mode[4] = {"Fail", "Fail", "2D", "3D"};

  14. uchar RxBuf[300], TxBuf[300],RxData[9];
  15. uchar RxLen = 0;
  16. uchar RxTempLen = 0;
  17. uchar rev_flag = 0;
  18. char dtbuf[50];
  19. nmea_msg gpsx;
  20. uchar swt = 1;

  21. void Show_GPS_Info1(nmea_msg gpsx)
  22. {
  23.   float tp;
  24.   //得到经度字符串
  25.   tp=gpsx.longitude;          
  26.   sprintf((char *)dtbuf,"Lon: %.5f %1c",tp/=100000,gpsx.ewhemi);
  27.   DisplayString(0, 0, dtbuf);
  28.   //得到纬度字符串
  29.   tp=gpsx.latitude;          
  30.   sprintf((char *)dtbuf,"Lat: %.5f %1c",tp/=100000,gpsx.nshemi);
  31.   DisplayString(0, 1, dtbuf);
  32.   //得到高度字符串
  33.   tp=gpsx.altitude;          
  34.   sprintf((char *)dtbuf,"Alt: %.1fm",tp/=10);
  35.   DisplayString(0, 2, dtbuf);
  36.   //得到速度字符串
  37.   tp=gpsx.speed;          
  38.   sprintf((char *)dtbuf,"Speed:%.3fkm/h",tp/=1000);       
  39.   DisplayString(0, 3, dtbuf);
  40. }

  41. void Show_GPS_Info2(nmea_msg gpsx)
  42. {
  43.   //定位状态
  44.   if(gpsx.fixmode<=3){       
  45.     sprintf((char *)dtbuf,"Fix Mode: %s",mode[gpsx.fixmode]);       
  46.     DisplayString(0, 0, dtbuf);       
  47.   }
  48.   //用于定位的卫星数
  49.   sprintf((char *)dtbuf,"Val sat: %02d",gpsx.posslnum);
  50.   DisplayString(0, 1, dtbuf);       
  51.   //可见卫星数
  52.   sprintf((char *)dtbuf,"Vis sat: %02d",gpsx.svnum%100);       
  53.   DisplayString(0, 2, dtbuf);       
  54. }

  55. void Show_GPS_Info3(nmea_msg gpsx)
  56. {
  57.   //显示UTC日期
  58.   sprintf((char *)dtbuf,"Date:%04d/%02d/%02d",gpsx.utc.year,gpsx.utc.month,gpsx.utc.date);
  59.   DisplayString(0, 0, dtbuf);
  60.   //显示UTC时间
  61.   sprintf((char *)dtbuf,"Time:%02d:%02d:%02d",gpsx.utc.hour,gpsx.utc.min,gpsx.utc.sec);
  62.   DisplayString(0, 1, dtbuf);
  63. }


  64. void main()
  65. {
  66.   volatile uint i;
  67.   WDTCTL = WDTPW + WDTHOLD;            //关闭看门狗

  68.   BCSCTL1 &= ~XT2OFF;                       // XT2= HF XTAL
  69.   do
  70.   {
  71.   IFG1 &= ~OFIFG;                           // Clear OSCFault flag
  72.   for (i = 0xFF; i > 0; i--);               // Time for flag to set
  73.   }
  74.   while ((IFG1 & OFIFG));                   // OSCFault flag still set?
  75.   //MCLK=8M,SCLK=1M
  76.   BCSCTL2 |= SELM_2 + SELS + DIVS_3;        // MCLK= XT2 (safe)
  77.   Delay_ms(500);
  78.   UartInit();
  79.   Delay_ms(500);
  80.   
  81.   P3DIR &= (~BIT2 + ~BIT3);
  82.   
  83.   LCDReset();
  84.   DisplayString(1, 0, Welcom1);
  85.   DisplayString(1, 1, Welcom2);
  86.   DisplayString(1, 2, Welcom3);
  87.   DisplayString(1, 3, Welcom4);
  88.   Delay_ms(2000);
  89.   LCDClear();
  90.   Delay_ms(1000);
  91. /*
  92.   DisplayString(0, 0, latitude);
  93.   DisplayString(0, 1, longitude);
  94.   DisplayString(0, 2, elevation);
  95.   DisplayString(0, 3, currTime);
  96. */  
  97.   SendString("Lixiaoming\n");
  98.   _EINT();
  99.   while(1){
  100.      //SendString("UART0 test!\n");
  101.     if(!(P3IN & BIT2)){
  102.       swt++;
  103.       if(swt == 4)
  104.         swt = 1;
  105.     }
  106.     if(rev_flag == 1){
  107.       int i,len = 0;
  108.       len = RxLen;
  109.       for(i = 0; i < len; i++)
  110.         TxBuf[i] = RxBuf[i];
  111.       RxLen = 0;
  112.       TxBuf[i] = 0;
  113.       GPS_Analysis(&gpsx,TxBuf);
  114.       switch(swt){
  115.       case 1: LCDClear(); Show_GPS_Info1(gpsx); break;
  116.       case 2: LCDClear(); Show_GPS_Info2(gpsx); break;
  117.       default: LCDClear(); Show_GPS_Info3(gpsx); break;
  118.       }
  119.       SendString(TxBuf);
  120.       rev_flag = 0;
  121.     }
  122.      //Delay_ms(1000);
  123.   }
  124. }

  125. #pragma vector = UART0RX_VECTOR
  126. __interrupt void UART0RxISR(void)
  127. {
  128.   //接收来自串口的数据
  129.   while(!(IFG1 & UTXIFG0));
  130.   RxBuf[RxTempLen++] = RXBUF0;
  131.   while(RxBuf[RxTempLen-1] == '\n' && RxBuf[RxTempLen-2] == '\r' ){
  132.         RxLen = RxTempLen;
  133.         RxTempLen = 0;
  134.         rev_flag = 1;
  135.   }
  136. }

  137. #pragma vector = UART1RX_VECTOR
  138. __interrupt void UART1RxISR(void)
  139. {
  140.   //接收来自串口的数据
  141.   while(!(IFG2 & UTXIFG1));
  142.   RxBuf[RxTempLen++] = RXBUF1;
  143.   while(RxBuf[RxTempLen-1] == '\n'){
  144.         RxLen = RxTempLen;
  145.         RxTempLen = 0;
  146.         rev_flag = 1;
  147.   }
  148. }

 楼主| nbnhnjnm 发表于 2019-2-27 18:49 | 显示全部楼层
显示的结果如下:(因为是在市内的窗口,信号不是很好)
PC串口接收到的数据如下:
  1. $GPRMC,134856.00,A,2232.50576,N,11354.64802,E,0.084,,251113,,,A*7E
  2. $GPGSV,3,2,09,22,75,191,27,25,58,074,22,29,08,122,16,31,48,276,19*76
  3. gpsx->utc temp: 134857
  4. gpsx->latitude temp: 223250578
  5. gpsx->longitude temp: 1135464798
  6. gpsx->utc.date temp: 251113
  7. $GPRMC,134857.00,A,2232.50578,N,11354.64798,E,0.173,,251113,,,A*74
  8. $GPGSV,3,2,09,22,75,191,27,25,58,074,23,29,08,122,15,31,48,276,20*7E
  9. gpsx->utc temp: 134858
  10. gpsx->latitude temp: 223250575
  11. gpsx->longitude temp: 1135464785
  12. gpsx->utc.date temp: 251113
  13. $GPRMC,134858.00,A,2232.50575,N,11354.64785,E,0.140,,251113,,,A*7A
  14. $GPGSV,3,2,09,22,75,191,27,25,58,074,23,29,08,122,15,31,48,276,19*74
  15. gpsx->utc temp: 134859
  16. gpsx->latitude temp: 223250575
  17. gpsx->longitude temp: 1135464782
  18. gpsx->utc.date temp: 251113
  19. $GPRMC,134859.00,A,2232.50575,N,11354.64782,E,0.130,,251113,,,A*7B
  20. $GPGSV,3,2,09,22,75,191,27,25,58,074,23,29,08,122,15,31,48,276,20*7E
  21. gpsx->utc temp: 134900
  22. gpsx->latitude temp: 223250570
  23. gpsx->longitude temp: 1135464784
  24. gpsx->utc.date temp: 251113
  25. $GPRMC,134900.00,A,2232.50570,N,11354.64784,E,0.112,,251113,,,A*75



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
zhangmangui 发表于 2019-2-27 22:39 | 显示全部楼层
非常全面  非常完整的帖子分享   
现在有一种模块集GPS和北斗一体
 楼主| nbnhnjnm 发表于 2019-2-28 19:06 | 显示全部楼层
zhangmangui 发表于 2019-2-27 22:39
非常全面  非常完整的帖子分享   
现在有一种模块集GPS和北斗一体

北斗已经做得很好了,基本上和GPS可以说是不相上下了。
 楼主| nbnhnjnm 发表于 2019-2-28 19:07 | 显示全部楼层
zhangmangui 发表于 2019-2-27 22:39
非常全面  非常完整的帖子分享   
现在有一种模块集GPS和北斗一体

只是应用方面的资料和经验还不如GPS多
lzbf 发表于 2019-3-3 21:29 | 显示全部楼层
可以做个GPS的授时系统了。     
houjiakai 发表于 2019-3-3 21:29 | 显示全部楼层
能够查看收到几颗GPS卫星信号吗
youtome 发表于 2019-3-3 21:29 | 显示全部楼层
这个的精度能够到多少呢   
cemaj 发表于 2019-3-3 21:30 | 显示全部楼层
可以做个远程定位系统。      
10299823 发表于 2019-3-3 21:30 | 显示全部楼层
做上位机的显示了吗?         
jimmhu 发表于 2019-3-3 21:31 | 显示全部楼层
nbnhnjnm 发表于 2019-2-28 19:06
北斗已经做得很好了,基本上和GPS可以说是不相上下了。

北斗的芯片也做了吗?      
lihuami 发表于 2019-3-3 21:31 | 显示全部楼层
msp430低功耗非常适合做手持设备  
xiaoyaozt 发表于 2019-3-3 21:32 | 显示全部楼层
楼主这个做的非常棒。               
uptown 发表于 2019-3-3 21:32 | 显示全部楼层
以后开发四轴飞行器的时候用得到。     
cehuafan 发表于 2019-3-3 21:33 | 显示全部楼层
好像见过他们有直接解析的代码         
xiaoyaozt 发表于 2019-3-3 21:33 | 显示全部楼层
ATK-NEO-6M GPS以前看别人使用过。   
lzbf 发表于 2019-3-3 21:33 | 显示全部楼层
高端了,这个产品设计了。   
lihuami 发表于 2019-3-3 21:33 | 显示全部楼层
楼主可以使用云设备共享数据了。  
houjiakai 发表于 2019-3-3 21:33 | 显示全部楼层
楼主做的非常厉害了。      
您需要登录后才可以回帖 登录 | 注册

本版积分规则

8

主题

51

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部