本文來源於「21ic TI微控制器&處理器論壇」,原貼見底部「閱讀原文」linux
近短期在網上買了一個GPS模塊,正好正在學習MSP430單片機,因而決心將GPS模塊與MSP430結合起來,同時將代碼貼出來,發現網上搜到好多資料都要註冊才能下載,有些還要錢。本身動腦,才能自娛自樂。git
1、測試篇緩存
剛拿到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顆衛星信號。antd
2、開發篇ide
剛拿到GPS模塊,感受要是開發起來會很麻煩,後來通過實驗,其實很簡單,由於賣家提供的資料已經足夠開發。句段的分析函數都已提供,咱們只需將接口寫好便可。接下來先看看個人硬件環境。svn
硬件環境: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
但我將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驅動。。。下面曬一下成果^-^.
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