MSP430與ATK-NEO-6M GPS模塊

MSP430與ATK-NEO-6M GPS模塊

本文來源於“21ic TI微控制器&處理器論壇”,原貼見底部“閱讀原文”

近短時間在網上買了一個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


<font size="2">#ifndef __GPS_H
#define __GPS_H

#include <math.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>

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

//GPS NMEA-0183協議重要參數結構體定義 
//衛星信息
typedef struct  
{                                                                                    
        uchar num;                //衛星編號
        uchar eledeg;        //衛星仰角
        uint azideg;        //衛星方位角
        uchar sn;                //信噪比                   
}nmea_slmsg;  
//UTC時間信息
typedef struct  
{                                                                                    
        uint year;        //年份
        uchar month;        //月份
        uchar date;        //日期
        uchar hour;         //小時
        uchar min;         //分鐘
        uchar sec;         //秒鐘
}nmea_utc_time;              
//NMEA 0183 協議解析後數據存放結構體
typedef struct  
{                                                                                    
        uchar svnum;                        //可見衛星數
        nmea_slmsg slmsg[12];                //最多12顆衛星
        nmea_utc_time utc;                //UTC時間
        int latitude;                        //緯度 分擴大100000倍,實際要除以100000
        uchar nshemi;                        //北緯/南緯,N:北緯;S:南緯                                  
        int longitude;                        //經度 分擴大100000倍,實際要除以100000
        uchar ewhemi;                        //東經/西經,E:東經;W:西經
        uchar gpssta;                        //GPS狀態:0,未定位;1,非差分定位;2,差分定位;6,正在估算.                                  
        uchar posslnum;                        //用於定位的衛星數,0~12.
        uchar possl[12];                        //用於定位的衛星編號
        uchar fixmode;                        //定位類型:1,沒有定位;2,2D定位;3,3D定位
        uint pdop;                        //位置精度因子 0~500,對應實際值0~50.0
        uint hdop;                        //水平精度因子 0~500,對應實際值0~50.0
        uint vdop;                        //垂直精度因子 0~500,對應實際值0~50.0

        int altitude;                        //海拔高度,放大了10倍,實際除以10.單位:0.1m         
        uint speed;                        //地面速率,放大了1000倍,實際除以10.單位:0.001公里/小時         
}nmea_msg; 
////////////////////////////////////////////////////////////////////////////////////////////////////         
//UBLOX NEO-6M 時鐘脈衝配置結構體
typedef struct  
{                                                                                    
        uint header;                        //cfg header,固定爲0X62B5(小端模式)
        uint id;                                //CFG TP ID:0X0706 (小端模式)
        uint dlength;                        //數據長度
        int interval;                        //時鐘脈衝間隔,單位爲us
        int length;                        //脈衝寬度,單位爲us
        signed char status;                //時鐘脈衝配置:1,高電平有效;0,關閉;-1,低電平有效.                          
        uchar timeref;                        //參考時間:0,UTC時間;1,GPS時間;2,當地時間.
        uchar flags;                        //時間脈衝設置標誌
        uchar reserved;                        //保留                          
        signed short antdelay;                 //天線延時
        signed short rfdelay;                //RF延時
        signed int userdelay;                  //用戶延時        
        uchar cka;                                //校驗CK_A                                                                   
        uchar ckb;                                //校驗CK_B                                                                  
}_ublox_cfg_tp; 
//UBLOX NEO-6M 刷新速率配置結構體
typedef struct  
{                                                                                    
        uint header;                        //cfg header,固定爲0X62B5(小端模式)
        uint id;                                //CFG RATE ID:0X0806 (小端模式)
        uint dlength;                        //數據長度
        uint measrate;                        //測量時間間隔,單位爲ms,最少不能小於200ms(5Hz)
        uint navrate;                        //導航速率(週期),固定爲1
        uint timeref;                        //參考時間:0=UTC Time;1=GPS Time;
        uchar cka;                                //校驗CK_A                                                                   
        uchar ckb;                                //校驗CK_B                                                                  
}_ublox_cfg_rate; 

int NMEA_Str2num(uchar *buf,uchar*dx);
void GPS_Analysis(nmea_msg *gpsx,uchar *buf);
void NMEA_GPGSV_Analysis(nmea_msg *gpsx,uchar *buf);
void NMEA_GPGGA_Analysis(nmea_msg *gpsx,uchar *buf);
void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uchar *buf);
void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uchar *buf);
void NMEA_GPRMC_Analysis(nmea_msg *gpsx,uchar *buf);
void NMEA_GPVTG_Analysis(nmea_msg *gpsx,uchar *buf);
void Ublox_Cfg_Tp(int interval,int length,signed char status);
void Ublox_Cfg_Rate(uint measrate,uchar reftime);

#endif  /* __GPS_H  */</font>

gps.c


#include "../inc/gps.h"

/*******************************************
函數名稱:NMEA_Comma_Pos
功    能:從buf裏面得到第cx個逗號所在的位置
參    數:
返回值  :0~0XFE,代表逗號所在位置的偏移
          0XFF,代表不存在第cx個逗號
********************************************/
uchar NMEA_Comma_Pos(uchar *buf,uchar cx)
{                             
        uchar *p=buf;
        while(cx)
        {                 
                if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF;//遇到'*'或者非法字符,則不存在第cx個逗號
                if(*buf==',')cx--;
                buf++;
        }
        return buf-p;         
}

/*******************************************
函數名稱:NMEA_Pow
功    能:m^n函數
參    數:
返回值  :m^n次方.
********************************************/
int NMEA_Pow(uchar m,uchar n)
{
        int result=1;         
        while(n--)result*=m;    
        return result;
}

/*******************************************
函數名稱:NMEA_Str2num
功    能:str轉換爲數字,以','或者'*'結束
參    數:buf:數字存儲區;dx:小數點位數,返回給調用函數
返回值  :轉換後的數值
********************************************/
int NMEA_Str2num(uchar *buf,uchar*dx)
{
        uchar *p=buf;
        int ires=0,fres=0;
        uchar ilen=0,flen=0,i;
        uchar mask=0;
        int res;
        while(1) //得到整數和小數的長度
        {
                if(*p=='-'){mask|=0X02;p++;}    //是負數
                if(*p==','||(*p=='*'))break;    //遇到結束了
                if(*p=='.'){mask|=0X01;p++;}    //遇到小數點了
                else if(*p>'9'||(*p<'0'))        //有非法字符
                {        
                        ilen=0;
                        flen=0;
                        break;
                }        
                if(mask&0X01)flen++;
                else ilen++;
                p++;
        }
        if(mask&0X02)buf++;        //去掉負號
        for(i=0;i<ilen;i++)        //得到整數部分數據
        {  
                ires+=NMEA_Pow(10,ilen-1-i)*(buf[i]-'0');
        }
        if(flen>5)flen=5;        //最多取5位小數
        *dx=flen;                 //小數點位數
        for(i=0;i<flen;i++)        //得到小數部分數據
        {  
                fres+=NMEA_Pow(10,flen-1-i)*(buf[ilen+1+i]-'0');
        } 
        res=ires*NMEA_Pow(10,flen)+fres;
        if(mask&0X02)res=-res;                   
        return res;
}

