1440|0

2014

帖子

0

TA的资源

纯净的硅(中级)

楼主
 

MSP430与ATK-NEO-6M GPS模块 [复制链接]

本帖最后由 Aguilera 于 2019-11-4 22:03 编辑

接下来先看看我的硬件环境。

硬件环境:MPS430开发板,FYD12864LCD显示屏,USB转串口线,ATK-NEO-6M GPS模块

软件环境:IAR集成开发环境,串口调试工具,Secure CRT

实现目标:MSP430通过串口2接收到GPS信息,显示在LCD上,同时通过串口1发送接收到的数据到PC。

 

1. 先把msp430的句段分析部分调通。

思路:将厂商提过的GPS语句分析部分代码移植过来,串口手动发送GPS数据,分析完后在LCD上显示。

将厂商提供的GPS语句分析代码贴出,(在此仅作为参考学习只用)

#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  */

 

#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-'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=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;
		*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相关代码


#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 */

#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);
  }
}

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


,但我将430的波特率设为38400发现接收到的数据为乱码,于是干脆直接将GPS的波特率设为9600,我直接将模块上的R5电阻取了,终于接收到正常的数据.)


#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: ";

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

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)
  
  UartInit();
  Delay_ms(500);
 
  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("**************\n");
  _EINT();
  while(1){
     //SendString("UART0 test!\n");
	 if(rev_flag == 1){
		int i,len = 0;
		len = RxLen;
		for(i = 0; i < len; i++)
			TxBuf = RxBuf;
		RxLen = 0;
		TxBuf = 0;
		GPS_Analysis(&gpsx,TxBuf);
		Show_GPS_Info(gpsx);
		SendString(TxBuf);
	 }
     //Delay_ms(1000);
  }
}

void Show_GPS_Info(nmea_msg gpsx)
{
  float tp;
  //得到经度字符串
  tp=gpsx.longitude;	   
  sprintf((char *)dtbuf,"Long:%.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);
  //显示UTC时间
  sprintf((char *)dtbuf,"UTC:%02d:%02d:%02d",gpsx.utc.hour,gpsx.utc.min,gpsx.utc.sec);
  DisplayString(0, 3, dtbuf);
}

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

#pragma vector = UART1RX_VECTOR
__interrupt void UART1RxISR(void)
{
  //接收来自串口的数据
  while(!(IFG2 & UTXIFG1)); 
  P2OUT = RXBUF1;
}

其中,有关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型,应该就正确了,期待回去后验证。。。。

昨天回去修改一下代码,将以前的uint类型替换为ulong,烧写后结果显示正确。同时在以前的基础上修改显示部分,按按键后显示另外的信息。

修改后的main.cpp如下:


#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 = RxBuf;
      RxLen = 0;
      TxBuf = 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;
  }
}

 显示的结果如下:

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表