'******************************************************************** '* GPS Coordinate display on LCD '* uP: AT89S8313 '* Language: BASCOM-AVR 1.11.7.4 '* Date: 2005.Jan.22 '* Version: V2.00 '* Author: Brett England '******************************************************************** $regfile = "2313def.dat" $crystal = 8000000 $baud = 4800 ' condition compilation flag Const Debug = 0 #if Debug Dim Temp_i As Byte #endif Dim Rs232_exit As Byte ' Sec count for RS232 timeout Dim Read_ok As Bit ' Valid GPS frame found Dim Data_ok As Bit ' Start of GPS frame Dim Read_num As Byte ' RS232 character count Dim S2 As String * 16 ' LCD output buffer Dim Gps_state As Bit Dim Gps_date As String * 7 ' DDMMYY + comma Dim Gps_time As String * 6 ' HHMMSS Dim Latitude As String * 9 Dim Longitude As String * 10 Dim North_south As Byte ' N/S Dim East_west As Byte ' E/W Dim Spin_c As Bit ' Toggles when no data Rx Dim Temp_j As Byte Dim Time1_count As Byte ' Second ticker Dim Time1_store As Byte Dim Time1_ok As Bit ' Internal timer overflow ind Dim Eventime As Bit ' Set every other second Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2 Config Lcd = 16 * 1 'configure lcd screen ' Once enabled, the timer counts each clock period (or you can select a ' divided down input clock if you prefer). When the timer overflows (65536 ' counts) you get an interrupt. With a 8MHz clock, this doesn't work out to ' anything very useful. At 8MHz, each clock pulse is 125nS and 65536 of them ' is 8.192 milliseconds. ' I want a timer that resolves to 1000mS, so the first step is to divide down ' the input clock . Input clock to divide by 256, so now each clock pulse is ' worth (8.192/256)=32uS. ' The trick is to preload the counter with a value that will cause it to count ' for 1000mS. Each time the counter expires, you can force the new number back ' into the timer register. We need 1/.000032 or 31250 counts. However, the ' counter expires at 65536, so the correct number to preload is 65536-31250 or ' 34285 This way, the timer will count up 31250 counts (1 second) and ' expire. Const 1000ms = 34285 Config Timer1 = Timer , Prescale = 256 On Timer1 Timer1_int ' Timer Overflow ISR On Urxc Rec_rs232 ' Serial Rx ISR Cls Cursor Off Noblink Time1_count = 0 : Timer1 = 1000ms : Time1_ok = 0 : Spin_c = 0 Start Timer1 Enable Timer1 Enable Interrupts ' Main Program LOOP ' Screen updates rotate every 2 seconds ' T+1 - Latitude ' T+3 - Longitude ' T+5 - Date/Time ' GPS unit polling occurs at ' T+0,T+2,T+4 Do If Time1_ok = 1 Then Read_ok = 0 : Read_num = 0 : Data_ok = 0 Stop Timer1 ' Every even second check GPS If Eventime = 0 Then Gps_date = "" : Gps_time = "" : Latitude = "" : Longitude = "" Gps_state = 0 Gosub Rs232_r Else ' Odd duty cycle tasks (2sec spacing) If Time1_count = 1 Then If North_south = 78 Then ' "N" -> 78 S2 = "North " Else S2 = "South " End If S2 = S2 + Latitude Elseif Time1_count = 3 Then If East_west = 69 Then ' "E" -> 69 S2 = "East " Else S2 = "West " End If S2 = S2 + Longitude Elseif Time1_count = 5 Then S2 = Gps_date + " " + Gps_time End If End If ' Animate symbol to show activity when no valid GPS data found If Gps_state = 0 Then S2 = "No GPS Frame " If Spin_c = 0 Then S2 = S2 + "*" Set Spin_c Else S2 = S2 + "+" Reset Spin_c End If End If Cls Lcd S2 Reset Time1_ok Start Timer1 End If Loop ' Timer interrupt handler Timer1_int: Timer1 = 1000ms Set Time1_ok Incr Time1_count Incr Rs232_exit If Time1_count > 5 Then Time1_count = 0 ' 6sec wrap - 0..5 Eventime = Time1_count.0 Return ' Decode the following string from an Etrex GPS receiver '$GPRMC,103044,A,5125.5210,N,00012.3645,W,0.0,304.9,290105,2.6,W,A*1E '12345678901234567890123456789012345678901234567890123456789012345678 ' 11111111112222222222333333333344444444445555555555666666666 Rec_rs232: Incr Read_num If Udr = 36 Then '"$"-->36 Read_num = 1 : Data_ok = 1 : Temp_j = 0 Elseif Data_ok = 1 Then Select Case Read_num Case 6: If Udr <> 67 Then Data_ok = 0 '"C"-->67 Case 8 To 13: Gps_time = Gps_time + Chr(udr) Case 15: If Udr = 65 Then Gps_state = 1 '"A"-->65 Case 17 To 25: Latitude = Latitude + Chr(udr) Case 27: North_south = Udr ' N/S indicator Case 29 To 38: Longitude = Longitude + Chr(udr) Case 40: East_west = Udr ' E/W indicator ' The next two parameters after E/W indicator are: ' Speed over ground, Course over ground - They vary dynamically in size. Case Is > 40: ' Note: The gps_date var will contain the date plus the trailing comma. ' Start on 3rd comma after E/W indicator If Temp_j = 3 Then Gps_date = Gps_date + Chr(udr) If Udr = 44 Then Incr Temp_j '","-->44 If Temp_j >= 4 Then Read_ok = 1 End Select End If #if Debug ' Display 1st 16 characters after $ (should be a GPS message) ' Note: With this code enabled the interrupt may take too long ' to service URXC and characters can be dropped. If Data_ok = 1 And Read_num < 17 Then Locate 1 , Read_num Lcd Chr(udr) End If #endif Rs232_exit = 0 Return Rs232_r: #if Debug Locate 1 , 1 Lcd "Reading GPS" #endif Reset Usr.7 Reset Ucr.7 Enable Urxc Rs232_exit = 0 ' Don't let the RS232 timeout code affect the next task in the main loop. Time1_store = Time1_count Start Timer1 Do ' The GPS unit sends data every 2secs, so on the 3rd sec if no data has ' been received then stop waiting. If Rs232_exit > 2 Then Exit Do Loop Until Read_ok = 1 Disable Urxc 'disable receive ISR Stop Timer1 Time1_count = Time1_store Return