/*******************************************
函數名稱:NMEA_GPGSV_Analysis
功    能:分析GPGSV信息
參    數:gpsx:nmea信息結構體;buf:接收到的GPS數據緩衝區首地址
返回值  :
********************************************/
void NMEA_GPGSV_Analysis(nmea_msg *gpsx,uchar *buf)
{
        uchar *p,*p1,dx;
        uchar len,i,j,slx=0;
        uchar posx;            
        p=buf;
        p1=(uchar*)strstr((const char *)p,"$GPGSV");
        len=p1[7]-'0';                                                        //得到GPGSV的條數
        posx=NMEA_Comma_Pos(p1,3);                                         //得到可見衛星總數
        if(posx!=0XFF)gpsx->svnum=NMEA_Str2num(p1+posx,&dx);
        for(i=0;i<len;i++)
        {         
                p1=(uchar*)strstr((const char *)p,"$GPGSV");  
                for(j=0;j<4;j++)
                {          
                        posx=NMEA_Comma_Pos(p1,4+j*4);
                        if(posx!=0XFF)gpsx->slmsg[slx].num=NMEA_Str2num(p1+posx,&dx);        //得到衛星編號
                        else break; 
                        posx=NMEA_Comma_Pos(p1,5+j*4);
                        if(posx!=0XFF)gpsx->slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx);//得到衛星仰角 
                        else break;
                        posx=NMEA_Comma_Pos(p1,6+j*4);
                        if(posx!=0XFF)gpsx->slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx);//得到衛星方位角
                        else break; 
                        posx=NMEA_Comma_Pos(p1,7+j*4);
                        if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx);        //得到衛星信噪比
                        else break;
                        slx++;           
                }   
                p=p1+1;//切換到下一個GPGSV信息
        }   
}

/*******************************************
函數名稱:NMEA_GPGGA_Analysis
功    能:分析GPGGA信息
參    數:gpsx:nmea信息結構體;buf:接收到的GPS數據緩衝區首地址
返回值  :
********************************************/
void NMEA_GPGGA_Analysis(nmea_msg *gpsx,uchar *buf)
{
        uchar *p1,dx;                         
        uchar posx;    
        p1=(uchar*)strstr((const char *)buf,"$GPGGA");
        posx=NMEA_Comma_Pos(p1,6);                                                                //得到GPS狀態
        if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);        
        posx=NMEA_Comma_Pos(p1,7);                                                                //得到用於定位的衛星數
        if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx); 
        posx=NMEA_Comma_Pos(p1,9);                                                                //得到海拔高度
        if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);  
}

/*******************************************
函數名稱:NMEA_GPGSA_Analysis
功    能:分析GPGSA信息
參    數:gpsx:nmea信息結構體;buf:接收到的GPS數據緩衝區首地址
返回值  :
********************************************/
void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uchar *buf)
{
        uchar *p1,dx;                         
        uchar posx; 
        uchar i;   
        p1=(uchar*)strstr((const char *)buf,"$GPGSA");
        posx=NMEA_Comma_Pos(p1,2);                                                                //得到定位類型
        if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx);        
        for(i=0;i<12;i++)                                                                                //得到定位衛星編號
        {
                posx=NMEA_Comma_Pos(p1,3+i);                                         
                if(posx!=0XFF)gpsx->possl[i]=NMEA_Str2num(p1+posx,&dx);
                else break; 
        }                                  
        posx=NMEA_Comma_Pos(p1,15);                                                                //得到PDOP位置精度因子
        if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx);  
        posx=NMEA_Comma_Pos(p1,16);                                                                //得到HDOP位置精度因子
        if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);  
        posx=NMEA_Comma_Pos(p1,17);                                                                //得到VDOP位置精度因子
        if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx);  
}

/*******************************************
函數名稱:NMEA_GPRMC_Analysis
功    能:分析GPRMC信息
參    數:gpsx:nmea信息結構體;buf:接收到的GPS數據緩衝區首地址
返回值  :
********************************************/
void NMEA_GPRMC_Analysis(nmea_msg *gpsx,uchar *buf)
{
        uchar *p1,dx;                         
        uchar posx;     
        int temp;           
        float rs;  
        p1=(uchar*)strstr((const char *)buf,"$GPRMC");
        posx=NMEA_Comma_Pos(p1,1);                                                                //得到UTC時間
        if(posx!=0XFF)
        {
                temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx);                 //得到UTC時間,去掉ms
                gpsx->utc.hour=temp/10000;
                gpsx->utc.min=(temp/100)%100;
                gpsx->utc.sec=temp%100;                  
        }                                                    
        posx=NMEA_Comma_Pos(p1,3);                                                                //得到緯度
        if(posx!=0XFF)
        {
                temp=NMEA_Str2num(p1+posx,&dx);                          
                gpsx->latitude=temp/NMEA_Pow(10,dx+2);        //得到°
                rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
                gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//轉換爲° 
        }
        posx=NMEA_Comma_Pos(p1,4);                                                                //南緯還是北緯 
        if(posx!=0XFF)gpsx->nshemi=*(p1+posx);                                         
        posx=NMEA_Comma_Pos(p1,5);                                                                //得到經度
        if(posx!=0XFF)
        {                                                                                                  
                temp=NMEA_Str2num(p1+posx,&dx);                          
                gpsx->longitude=temp/NMEA_Pow(10,dx+2);        //得到°
                rs=temp%NMEA_Pow(10,dx+2);                                //得到'                 
                gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//轉換爲° 
        }
        posx=NMEA_Comma_Pos(p1,6);                                                                //東經還是西經
        if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);                 
        posx=NMEA_Comma_Pos(p1,9);                                                                //得到UTC日期
        if(posx!=0XFF)
        {
                temp=NMEA_Str2num(p1+posx,&dx);                                                 //得到UTC日期
                gpsx->utc.date=temp/10000;
                gpsx->utc.month=(temp/100)%100;
                gpsx->utc.year=2000+temp%100;                  
        } 
}

