Komunikacja z modułem GPS02 firmy HOPE realizowana jest przy wykorzystaniu protokołu NMEA-0183, polegającego na wysyłaniu odpowiednio uformowanych zdań. Moduł standardowo komunikuje się przez port UART z prędkością 9600 bps, 8 bitów danych, 1 bit stopu, brak bitu parzystości. Najbardziej przydatne sekwencje to RMC (Recommended Minimum Specific GNSS Data) oraz VTG (Course Over Ground and Ground Speed). Budowa zdania RMC jest następująca:
$GPRMC,170230.918,A,5413.2821,N,01610.4976,E,000.0,000.0,170611,,,A*68
Gdzie poszczególne elementy mają następujące znaczenie:
- $GPRMC, – nagłówek zdania RMC,
- 170230.918, – czas UTC (w postaci hhmmss.sss),
- A, – znacznik ważności danych (A – dane ważne, V – dane nieważne),
- 5413.2821,N, – szerokość geograficzna (w postaci ssmm.mmmm) wraz z określeniem półkuli,
- 01610.4976,E, – długość geograficzna (w postaci sssmm.mmmm) wraz z określeniem półkuli,
- 000.0, – prędkość przemieszczania podana w węzłach,
- 000.0, – kierunek przemieszczania podany w stopniach,
- 170611,,, – data czasu UTC (w postaci ddmmyy),
- A*68 – suma kontrolna.
Natomiast budowa zdania VTG wygląda jak poniżej:
$GPVTG,000.0,T,,M,000.0,N,000.0,K,A*0D
Gdzie poszczególne elementy mają następujące znaczenie:
- $GPVTG, – nagłówek zdania VTG,
- 000.0, T, – kierunek przemieszczania podany w stopniach (prawdziwy),
- , M, – kierunek przemieszczania podany w stopniach (magnetyczny),
- 000.0,N, – prędkość przemieszczania podana w węzłach,
- 000.0, K, – prędkość przemieszczania podana w km/h,
- A*0D – suma kontrolna.
Przesyłane zdania mają stałą długość, wobec czego najlepszym sposobem jest przechowywanie ich w postaci tablic, a do poszczególnych elementów odwoływać się poprzez odpowiedni indeks.
W projekcie zaimplementowano także sygnalizację stanu pracy, jest ona realizowana przy użyciu trzech diod LED:
- LED1 – zapalenie tej diody informuje iż moduł GPS do urządzenia wysyła poprawne dane o współrzędnych geograficznych,
- LED2 – dioda będzie świeciła w czasie generowania pliku .gpx,
- LED3 – podobnie jak dioda LED2, jest zapalana podczas generowania pliku .gpx, z tą różnicą iż w momencie zatrzymania generowania pliku dioda gaśnie.
Program dla mikrokontrolera
Na listingu poniżej przedstawiono część kodu głównego programu. Na początku realizowana jest konfiguracja: RCC, wykorzystywanych pinów, używanych peryferii UART, inicjalizacja obsługi przerwań oraz inicjalizacja wyświetlacza modułu KAmodLCD1. W przypadku konfiguracji RCC, GPIO, UART i przerwań mamy do czynienia z podstawowymi konfiguracjami.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
int main(void) { //konfiguracja RCC Configuration_RCC(); //konfiguracja GPIO Configuration_GPIO(); //konfiguracja UART-ów Configuration_UART(); //konfiguracja obsługi przerwań Configuration_Interrupts(); //inicjalizacja wyświetlacza modułu KAmodLCD1 PCD8544_INIT(); PCD8544_LCDClear(); //nieskończona pętla while (1) { //kontrola dioda LED //uzyskiwane dane są ważne if(RxBufferRMC[18] == 'A') {LED_1_ON;} else {LED_1_OFF;} //włączone jest generowanie pliku .gpx if(OutputState != 0) {LED_2_ON;} else {LED_2_OFF;} //trwa wysyłanie nowych danych if((OutputState > 0) && (OutputState != 4)) {LED_3_ON;} else {LED_3_OFF;} //warunek sprawdzający czy odbiornik GPS przesyła poprawne dane //jeśli dane są poprawne to są one wyświetlane na wyświetlaczu if(RxBufferRMC[18] == 'A') { //wyczyszczenie zawartosci wyswietlacza PCD8544_LCDClear(); . . . //wyświetlenie aktualnej szerokości geograficznej PCD8544_LCDWriteSign(RxBufferRMC[20],12,2); PCD8544_LCDWriteSign(RxBufferRMC[21],18,2); PCD8544_LCDWriteSign(0x5C,24,2); PCD8544_LCDWriteSign(RxBufferRMC[22],30,2); PCD8544_LCDWriteSign(RxBufferRMC[23],36,2); PCD8544_LCDWriteSign('.',42,2); PCD8544_LCDWriteSign(RxBufferRMC[25],48,2); PCD8544_LCDWriteSign(RxBufferRMC[26],54,2); PCD8544_LCDWriteSign('\'',60,2); PCD8544_LCDWriteSign(RxBufferRMC[30],66,2); . . . } //w przypadku uzyskiwania danych, na wyświetlaczu pojawi się odpowiedni komunikat else { //wyczyszczenie zawartości wyświetlacza PCD8544_LCDClear(); //wyświetlenie odpowiednich informacji na wyświetlacz PCD8544_LCDWriteText("GPS",33,0); PCD8544_LCDWriteText("searching",15,3); } //zaktualizowanie informacji na wyświetlaczu PCD8544_LCDWrite(); //warunkowa aktualizacja informacji //realizowana gdy występuje różnica czasu w ciągach RxBufferRMC i OutputInner //sprawdzana jest wartość sekund if(RxBufferRMC[12] != OutputInner[73]) { //aktualizacja aktualnego czasu w ciągu OutputPre //rok OutputPre[306] = '2'; OutputPre[307] = '0'; OutputPre[308] = RxBufferRMC[61]; OutputPre[309] = RxBufferRMC[62]; //miesiac OutputPre[311] = RxBufferRMC[59]; OutputPre[312] = RxBufferRMC[60]; //dzien OutputPre[314] = RxBufferRMC[57]; OutputPre[315] = RxBufferRMC[58]; //godziny OutputPre[317] = RxBufferRMC[7]; OutputPre[318] = RxBufferRMC[8]; //minuty OutputPre[320] = RxBufferRMC[9]; OutputPre[321] = RxBufferRMC[10]; //sekundy OutputPre[323] = RxBufferRMC[11]; OutputPre[324] = RxBufferRMC[12]; //warunkowe wykonanie kodu w przypadku gdy program oczekuje //aktualizacji danych w ciągu OutputInner // if(OutputState == 3) { . . . //aktualizacja szerokości geograficznej w ciągu OutputInner OutputInner[15] = RxBufferRMC[20]; OutputInner[16] = RxBufferRMC[21]; //przeliczenie wartości minut na wartość ułamkowa stopnia temp = ((RxBufferRMC[22] - 0x30) * 100000); temp += ((RxBufferRMC[23] - 0x30) * 10000); temp += ((RxBufferRMC[25] - 0x30) * 1000); temp += ((RxBufferRMC[26] - 0x30) * 100); temp += ((RxBufferRMC[27] - 0x30) * 10); temp += ((RxBufferRMC[28] - 0x30) * 1); temp = temp / 60; //aktualizacja szerokości geograficznej w ciągu OutputInner cd. OutputInner[18] = temp / 1000 + 0x30; temp = temp % 1000; OutputInner[19] = temp / 100 + 0x30; temp = temp % 100; OutputInner[20] = temp / 10 + 0x30; temp = temp % 10; OutputInner[21] = temp % 10 + 0x30; OutputInner[22] = '0'; OutputInner[23] = '0'; . . . //ustawienie danych do wysyłani if(OutputState == 3) { OutputState = 2; //włączenie przerwania od TXE USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } } } } } |