This post was last edited by Aguilera on 2019-11-4 22:03
Next, let me take a look at my hardware environment.
Hardware environment: MPS430 development board, FYD12864LCD display, USB to serial cable, ATK-NEO-6M GPS module
Software environment: IAR integrated development environment, serial port debugging tool, Secure CRT
Achievement goal: MSP430 receives GPS information through serial port 2 and displays it on the LCD, and sends the received data to the PC through serial port 1.
1. First adjust the sentence analysis part of msp430.
Idea: Transplant the GPS sentence analysis code mentioned by the manufacturer, manually send GPS data through the serial port, and display it on the LCD after analysis.
Post the GPS sentence analysis code provided by the manufacturer (only for reference and study)
#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 protocol important parameter structure definition
//Satellite information
typedef struct
{
uchar num; //Satellite number
uchar eledeg; //Satellite elevation angle
uint azideg; //Satellite azimuth
uchar sn; //Signal to noise ratio
}nmea_slmsg;
//UTC time information
typedef struct
{
uint year; //year
uchar month; //month
uchar date; //date
uchar hour; //hour
uchar min; //minutes
uchar sec; //seconds
}nmea_utc_time;
//NMEA 0183 protocol parsed data storage structure
typedef struct
{
uchar svnum; //Number of visible satellites
nmea_slmsg slmsg[12]; //Maximum 12 satellites
nmea_utc_time utc; //UTC time
int latitude; //The latitude is enlarged by 100000 times, so it should be divided by 100000
uchar nshemi; //North Latitude/South Latitude, N: North Latitude; S: South Latitude
int longitude; //Longitude is enlarged 100000 times, actually divided by 100000
uchar ewhemi; //East longitude/West longitude, E: East longitude; W: West longitude
uchar gpssta; //GPS status: 0, not positioned; 1, non-differential positioning; 2, differential positioning; 6, estimating.
uchar posslnum; //The number of satellites used for positioning, 0~12.
uchar possl[12]; //Satellite number used for positioning
uchar fixmode; // Positioning type: 1, no positioning; 2, 2D positioning; 3, 3D positioning
uint pdop; //Position precision factor 0~500, corresponding to actual value 0~50.0
uint hdop; //Horizontal precision factor 0~500, corresponding to actual value 0~50.0
uint vdop; //Vertical precision factor 0~500, corresponding to actual value 0~50.0
int altitude; //Altitude, magnified 10 times, actually divided by 10. Unit: 0.1m
uint speed; // Ground speed, magnified 1000 times, actually divided by 10. Unit: 0.001 km/h
}nmea_msg;
////////////////////////////////////////////////////////////////////////////////////////////////////
//UBLOX NEO-6M clock pulse configuration structure
typedef struct
{
uint header; //cfg header, fixed to 0X62B5 (little endian mode)
uint id; //CFG TP ID:0X0706 (little endian mode)
uint dlength; //data length
int interval; //clock pulse interval, unit is us
int length; //Pulse width, unit is us
signed char status; //Clock pulse configuration: 1, high level is valid; 0, off; -1, low level is valid.
uchar timeref; //Reference time: 0, UTC time; 1, GPS time; 2, local time.
uchar flags; //Time pulse setting flag
uchar reserved; //reserved
signed short antdelay; //antenna delay
signed short rfdelay; //RF delay
signed int userdelay; //User delay
uchar cka; //Check CK_A
uchar ckb; //Check CK_B
}_ublox_cfg_tp;
//UBLOX NEO-6M refresh rate configuration structure
typedef struct
{
uint header; //cfg header, fixed to 0X62B5 (little endian mode)
uint id; //CFG RATE ID:0X0806 (little endian mode)
uint dlength; //data length
uint measrate; //Measurement time interval, in ms, must not be less than 200ms (5Hz)
uint navrate; //Navigation rate (cycle), fixed at 1
uint timeref; //Reference time: 0=UTC Time; 1=GPS Time;
uchar cka; //Check CK_A
uchar ckb; //Check CK_B
}_ublox_cfg_rate;
int NMEA_Str2num(fly *buf,fly*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"
/*******************************************
Function Name: NMEA_Comma_Pos
Function: Get the position of the cxth comma from buf
parameter:
Return value: 0~0XFE, representing the offset of the comma position
0XFF, indicating that the cxth comma does not exist
********************************************/
fly NMEA_Comma_Pos(fly *buf,fly cx)
{
fly *p=buf;
while(cx)
{
if(*buf=='*'||*buf<' '||*buf>'z')return 0XFF; //If '*' or illegal characters are encountered, the cxth comma does not exist
if(*buf==',')cx--;
buf++;
}
return buf-p;
}
/*******************************************
Function name: NMEA_Pow
Function: m^n function
parameter:
Return value: m^n power.
********************************************/
int NMEA_Pow(fly m,fly n)
{
int result=1;
while(n--)result*=m;
return result;
}
/*******************************************
Function name: NMEA_Str2num
Function: Convert str to a number, ending with ',' or '*'
Parameters: buf: digital storage area; dx: number of decimal places, returned to the calling function
Return value: the converted value
********************************************/
int NMEA_Str2num(fly *buf,fly*dx)
{
fly *p=buf;
int ires=0,fres=0;
uchar ilen=0,flen=0,i;
fly mask=0;
int res;
while(1) //Get the length of integers and decimals
{
if(*p=='-'){mask|=0X02;p++;} //is a negative number
if(*p==','||(*p=='*'))break; //Ended
if(*p=='.'){mask|=0X01;p++;} // Encountered a decimal point
else if(*p>'9'||(*p<'0')) // There are illegal characters
{
ilen=0;
flen=0;
break;
}
if(mask&0X01)flen++;
else ilen++;
p++;
}
if(mask&0X02)buf++; //remove the minus sign
for(i=0;i<ilen;i++) //Get the integer part of the data
{
ires+=NMEA_Pow(10,ilen-1-i)*(buf-'0');
}
if(flen>5)flen=5; //Maximum 5 decimal places
*dx=flen; //Decimal places
for(i=0;i<flen;i++) //Get the decimal part of the data
{
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;
}
/*******************************************
Function name: NMEA_GPGSV_Analysis
Function: Analyze GPGSV information
Parameters: gpsx: nmea information structure; buf: the first address of the received GPS data buffer
Return value:
********************************************/
void NMEA_GPGSV_Analysis(nmea_msg *gpsx,uchar *buf)
{
fly *p,*p1,dx;
fly len,i,j,slx=0;
flying poskh;
p=buf;
p1=(uchar*)strstr((const char *)p,"$GPGSV");
len=p1[7]-'0'; //Get the number of GPGSV
posx=NMEA_Comma_Pos(p1,3); //Get the total number of visible satellites
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); //Get satellite number
else break;
posx=NMEA_Comma_Pos(p1,5+j*4);
if(posx!=0XFF)gpsx->slmsg[slx].eledeg=NMEA_Str2num(p1+posx,&dx); //Get satellite elevation angle
else break;
posx=NMEA_Comma_Pos(p1,6+j*4);
if(posx!=0XFF)gpsx->slmsg[slx].azideg=NMEA_Str2num(p1+posx,&dx); //Get satellite azimuth
else break;
posx=NMEA_Comma_Pos(p1,7+j*4);
if(posx!=0XFF)gpsx->slmsg[slx].sn=NMEA_Str2num(p1+posx,&dx); //Get satellite signal-to-noise ratio
else break;
slx++;
}
p=p1+1; //Switch to the next GPGSV information
}
}
/*******************************************
Function name: NMEA_GPGGA_Analysis
Function: Analyze GPGGA information
Parameters: gpsx: nmea information structure; buf: the first address of the received GPS data buffer
Return value:
********************************************/
void NMEA_GPGGA_Analysis(nmea_msg *gpsx,uchar *buf)
{
fly *p1,dx;
flying poskh;
p1=(uchar*)strstr((const char *)buf,"$GPGGA");
posx=NMEA_Comma_Pos(p1,6); //Get GPS status
if(posx!=0XFF)gpsx->gpssta=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,7); //Get the number of satellites used for positioning
if(posx!=0XFF)gpsx->posslnum=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,9); //Get the altitude
if(posx!=0XFF)gpsx->altitude=NMEA_Str2num(p1+posx,&dx);
}
/*******************************************
Function name: NMEA_GPGSA_Analysis
Function: Analyze GPGSA information
Parameters: gpsx: nmea information structure; buf: the first address of the received GPS data buffer
Return value:
********************************************/
void NMEA_GPGSA_Analysis(nmea_msg *gpsx,uchar *buf)
{
fly *p1,dx;
flying poskh;
flying i;
p1=(uchar*)strstr((const char *)buf,"$GPGSA");
posx=NMEA_Comma_Pos(p1,2); //Get positioning type
if(posx!=0XFF)gpsx->fixmode=NMEA_Str2num(p1+posx,&dx);
for(i=0;i<12;i++) //Get the positioning satellite number
{
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); //Get PDOP position precision factor
if(posx!=0XFF)gpsx->pdop=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,16); //Get HDOP position precision factor
if(posx!=0XFF)gpsx->hdop=NMEA_Str2num(p1+posx,&dx);
posx=NMEA_Comma_Pos(p1,17); //Get VDOP position precision factor
if(posx!=0XFF)gpsx->vdop=NMEA_Str2num(p1+posx,&dx);
}
/*******************************************
Function name: NMEA_GPRMC_Analysis
Function: Analyze GPRMC information
Parameters: gpsx: nmea information structure; buf: the first address of the received GPS data buffer
Return value:
********************************************/
void NMEA_GPRMC_Analysis(nmea_msg *gpsx,uchar *buf)
{
fly *p1,dx;
flying poskh;
int temp;
float rs;
p1=(uchar*)strstr((const char *)buf,"$GPRMC");
posx=NMEA_Comma_Pos(p1,1); //Get UTC time
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx); //Get UTC time, remove ms
gpsx->utc.hour=temp/10000;
gpsx->utc.min=(temp/100)%100;
gpsx->utc.sec=temp%100;
}
posx=NMEA_Comma_Pos(p1,3); //Get latitude
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx);
gpsx->latitude=temp/NMEA_Pow(10,dx+2); //get degrees
rs=temp%NMEA_Pow(10,dx+2); //get'
gpsx->latitude = gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60; //Convert to degrees
}
posx=NMEA_Comma_Pos(p1,4); //South latitude or north latitude
if(posx!=0XFF)gpsx->nshemi=*(p1+posx);
posx=NMEA_Comma_Pos(p1,5); //Get longitude
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx);
gpsx->longitude=temp/NMEA_Pow(10,dx+2); //get degrees
rs=temp%NMEA_Pow(10,dx+2); //get'
gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60; //Convert to degrees
}
posx=NMEA_Comma_Pos(p1,6); //East longitude or west longitude
if(posx!=0XFF)gpsx->ewhemi=*(p1+posx);
posx=NMEA_Comma_Pos(p1,9); //Get UTC date
if(posx!=0XFF)
{
temp=NMEA_Str2num(p1+posx,&dx); //Get UTC date
gpsx->utc.date=temp/10000;
gpsx->utc.month=(temp/100)%100;
gpsx->utc.year=2000+temp%100;
}
}
/*******************************************
Function name: NMEA_GPVTG_Analysis
Function: Analyze GPVTG information
Parameters: gpsx: nmea information structure; buf: the first address of the received GPS data buffer
Return value:
********************************************/
void NMEA_GPVTG_Analysis(nmea_msg *gpsx,uchar *buf)
{
fly *p1,dx;
flying poskh;
p1=(uchar*)strstr((const char *)buf,"$GPVTG");
posx=NMEA_Comma_Pos(p1,7); //Get ground speed
if(posx!=0XFF)
{
gpsx->speed=NMEA_Str2num(p1+posx,&dx);
if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx); //Ensure 1000 times enlargement
}
}
/*******************************************
Function name: GPS_Analysis
Function: Extract NMEA-0183 information
Parameters: gpsx: nmea information structure; buf: the first address of the received GPS data buffer
Return value:
********************************************/
void GPS_Analysis(nmea_msg *gpsx,uchar *buf)
{
NMEA_GPGSV_Analysis(gpsx,buf); //GPGSV analysis
NMEA_GPGGA_Analysis(gpsx,buf); //GPGGA analysis
NMEA_GPGSA_Analysis(gpsx,buf); //GPGSA analysis
NMEA_GPRMC_Analysis(gpsx,buf); //GPRMC解析
NMEA_GPVTG_Analysis(gpsx,buf); //GPVTG解析
}
/*******************************************
Function name: Ublox_CheckSum
Function: GPS checksum calculation
Parameters: buf: the first address of the data buffer; len: data length; cka, ckb: two check results.
Return value:
********************************************/
void Ublox_CheckSum(uchar *buf,uint len,uchar* cka,uchar*ckb)
{
uint i;
*cka=0;*ckb=0;
for(i=0;i<len;i++)
{
*chka=*chka+buf;
*ckb=*ckb+*cka;
}
}
/*******************************************
Function name: Ublox_Cfg_Tp
Function: Configure the clock pulse output of UBLOX NEO-6
Parameter: interval: pulse interval
length: pulse width
status: pulse configuration: 1, high level is valid; 0, off; -1, low level is valid.
Return value:
********************************************/
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; //The data area length is 20 bytes.
cfg_tp->interval=interval; //Pulse interval, us
cfg_tp->length=length; //Pulse width, us
cfg_tp->status=status; //Clock pulse configuration
cfg_tp->timeref=0; //reference UTC time
cfg_tp->flags=0; //flags为0
cfg_tp->reserved=0; //Reserved bit is 0
cfg_tp->antdelay=820; //antenna delay is 820ns
cfg_tp->rfdelay=0; //RF delay is 0ns
cfg_tp->userdelay=0; //User delay is 0ns
Ublox_CheckSum((uchar*)(&cfg_tp->id),sizeof(_ublox_cfg_tp)-4,&cfg_tp->cka,&cfg_tp->ckb);
while(DMA1_Channel7->CNDTR!=0); //Wait for channel 7 transmission to complete
UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_tp)); //Send via dma
*/
}
/*******************************************
Function Name: Ublox_Cfg_Rate
Function: Configure the update rate of UBLOX NEO-6
Parameters: measrate: measurement time interval, in ms, must not be less than 200ms (5Hz)
reftime: reference time, 0=UTC Time; 1=GPS Time (usually set to 1)
Return value:
********************************************/
void Ublox_Cfg_Rate(uint measrate,uchar reftime)
{/*
_ublox_cfg_rate *cfg_rate=(_ublox_cfg_rate *)USART2_TX_BUF;
if(measrate<200)return; //Less than 200ms, exit directly
cfg_rate->header=0X62B5; //cfg header
cfg_rate->id=0X0806; //cfg rate id
cfg_rate->dlength=6; //The data area length is 6 bytes.
cfg_rate->measrate=measrate; //Pulse interval, us
cfg_rate->navrate=1; //Navigation rate (cycle), fixed at 1
cfg_rate->timeref=reftime; //reference time is GPS time
Ublox_CheckSum((uchar*)(&cfg_rate->id),sizeof(_ublox_cfg_rate)-4,&cfg_rate->cka,&cfg_rate->ckb);
while(DMA1_Channel7->CNDTR!=0); //Wait for channel 7 transmission to complete
UART_DMA_Enable(DMA1_Channel7,sizeof(_ublox_cfg_rate)); //Send via DMA
*/
}
The above is the GPS related code, the following is the MSP430 related code
#ifndef _UART_H_
#define _UART_H_
#include <msp430f149.h>
void UartInit(void);
void SendData(volatile dat);
void SendByte(uchar *pData);
void SendString(char *s);
#endif /* __UART_H */
#include "../inc/uart.h"
void UartInit(void)
{
//Serial port 1 configuration
P3DIR |= BIT4; //p3.4 is set as output
P3SEL |= BIT4 + BIT5; //P3.4,5 are set to 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; //Baud rate is 9600 (ACLK is 8MHz)
UMCTL0 = 0x4A;
UCTL0 &= ~SWRST; // reset UART
IE1 |= URXIE0; // enable rx inerrupt
//Serial port 2 configuration
P3DIR |= BIT6; //p3.6 is set as output
P3SEL |= BIT6 + BIT7; //P3.6,7 are set to 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; //Baud rate is 9600 (ACLK is 8MHz)
UMCTL1 = 0x4A;
UCTL1 &= ~SWRST; // reset UART
IE2 |= URXIE1; // enable rx inerrupt
}
void SendData(unsigned char dat)
{
TXBUF0 = that;
while(!(IFG1 & UTXIFG0));
//IFG1 &= ~(UTXIFG0);
}
void SendString(char *s)
{
while(*s){
SendData(*s++);
}
}
void SendByte(uchar *pData)
{
flying i;
for(i = 0; i < 8; i++){
SendData(pData);
}
}
The serial port operation is to configure the baud rate of both serial port 1 and serial port 2 to 9600 (I have read the application manual of the GPS module before and found that the default baud rate is 38400
, but I set the baud rate of 430 to 38400 and found that the received data was garbled, so I simply set the baud rate of GPS to 9600, and directly removed the R5 resistor on the module, and finally received normal data.)
#include <msp430f149.h>
#include "inc/lcd_fyd12864.h"
#include "inc/uart.h"
#include "inc/gps.h"
uchar Welcom1[] = "Welcome to Embedded";
uchar Welcom2[] = "*************";
uchar Welcom3[] = "Moderator: ******";
uchar Welcom4[] = "DIY Lab";
uchar latitude[] = "Lat: ";
uchar longitude[] = "Long: ";
uchar elevation[] = "Ele: ";
uchar currTime[] = "Time: ";
float RxBuf[300], TxBuf[300];
float RxLen = 0;
float RxTempLen = 0;
uchar rev_flag = 0;
char dtbuf[50];
nmea_msg gpsx;
void main()
{
volatile uint i;
WDTCTL = WDTPW + WDTHOLD; // Turn off the watchdog
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;
//Get the longitude string
tp=gpsx.longitude;
sprintf((char *)dtbuf,"Long:%.5f %1c",tp/=100000,gpsx.ewhemi);
DisplayString(0, 0, dtbuf);
//Get the latitude string
tp=gpsx.latitude;
sprintf((char *)dtbuf,"Lat:%.5f %1c",tp/=100000,gpsx.nshemi);
DisplayString(0, 1, dtbuf);
//Get the height string
tp=gpsx.altitude;
sprintf((char *)dtbuf,"Alt:%.1fm",tp/=10);
DisplayString(0, 2, dtbuf);
//Display UTC time
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)
{
//Receive data from the serial port
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)
{
//Receive data from the serial port
while(!(IFG2 & UTXIFG1));
P2OUT = RXBUF1;
}
Among them, the LCD display part will be discussed in detail in other blog posts.
After burning the program to 430, power on, open the serial port debugging tool, and send the text as follows:
$GPGGA,023543.00,2308.28715,N,11322.09875,E,1,06,1.49,41.6,M,-5.3,M,,*7D
The data received will be the same as the one sent, and the LCD will show the altitude as 41.6m.
This indicates that the data can be accepted and processed correctly.
All you need to do next is copy the receive interrupt code of serial port 0 to the receive interrupt code of serial port 1.
Power on the device, and the LCD will display information, but the displayed data will be 0, indicating that GPS has not yet successfully located the device. After about 2 to 3 minutes, the indicator light on the GPS module will begin to flash, and the current longitude, latitude, altitude, and UTC time can be seen on the LCD. At the same time, when connected with ScuetCRT, the original data received by 430 can be seen.
The following figure shows the result of the experiment. The time display has a little problem, because there is no conversion or other reasons. However, after a few days of hard work, the GPS is finally fixed. The next step is to write a Linux driver. . . . Below is a post
Replenish:
I was busy with work before, and now I look back and find that the results of analyzing and displaying the received data are not correct. It is very likely caused by data overflow. The data sent to the PC through serial port 1 can be seen that the data received from the GPS module is correct. The only possibility is that an error occurred during data analysis. Sure enough, I tracked it to gps.c and found that the data processed was too large, and the int of msp430 is only 16 bits, with a maximum value of 65536, so it will definitely overflow when loading the data. I only discovered this when I occasionally looked at it at work today. After returning, I replaced the int type used with the long type, and it should be correct. I look forward to verifying it after returning. . . .
Yesterday I went back to modify the code and replaced the previous uint type with ulong. After burning, the result was displayed correctly. At the same time, I modified the display part based on the previous one, and displayed other information after pressing the button.
The modified main.cpp is as follows:
#include <msp430f149.h>
#include "inc/lcd_fyd12864.h"
#include "inc/uart.h"
#include "inc/gps.h"
uchar Welcom1[] = "Welcome to Embedded";
uchar Welcom2[] = "************";
uchar Welcom3[] = "Moderator: *******";
uchar Welcom4[] = "DIY Lab";
uchar latitude[] = "Lat: ";
uchar longitude[] = "Long: ";
uchar elevation[] = "Ele: ";
uchar currTime[] = "Time: ";
const uchar *mode[4] = {"Fail", "Fail", "2D", "3D"};
float RxBuf[300], TxBuf[300],RxData[9];
float RxLen = 0;
float RxTempLen = 0;
uchar rev_flag = 0;
char dtbuf[50];
nmea_msg gpsx;
fly swt = 1;
void Show_GPS_Info1(nmea_msg gpsx)
{
float tp;
//Get the longitude string
tp=gpsx.longitude;
sprintf((char *)dtbuf,"Lon: %.5f %1c",tp/=100000,gpsx.ewhemi);
DisplayString(0, 0, dtbuf);
//Get the latitude string
tp=gpsx.latitude;
sprintf((char *)dtbuf,"Lat: %.5f %1c",tp/=100000,gpsx.nshemi);
DisplayString(0, 1, dtbuf);
//Get the height string
tp=gpsx.altitude;
sprintf((char *)dtbuf,"Alt: %.1fm",tp/=10);
DisplayString(0, 2, dtbuf);
//Get the speed string
tp=gpsx.speed;
sprintf((char *)dtbuf,"Speed:%.3fkm/h",tp/=1000);
DisplayString(0, 3, dtbuf);
}
void Show_GPS_Info2(nmea_msg gpsx)
{
// Positioning status
if(gpsx.fixmode<=3){
sprintf((char *)dtbuf,"Fix Mode: %s",mode[gpsx.fixmode]);
DisplayString(0, 0, dtbuf);
}
//Number of satellites used for positioning
sprintf((char *)dtbuf,"Val sat: %02d",gpsx.posslnum);
DisplayString(0, 1, dtbuf);
//Number of visible satellites
sprintf((char *)dtbuf,"Vis sat: %02d",gpsx.svnum%100);
DisplayString(0, 2, dtbuf);
}
void Show_GPS_Info3(nmea_msg gpsx)
{
// Display UTC date
sprintf((char *)dtbuf,"Date:%04d/%02d/%02d",gpsx.utc.year,gpsx.utc.month,gpsx.utc.date);
DisplayString(0, 0, dtbuf);
//Display UTC time
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; // Turn off the watchdog
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)
{
//Receive data from the serial port
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)
{
//Receive data from the serial port
while(!(IFG2 & UTXIFG1));
RxBuf[RxTempLen++] = RXBUF1;
while(RxBuf[RxTempLen-1] == '\n'){
RxLen = RxTempLen;
RxTempLen = 0;
rev_flag = 1;
}
}
The results are as follows:
|