/*******************************************
函數名稱:NMEA_GPVTG_Analysis
功    能:分析GPVTG信息
參    數:gpsx:nmea信息結構體;buf:接收到的GPS數據緩衝區首地址
返回值  :
********************************************/
void NMEA_GPVTG_Analysis(nmea_msg *gpsx,uchar *buf)
{
        uchar *p1,dx;                         
        uchar posx;    
        p1=(uchar*)strstr((const char *)buf,"$GPVTG");                                                         
        posx=NMEA_Comma_Pos(p1,7);                                                                //得到地面速率
        if(posx!=0XFF)
        {
                gpsx->speed=NMEA_Str2num(p1+posx,&dx);
                if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx);                                  //確保擴大1000倍
        }
}

/*******************************************
函數名稱:GPS_Analysis
功    能:提取NMEA-0183信息
參    數:gpsx:nmea信息結構體;buf:接收到的GPS數據緩衝區首地址
返回值  :
********************************************/
void GPS_Analysis(nmea_msg *gpsx,uchar *buf)
{
        NMEA_GPGSV_Analysis(gpsx,buf);        //GPGSV解析
        NMEA_GPGGA_Analysis(gpsx,buf);        //GPGGA解析         
        NMEA_GPGSA_Analysis(gpsx,buf);        //GPGSA解析
        NMEA_GPRMC_Analysis(gpsx,buf);        //GPRMC解析
        NMEA_GPVTG_Analysis(gpsx,buf);        //GPVTG解析
}

/*******************************************
函數名稱:Ublox_CheckSum
功    能:GPS校驗和計算
參    數:buf:數據緩存區首地址;len:數據長度;cka,ckb:兩個校驗結果.
返回值  :
********************************************/
void Ublox_CheckSum(uchar *buf,uint len,uchar* cka,uchar*ckb)
{
        uint i;
        *cka=0;*ckb=0;
        for(i=0;i<len;i++)
        {
                *cka=*cka+buf[i];
                *ckb=*ckb+*cka;
        }
}

/*******************************************
函數名稱:Ublox_Cfg_Tp
功    能:配置UBLOX NEO-6的時鐘脈衝輸出
參    數:interval:脈衝間隔
          length:脈衝寬度
          status:脈衝配置:1,高電平有效;0,關閉;-1,低電平有效.
返回值  :
********************************************/
void Ublox_Cfg_Tp(int interval,int length,signed char status)
{/*
        _ublox_cfg_tp *cfg_tp=(_ublox_cfg_tp *)USART2_TX_BUF;
        cfg_tp->header=0X62B5;                //cfg header
        cfg_tp->id=0X0706;                        //cfg tp id
        cfg_tp->dlength=20;                        //數據區長度爲20個字節.
        cfg_tp->interval=interval;        //脈衝間隔,us
        cfg_tp->length=length;                //脈衝寬度,us
        cfg_tp->status=status;                   //時鐘脈衝配置
        cfg_tp->timeref=0;                        //參考UTC 時間
        cfg_tp->flags=0;                        //flags爲0
        cfg_tp->reserved=0;                         //保留位爲0
        cfg_tp->antdelay=820;            //天線延時爲820ns
        cfg_tp->rfdelay=0;                    //RF延時爲0ns
        cfg_tp->userdelay=0;            //用戶延時爲0ns
        Ublox_CheckSum((uchar*)(&cfg_tp->id),sizeof(_ublox_cfg_tp)-4,&cfg_tp->cka,&cfg_tp->ckb);
        while(DMA1_Channel7->CNDTR!=0);        //等待通道7傳輸完成   
        UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_tp));        //通過dma發送出去
  */
}

