'GPS-Uhr_V1-0.bas - Programm zur Darstellung der aktuellen Uhrzeit in UTC bzw. GMT 'Wolfgang Schneider, 06.04.2008 'Historie 'V1.0 Grundfunktionen mit Anzeige Datum, Uhrzeit, Locator und Anzahl Satelliten 'Basis: Microcontroller ATMega32 und LC-Display 20 x 2 auf Port C 'und als Empfänger eine GPS-Maus GR-213 der Fa. Holux 'Ein-/Ausgabe RS232 (GPS-Maus), VF-Display und ggf. I2C auf Port D 'Eingabe Steuerbefehle auf Port A 'PA7: Anzeige aktuelle Zeit bzw. Locator und Anzahl der Satelliten. 'PA7: Umschaltung Sommer-/Winterzeit 'PA6: Zeitzone +1 'PA5: Zeitzone -1 'Ausgabe Steuerbefehle auf Port B 'wird derzeit nicht benötigt 'Funktionsbeschreibung 'siehe Programmablaufbeschreibung in UKW-Berichte 2/2008 "GPS-Uhr" $regfile = "m32def.dat" $crystal = 9216000 'Quarzfrequenz $baud = 4800 $prog &HFF , &HFF , &HD9 , &H00 'Fuse-Bits: JTAG disabled, OSC High Frequency 'I2C-Bus initialisieren 'Config Scl = Portd.7 'Port PD7 ist SCL 'Config Sda = Portd.6 'Port PD6 ist SDA 'Config I2cdelay = 10 'SCL = 100 kHz 'I2cinit 'logischer Kanal für VF-Display öffnen Open "COMD.6:9600,8,N,1" For Output As #1 'LCD initialisieren Config Lcd = 20 * 2 'configure lcd screen Config Lcdbus = 4 Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.2 , Rs = Portc.0 Initlcd 'Initialisieren der Ports Config Porta = Input Porta.7 = 1 'interne Pull-Up-Widerstände aktivieren Porta.6 = 1 Porta.5 = 1 Porta.4 = 1 Config Portb = Output Sekundenpuls Alias Portb.0 'Interrupt-Routine für RS232 aktivieren On Urxc Onrxd Enable Urxc 'Dimensionierung der Variablen 'Dim Ser_buf(1) As String * 82 'max 1 x 82 Zeichen für GPS-Daten Dim Ser_buf(2) As String * 82 'max 2 x 82 Zeichen für GPS-Daten Dim S11 As String * 11 Dim Zeile1 As Byte Dim Zeile2 As Byte Dim I As Integer Dim Arr(13) As String * 11 Dim Laenge As String * 16 Dim Breite As String * 16 Dim Datum As String * 10 Dim Uhrzeit As String * 8 Dim Zeitzone As Integer Dim Zeichenfolge As String * 2 Dim X As Integer Dim Y As Integer Dim Z As Integer 'Programmstart Enable Interrupts Cls Cursor Off Noblink Locate 1 , 1 Lcd "GPS-Uhr V1.0 - DJ8ES" Locate 2 , 1 Lcd " Init GPS-Maus" Print #1 , Chr(12) 'CLS für LF-Display Print #1 , "Init GPS-Maus" ; 'Benötigte Datensätze aus GPS-Receiver konfigurieren 'Print "$PSRF103,00,00,00,01*24" 'GGA abschalten Print "$PSRF103,01,00,00,01*25" 'GLL abschalten Print "$PSRF103,02,00,00,01*26" 'GSA abschalten Print "$PSRF103,03,00,00,01*27" 'GSV abschalten 'Print "$PSRF103,04,00,00,01*20" 'RMC abschalten Print "$PSRF103,05,00,00,01*21" 'VTG abschalten Print "$PSRF103,06,00,00,01*22" 'MSS abschalten Print "$PSRF103,00,00,01,01*25" 'GGA einschalten Print "$PSRF103,04,00,01,01*21" 'RMC im 1s-Takt einschalten 'Print "$PSRF103,00,00,01,01*20" 'VTG einschalten Wait 2 'Startbedingung Portb = &B00000000 'Steuerport auf "Alles Aus" Zeitzone = 1 'entspricht MEZ Locate 1 , 1 Lcd "GPS-Uhr V1.0 - DJ8ES" Locate 2 , 1 Lcd " Warte auf GPS-Maus" Wait 2 'Maus-Init abwarten Do S11 = Left(ser_buf(1) , 5) Loop Until S11 = "GPGGA" Or S11 = "GPRMC" Locate 2 , 1 'GPS-Signal ist ok Lcd "GPS-Signal ok "; Print #1 , ", ok" ; If S11 = "GPRMC" Then Zeile1 = 1 Zeile2 = 2 Else Zeile1 = 2 Zeile2 = 1 End If Wait 3 Cls Do 'Die eingelesenen Datensätze (max. 2) werden in 13 Bereiche (Array 1..13) abgelegt 'Format: GPGGA,072344.187,5141.6192,N,00752.0280,E,1,06,1.6,119.9,M,47.4,M,0.0,0000 'Format: GPRMC,072344.187,... 'Auswertung GPRMC: Datum, Uhrzeit und Positionsangaben Do I = Split(ser_buf(zeile1) , Arr(1) , ",") Loop Until I > 12 '12 + 1 sind nötig, damit der 12. voll gefüllt ist 'aktuelle Zeit (UTC) liegt in Array 2 (GPRMC) Uhrzeit = Left(arr(2) , 2) + ":" + Mid(arr(2) , 3 , 2) + ":" + Mid(arr(2) , 5 , 2) Locate 1 , 13 Lcd Uhrzeit 'aktuelles Datum liegt in Array 10 (GPRMC) Datum = Left(arr(10) , 2) + "." + Mid(arr(10) , 3 , 2) + ".20" + Mid(arr(10) , 5 , 2) Locate 1 , 1 Lcd Datum Locate 1 , 11 Lcd " " 'Anzeige Datum und Uhrzeit (utc) auf dem LF-Display Zeichenfolge = Mid(arr(2) , 5 , 2) 'Auswertung aktuelle Sekunde X = Val(zeichenfolge) If X <> Z Then 'Warte für Anzeige auf nächste Sekunde Print #1 , Chr(12) ; " Time: " ; Uhrzeit ; " UTC"; Z = X End If 'Abfrage der Eingangspins auf gewünschten Ausgabemodus If Pina.7 = 0 Then 'Umschaltung auf Anzeige Locator/Anzahl Satelliten 'Anzeige des Locators (Maidenhead) Locate 2 , 14 '1. Buchstabe Zeichenfolge = Mid(arr(6) , 1 , 2) 'aktuelle Länge liegt in Array 6 (GPRMC) X = Val(zeichenfolge) X = X / 2 X = X + 74 Lcd Chr(x) '2. Buchstabe Zeichenfolge = Mid(arr(4) , 1 , 1) 'aktuelle Breite liegt in Array 4 (GPRMC) X = Val(zeichenfolge) X = X + 74 Lcd Chr(x) '1. Ziffer Zeichenfolge = Mid(arr(6) , 2 , 2) 'aktuelle Länge liegt in Array 6 (GPRMC) X = Val(zeichenfolge) While X >= 20 X = X - 20 Wend X = X / 2 X = X + 48 Lcd Chr(x) '2. Ziffer Zeichenfolge = Mid(arr(4) , 2 , 1) 'aktuelle Breite liegt in Array 4 (GPRMC) X = Val(zeichenfolge) X = X + 48 Lcd Chr(x) '3. Buchstabe Zeichenfolge = Mid(arr(6) , 3 , 1) 'aktuelle Länge liegt in Array 6 (GPRMC) X = Val(zeichenfolge) Y = X / 2 Y = Y * 2 Y = X - Y Y = Y * 60 Zeichenfolge = Mid(arr(6) , 4 , 2) 'aktuelle Länge liegt in Array 6 (GPRMC) X = Val(zeichenfolge) X = X + Y X = X / 5 X = X + 65 Lcd Chr(x) '4. Buchstabe Zeichenfolge = Mid(arr(4) , 3 , 2) + Mid(arr(4) , 6 , 1) 'aktuelle Breite liegt in Array 4 (GPRMC) X = Val(zeichenfolge) X = X / 25 X = X + 65 Lcd Chr(x) 'Auswertung GPGGA: Anzahl aktuell verfügbarer Satelliten Do I = Split(ser_buf(zeile2) , Arr(1) , ",") Loop Until I > 8 'aktuelle Anzahl der nutzbaren Satelliten liegt in Array 8 (GPGGA) Locate 2 , 1 Lcd "Sat.: " ; Arr(8) Locate 2 , 9 Lcd " " Locate 2 , 20 Lcd " " Else 'Anzeige lokale Uhrzeit (z.B. MEZ) 'Abfrage der Eingabetaster für +/- Zeitzone While Pina.4 = 0 Zeitzone = Zeitzone - 1 If Zeitzone < -11 Then Zeitzone = -11 Waitms 1000 Wend While Pina.5 = 0 Zeitzone = Zeitzone + 1 If Zeitzone > 12 Then Zeitzone = 12 Waitms 1000 Wend Locate 2 , 1 Select Case Zeitzone Case -11 : Lcd "Midway...:" Case -10 : Lcd "Honolulu.:" Case -9 : Lcd "Anchorage:" Case -8 : Lcd "Seattle..:" Case -7 : Lcd "Phoenix..:" Case -6 : Lcd "Chikago..:" Case -5 : Lcd "New York.:" Case -4 : Lcd "Brasilia.:" Case -3 : Lcd "Grönland.:" Case -2 : Lcd "Antarktis:" Case -1 : Lcd "Dakar....:" Case 0 : Lcd "London...:" Case 1 : Lcd "Berlin...:" Case 2 : Lcd "Bagdad...:" Case 3 : Lcd "Moskau...:" Case 4 : Lcd "Somalia..:" Case 5 : Lcd "Myanmar..:" Case 6 : Lcd "Jakarta..:" Case 7 : Lcd "Singapur.:" Case 8 : Lcd "Peking...:" Case 9 : Lcd "Tokio....:" Case 10 : Lcd "Sydney...:" Case 11 : Lcd "Lord Howe:" Case 12 : Lcd "Kiribati.:" Case Else : Zeitzone = 1 'im Fehlerfall auf Defaultwert 1 (MEZ) End Select Uhrzeit = Left(arr(2) , 2) X = Val(uhrzeit) X = X + Zeitzone 'Standard-Einstellung für Winterzeit If Pina.6 = 0 Then 'Umschaltung auf Sommerzeit X = X + 1 End If If X > 23 Then X = X - 24 End If If X < 0 Then X = X + 24 End If If X < 10 Then Uhrzeit = "0" + Str(x) + ":" + Mid(arr(2) , 3 , 2) + ":" + Mid(arr(2) , 5 , 2) Else Uhrzeit = Str(x) + ":" + Mid(arr(2) , 3 , 2) + ":" + Mid(arr(2) , 5 , 2) End If Locate 2 , 13 Lcd Uhrzeit Locate 2 , 11 Lcd " " End If Loop End '--------------RS232-Interrupt--------------------- Dim Udr_buf As Byte Dim Ser_col As Byte Ser_col = 1 'Index auf ser_buf() Onrxd: Udr_buf = Udr 'Byte aus UART lesen Select Case Udr_buf Case 13 : Case 10 : Incr Ser_col If Ser_col = 3 Then Ser_col = 1 End If Case "$" : Ser_buf(ser_col) = "" Case Else If Len(ser_buf(ser_col)) < 82 Then Ser_buf(ser_col) = Ser_buf(ser_col) + Chr(udr_buf) End If End Select Return