GPS 通訊模組系統,透過RS232通訊介面可獲得衛星時間與方位
NMEA((National Marine Electronics Association)0183 ASCII 的格式
本人將使用收到的 RMC 資料串進行解析,取出衛星當下的時間
Message Structure:
$GPRMC,hhmmss,status,latitude,N,longitude,E,spd,cog,ddmmyy,mv,mvE,mode*cs<CR><LF>
Example:
$GPRMC,083559.00,A,4717.11437,N,00833.91522,E,0.004,77.52,091202,,,A*57
Field No. |
Example |
Format |
Name |
Unit |
Description |
0 |
$GPRMC |
string |
$GPRMC |
- |
Message
ID, RMC protocol header |
1 |
083559.00 |
hhmmss.sss |
hhmmss. |
- |
UTC
Time, Time of position fix |
2 |
A |
character |
Status |
- |
Status,
V = Navigation receiver warning, A = Data
valid, see Position Fix Flags description |
3 |
4717.11437 |
ddmm.mmmm |
Latitude |
- |
Latitude,
Degrees + minutes, see Format description |
4 |
N |
character |
N |
- |
N/S
Indicator, hemisphere N=north or S=south |
5 |
00833.91522 |
dddmm.
Mmmm |
Longitude |
- |
Longitude,
Degrees + minutes, see Format description |
6 |
E |
character |
E |
- |
E/W
indicator, E=east or W=west |
7 |
0.004 |
numeric |
Spd |
knots |
Speed
over ground |
8 |
77.52 |
numeric |
Cog |
degrees |
Course
over ground |
9 |
091202 |
ddmmyy |
date |
- |
Date
in day, month, year format |
10 |
- |
numeric |
mv |
degrees |
Magnetic
variation value, not being output by receiver |
11 |
- |
character |
mvE |
- |
Magnetic
variation E/W indicator, not being output by receiver |
12 |
- |
character |
mode |
- |
Mode
Indicator, see Position Fix Flags description |
13 |
*57 |
hexadecimal |
cs |
- |
Checksum |
14 |
- |
character |
<CR><LF> |
- |
Carriage
Return and Line Feed |
程式撰寫
- 使用編譯器: CCS PCWHD
- 使用單晶片:Microchip PIC18F45K22
透過剛剛介紹的$GPSRMC 接收來自衛星訊號的ASCII內容,裡面包含了有UTC標準時間,本文透過解析內容並轉為資料串再回傳給單晶片修正RTC時間
副程式除了解析出時間外,同時也將轉換經緯度座標位置
char *srg: 傳入接收來自於RS232資料串
TDateTime *DT: 傳入欲擺放時間日期等資訊的結構串
TCoordinate *Coordinate:傳入欲擺放經緯度等資訊的結構串
程序完成後成功傳為0
int GPS_GPRMC_stream_decoder(char *srg, TDateTime *DT, TCoordinate *Coordinate)
{
char st = 0, ed = 0, index = 0;
//step1: find $GPRMC position,not found reutn value = -1
if (strFind(srg, (char*)"$GPRMC", 0) == -1)
return -1;
//step2: find first ',' position in string
st = charFind(srg, ',', 0);
if (st == -1)
return -1;
char str[16];
char str_length = strlen(srg);
while (st != -1 && index < str_length)
{
ed = charFind(srg, ',', st+1);
switch (++index)
{
case 1 : DT->hour = atoi(StrmnCpy(str, srg, st+1, 2));
DT->min = atoi(StrmnCpy(str, srg, st+3, 2));
DT->sec = atoi(StrmnCpy(str, srg, st+5, 2));
break;
case 2 : if (*StrmnCpy(str, srg, st+1, 1) != 'A')
return -1;
break;
case 3 : StrmnCpy(str, srg, st+1, ed-st-1);
Coordinate->Latitude = GPS_StrtoLatitude(&str, ed-st-1);
break;
case 4 : StrmnCpy(str, srg, st+1, 1);
Coordinate->N_S = str[0];
break;
case 5 : StrmnCpy(str, srg, st+1, ed-st-1);
Coordinate->Longitude = GPS_StrtoLongitude(&str, ed-st-1);
break;
case 6 : StrmnCpy(str, srg, st+1, 1);
Coordinate->E_W = str[0];
break;
case 7 : StrmnCpy(str, srg, st+1, ed-st-1);
Coordinate->speed = strtof(str, '0');
break;
case 9 : DT->m_day = atoi(StrmnCpy(str, srg, st+1, 2));
DT->month = atoi(StrmnCpy(str, srg, st+3, 2));
DT->year = atoi(StrmnCpy(str, srg, st+5, 2));
DT->w_day = RTC_Weekend_Transfer(20, DT->year, DT->month, DT->m_day);
break;
}
st = ed;
}
return 0;
}
尋找字串中指定的字串內容處在位置
int strFind(char *srg, char *s, size_t st)
{
BYTE pos;
for (pos=st, srg+=st; *srg != '\0'; srg++, pos++)
if (strspn(srg, s) == strlen(s))
return pos;
return -1;
}
尋找字元中指定的字串內容處在位置
int charFind(char *s, char c, size_t st)
{
BYTE pos;
for (pos=st, s+=st; *s != '\0'; s++, pos++)
if (*s == c)
return pos;
return -1;
}
複製字串
char *StrmnCpy(char *str, char *srg, size_t m, size_t n)
{
int i=0;
char *s;
for(s=str, i=m, srg+=m; i<m+n; i++)
*s++ = *srg++;
*s++ = '\0';
return str;
}