/*******************************************
函數名稱:Ublox_Cfg_Rate
功    能:配置UBLOX NEO-6的更新速率            
參    數:measrate:測量時間間隔,單位爲ms,最少不能小於200ms(5Hz)
          reftime:參考時間,0=UTC Time;1=GPS Time(一般設置爲1)
返回值  :
********************************************/
void Ublox_Cfg_Rate(uint measrate,uchar reftime)
{/*
        _ublox_cfg_rate *cfg_rate=(_ublox_cfg_rate *)USART2_TX_BUF;
        if(measrate<200)return;                //小於200ms,直接退出
        cfg_rate->header=0X62B5;        //cfg header
        cfg_rate->id=0X0806;                 //cfg rate id
        cfg_rate->dlength=6;                 //數據區長度爲6個字節.
        cfg_rate->measrate=measrate;//脈衝間隔,us
        cfg_rate->navrate=1;                //導航速率(週期),固定爲1
        cfg_rate->timeref=reftime;         //參考時間爲GPS時間
        Ublox_CheckSum((uchar*)(&cfg_rate->id),sizeof(_ublox_cfg_rate)-4,&cfg_rate->cka,&cfg_rate->ckb);
        while(DMA1_Channel7->CNDTR!=0);        //等待通道7傳輸完成   
        UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_rate));//通過dma發送出去
  */
}

以上爲GPS相關代碼,下面爲MSP430相關代碼

uart.h


#ifndef _UART_H_
#define _UART_H_

#include <msp430f149.h>

void UartInit(void);
void SendData(uchar dat);
void SendByte(uchar *pData);
void SendString(char *s);

#endif        /* __UART_H */

uart.c


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

void UartInit(void)
{
  //串口1配置
  P3DIR |= BIT4;            //p3.4設爲輸出
  P3SEL |= BIT4 + BIT5;     //P3.4,5設置爲TXD/RXD        
  ME1 |= UTXE0 + URXE0;     //enable tx and rx
  UCTL0 = 0x00;             //reset as 0
  UCTL0 |= CHAR;            //8 bit transfer        
  UTCTL0 = 0x00;            //reset as 0
  UTCTL0 |= SSEL0;          //select aclk(8M)
  UBR00 = 0x03;
  UBR10 = 0x00;             //波特率爲  9600(ACLK爲8MHz)
  UMCTL0 = 0x4A; 
  UCTL0 &= ~SWRST;          // reset UART        
  IE1 |= URXIE0;            // enable rx inerrupt

  //串口2配置
  P3DIR |= BIT6;            //p3.6設爲輸出
  P3SEL |= BIT6 + BIT7;     //P3.6,7設置爲TXD/RXD        
  ME2 |= URXE1 + UTXE1;     //enable tx and rx
  UCTL1 = 0x00;             //reset as 0
  UCTL1 |= CHAR;            //8 bit transfer        
  UTCTL1 = 0x00;            //reset as 0
  UTCTL1 |= SSEL0;          //select mclk
  UBR01 = 0x03;
  UBR11 = 0x00;             //波特率爲  9600(ACLK爲8MHz)
  UMCTL1 = 0x4A;
  UCTL1 &= ~SWRST;          // reset UART        
  IE2 |= URXIE1;            // enable rx inerrupt
}

void SendData(unsigned char dat)
{
  TXBUF0 = dat;
  while(!(IFG1 & UTXIFG0));
  //IFG1 &= ~(UTXIFG0);
}

void SendString(char *s)
{
  while(*s){
    SendData(*s++);
  }
}

void SendByte(uchar *pData)
{
  uchar i;
  for(i = 0; i < 8; i++){
    SendData(pData[i]);
  }
}

該串口操作爲配置串口1和串口2波特率都爲9600(之前看了GPS模塊的應用手冊,發現默認的波特率爲38400

MSP430與ATK-NEO-6M GPS模塊

但我將430的波特率設爲38400發現接收到的數據爲亂碼,於是乾脆直接將GPS的波特率設爲9600,我直接將模塊上的R5電阻取了,終於接收到正常的數據.)

main.c


#include <msp430f149.h>
#include "inc/lcd_fyd12864.h"
#include "inc/uart.h"
#include "inc/gps.h"

uchar Welcom1[] = "歡迎來到嵌入式";
uchar Welcom2[] = "************";
uchar Welcom3[] = "版主:*******";
uchar Welcom4[] = "DIY 實驗室";

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

uchar RxBuf[300], TxBuf[300],RxData[9];
uchar RxLen = 0;
uchar RxTempLen = 0;
uchar rev_flag = 0;
char dtbuf[50];
nmea_msg gpsx;
uchar swt = 1;

void Show_GPS_Info1(nmea_msg gpsx)
{
  float tp;
  //得到經度字符串
  tp=gpsx.longitude;           
  sprintf((char *)dtbuf,"Lon: %.5f %1c",tp/=100000,gpsx.ewhemi);
  DisplayString(0, 0, dtbuf);
  //得到緯度字符串
  tp=gpsx.latitude;           
  sprintf((char *)dtbuf,"Lat: %.5f %1c",tp/=100000,gpsx.nshemi);
  DisplayString(0, 1, dtbuf);
  //得到高度字符串
  tp=gpsx.altitude;           
  sprintf((char *)dtbuf,"Alt: %.1fm",tp/=10);
  DisplayString(0, 2, dtbuf);
  //得到速度字符串
  tp=gpsx.speed;           
  sprintf((char *)dtbuf,"Speed:%.3fkm/h",tp/=1000);        
  DisplayString(0, 3, dtbuf);
}

void Show_GPS_Info2(nmea_msg gpsx)
{
  //定位狀態
  if(gpsx.fixmode<=3){        
    sprintf((char *)dtbuf,"Fix Mode: %s",mode[gpsx.fixmode]);        
    DisplayString(0, 0, dtbuf);        
  }
  //用於定位的衛星數
  sprintf((char *)dtbuf,"Val sat: %02d",gpsx.posslnum);
  DisplayString(0, 1, dtbuf);        
  //可見衛星數
  sprintf((char *)dtbuf,"Vis sat: %02d",gpsx.svnum%100);        
  DisplayString(0, 2, dtbuf);        
}

void Show_GPS_Info3(nmea_msg gpsx)
{
  //顯示UTC日期
  sprintf((char *)dtbuf,"Date:%04d/%02d/%02d",gpsx.utc.year,gpsx.utc.month,gpsx.utc.date);
  DisplayString(0, 0, dtbuf);
  //顯示UTC時間
  sprintf((char *)dtbuf,"Time:%02d:%02d:%02d",gpsx.utc.hour,gpsx.utc.min,gpsx.utc.sec);
  DisplayString(0, 1, dtbuf);
}

void main()
{
  volatile uint i;
  WDTCTL = WDTPW + WDTHOLD;            //關閉看門狗

  BCSCTL1 &= ~XT2OFF;                       // XT2= HF XTAL
  do
  {
  IFG1 &= ~OFIFG;                           // Clear OSCFault flag
  for (i = 0xFF; i > 0; i--);               // Time for flag to set
  }
  while ((IFG1 & OFIFG));                   // OSCFault flag still set?
  //MCLK=8M,SCLK=1M
  BCSCTL2 |= SELM_2 + SELS + DIVS_3;        // MCLK= XT2 (safe)
  Delay_ms(500);
  UartInit();
  Delay_ms(500);

  P3DIR &= (~BIT2 + ~BIT3);

  LCDReset();
  DisplayString(1, 0, Welcom1);
  DisplayString(1, 1, Welcom2);
  DisplayString(1, 2, Welcom3);
  DisplayString(1, 3, Welcom4);
  Delay_ms(2000);
  LCDClear();
  Delay_ms(1000);
/*
  DisplayString(0, 0, latitude);
  DisplayString(0, 1, longitude);
  DisplayString(0, 2, elevation);
  DisplayString(0, 3, currTime);
*/  
  SendString("Lixiaoming\n");
  _EINT();
  while(1){
     //SendString("UART0 test!\n");
    if(!(P3IN & BIT2)){
      swt++;
      if(swt == 4)
        swt = 1;
    }
    if(rev_flag == 1){
      int i,len = 0;
      len = RxLen;
      for(i = 0; i < len; i++)
        TxBuf[i] = RxBuf[i];
      RxLen = 0;
      TxBuf[i] = 0;
      GPS_Analysis(&gpsx,TxBuf);
      switch(swt){
      case 1: LCDClear(); Show_GPS_Info1(gpsx); break;
      case 2: LCDClear(); Show_GPS_Info2(gpsx); break;
      default: LCDClear(); Show_GPS_Info3(gpsx); break;
      }
      SendString(TxBuf);
      rev_flag = 0;
    }
     //Delay_ms(1000);
  }
}

#pragma vector = UART0RX_VECTOR
__interrupt void UART0RxISR(void)
{
  //接收來自串口的數據
  while(!(IFG1 & UTXIFG0)); 
  RxBuf[RxTempLen++] = RXBUF0;
  while(RxBuf[RxTempLen-1] == '\n' && RxBuf[RxTempLen-2] == '\r' ){
        RxLen = RxTempLen;
        RxTempLen = 0;
        rev_flag = 1;
  }
}

#pragma vector = UART1RX_VECTOR
__interrupt void UART1RxISR(void)
{
  //接收來自串口的數據
  while(!(IFG2 & UTXIFG1)); 
  RxBuf[RxTempLen++] = RXBUF1;
  while(RxBuf[RxTempLen-1] == '\n'){
        RxLen = RxTempLen;
        RxTempLen = 0;
        rev_flag = 1;
  }
}

其中,有關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驅動。。。下面曬一下成果^-^.
MSP430與ATK-NEO-6M GPS模塊

PC串口接收到的數據如下:


$GPRMC,134856.00,A,2232.50576,N,11354.64802,E,0.084,,251113,,,A*7E
$GPGSV,3,2,09,22,75,191,27,25,58,074,22,29,08,122,16,31,48,276,19*76
gpsx->utc temp: 134857
gpsx->latitude temp: 223250578
gpsx->longitude temp: 1135464798
gpsx->utc.date temp: 251113
$GPRMC,134857.00,A,2232.50578,N,11354.64798,E,0.173,,251113,,,A*74
$GPGSV,3,2,09,22,75,191,27,25,58,074,23,29,08,122,15,31,48,276,20*7E
gpsx->utc temp: 134858
gpsx->latitude temp: 223250575
gpsx->longitude temp: 1135464785
gpsx->utc.date temp: 251113
$GPRMC,134858.00,A,2232.50575,N,11354.64785,E,0.140,,251113,,,A*7A
$GPGSV,3,2,09,22,75,191,27,25,58,074,23,29,08,122,15,31,48,276,19*74
gpsx->utc temp: 134859
gpsx->latitude temp: 223250575
gpsx->longitude temp: 1135464782
gpsx->utc.date temp: 251113
$GPRMC,134859.00,A,2232.50575,N,11354.64782,E,0.130,,251113,,,A*7B
$GPGSV,3,2,09,22,75,191,27,25,58,074,23,29,08,122,15,31,48,276,20*7E
gpsx->utc temp: 134900
gpsx->latitude temp: 223250570
gpsx->longitude temp: 1135464784
gpsx->utc.date temp: 251113
$GPRMC,134900.00,A,2232.50570,N,11354.64784,E,0.112,,251113,,,A*75
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章