Code:
;
;
; PIC16F876a
; __________
; !MCLR |1 28| RB7------D7
; PLL Volt--AN0---RA0 |2 27| RB6------D6
; Temp--AN1---RA1 |3 26| RB5------D5
; AN2---RA2 |4 25| RB4------D4
; AN3---RA3 |5 24| RB3------LCD E
; NMEA data---RA4 |6 23| RB2------LCD RS
; AN4---RA5 |7 22| RB1------
; Ground---Vss |8 21| RB0------
; OSC1---XTAL |9 20| VDD------ +5 V
; OSC2---XTAL |10 19| Vss------Ground
; ---RC0 |11 18| RC7------
; ---RC1 |12 17| RC6------
; ---RC2 |13 16| RC5------
; pbutton---RC3 |14 15| RC4------
; ----------
;
;
;====================================================================='
' Program to display returned value of a GPS on RA4
' LCD in 4-BIT mode PIC16F876a controller 4Mhz clock Fuse PWRT BODEN
'
'GPS sentence: $GPRMC,192144.62,A,5041.6058,N,00412.6124,E,0.45,3 57.74,081205,,*0B
@ __config _HS_OSC & _WDT_ON & _PWRTE_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF
;-- Place a copy of these variables in your Main program -------------------
;-- The compiler will tell you which lines to un-comment --
;-- Do Not un-comment these lines --
;---------------------------------------------------------------------------
;wsave VAR BYTE $20 SYSTEM ' location for W if in bank0
wsave VAR BYTE $70 SYSTEM ' alternate save location for W
' if using $70, comment wsave1-3
' --- IF any of these three lines cause an error ?? ------------------------
' Comment them out to fix the problem ----
' -- Which variables are needed, depends on the Chip you are using --
'wsave1 VAR BYTE $A0 SYSTEM ' location for W if in bank1
'wsave2 VAR BYTE $120 SYSTEM ' location for W if in bank2
;wsave3 VAR BYTE $1A0 SYSTEM ' location for W if in bank3
' --------------------------------------------------------------------------
INCLUDE "FP20.bas" ; 24-bit Floating Point for 14-bit cores with RAM at $20
Define LCD_DREG PORTB ' Port for LCD Data
Define LCD_DBIT 4 ' Set LCD starting data bit
Define LCD_RSREG PORTB ' Port for RegisterSelect (RS) bit
Define LCD_RSBIT 2 ' Port Pin for RS bit (pin9)
Define LCD_EREG PORTB ' Port for Enable (E) bit
Define LCD_EBIT 3 ' Port Pin for E bit (pin7)
Define LCB_BITS 4 ' Using 4-bit bus
Define LCD_COMMANDUS 1500 ' Command Delay (uS)
define LCD_DATAUS 50 ' Data Delay (uS)
DEFINE OSC 4
OPTION_REG.7=0 ' Enable Pull-Up's
GPSin VAR PORTA.4
Pbutton VAR PORTC.3
' Initialise ADC
ADCON1 = %10000100 ' Set PORTA analog and RIGHT justify result
ADCON0 = %01000001 ' Configure and turn on A/D Module channel 0 Fosc 8
PAUSE 500
'Declare variables
val VAR WORD ' final calculated adc valuesWORD' final calculated adc values
volt VAR WORD ' scaled value real part
voltd1 VAR WORD ' scaled value first decimal place
voltd2 VAR WORD ' scaled value second decimal place
i var byte ' counter
'Allocate Variables for GPS:
TimeOut CON 2000
hh VAR BYTE 'hours
mm VAR BYTE 'minutes
ss VAR BYTE 'seconds
knots VAR WORD 'speed in knots (units)
knotsten VAR BYTE 'speed in knots (tens)
course VAR WORD 'heading
latdeg VAR BYTE 'degrees latitude
latmin VAR BYTE 'minutes latitude
latsecs VAR BYTE 'seconds latitude
NS VAR BYTE 'north or south
londeg VAR BYTE 'degrees longitude
lonmin VAR BYTE 'minutes longitude
lonsecs VAR BYTE 'seconds longtitude
EW VAR BYTE 'east or west
d VAR BYTE 'day
m VAR BYTE 'month
y VAR BYTE 'year
butt VAR BYTE 'pushbutton variable
marker VAR BYTE 'toggle marker
MH VAR BYTE[6]
LonMinDec VAR BYTE
LonDir VAR BYTE
LatMinDec VAR BYTE
LatDir VAR BYTE
nPos var byte
nDig var byte
fix VAR WORD 'GPS fix
LCDOut $fe,$80," GPS Decoder "
LCDOut $FE,$c0," G8VLQ March 2014 "
Pause 3000
LCDOut $FE, 1 'Clear Screen
butt = 0
marker = 0
GPS: 'read GPS #############################################################################################
SerIn2 GPSin,188,Timeout,Clock,[wait("$GPRMC"),wait(","),DEC2 hh,DEC2 mm,DEC2 ss,wait(","),fix,wait(",")_
,DEC2 latdeg,DEC2 latmin,wait("."),DEC2 latsecs,wait(","),NS,wait(","),DEC3 londeg,DEC2 lonmin,wait("."),DEC2 lonsecs,_
wait(","),EW,wait(","),knots,wait("."),DEC2 knotsten,wait(","),DEC3 course,wait(","),DEC2 d,DEC2 m,DEC2 y]
IF marker = 1 THEN BigClock
LonMinDec = lonmin
LatMinDec = latmin
LonDir = EW
LatDir = NS
BUTTON Pbutton,0,100,0,butt,1,BigClockClear
If m = 01 then gosub January ; show month
If m = 02 then gosub February
If m = 03 then gosub March
If m = 04 then gosub April
If m = 05 then gosub May
If m = 06 then gosub June
If m = 07 then gosub July
If m = 08 then gosub August
If m = 09 then gosub September
If m = 10 then gosub October
If m = 11 then gosub November
If m = 12 then gosub December
gosub PLL ;pll control voltage
GOSUB Locator ;maidenhead locator
GOSUB Clock ;Large digit clock
goto GPS ; ##########################################################################################
;-------------------------------------------------------------
PLL:
Val = 0 ' Value returned is the average of 5 conversions
For i = 0 TO 4
ADCON0.2 = 1 ' Start conversion
NotDone:
pause 1
IF ADCON0.2 = 1 Then NotDone
val = val + ((ADRESH * 256)+(ADRESL))
nEXT I
VAL = VAL/5
' Calculate Voltage to 2 decimal places
volt = val * 5/1024
voltd1 = ( val * 5//1024) * 10/1024
Voltd2 = ((val *5 //1024) * 10//1024) * 10/1024
RETURN
;---------------------------------------------
Locator:
;----[convert Longitude Sexagesimal to Decimal Degrees]-------------------------
Aint = LonMinDec : GOSUB ItoFA ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB ; divided by 100
GOSUB fpdiv
Bint = LonMin : GOSUB ItoFB ; add whole portion of Minutes
GOSUB fpadd
Bint = 60 : GOSUB ItoFB ; divide by 60
GOSUB fpdiv
Bint = LonDeg : GOSUB ItoFB ; add degrees
GOSUB fpadd
IF LonDir = "W" THEN ; if west of Prime Meridian
GOSUB AtoB
Aint = 0 : GOSUB ItoFA ; subtract from 0 to negate
GOSUB fpsub
ENDIF
Bint = 180 : GOSUB ItoFB ; add 180
GOSUB fpadd
;----[Have Longitude in AARG as Float]------------------------------------------
GOSUB SaveLon ; save Longitude for later
Bint = 20 : GOSUB ItoFB ; Lon / 20
GOSUB fpdiv
GOSUB SaveAARG ; save AARG for modulus
GOSUB FtoIA ; get integer
MH(0) = "A" + Aint ; + "A" = First character
; -- do Lon // 20 --- (modulus)
Bint = Aint ; copy integer result to BARG
GOSUB ItoFB ; convert it to float
GOSUB RestoreAARG ; restore Lon / 20 to AARG
GOSUB fpsub ; subtract integer
Bint = 20 ; multiply times original divisor (20)
GOSUB ItoFB
GOSUB fpmul ; AARG now contains the modulus
Bint = 2 : GOSUB ItoFB ; divide modulus by 2
GOSUB fpdiv
GOSUB FtoIA ; get integer
MH(2) = "0" + Aint ; + "0" = Third character
GOSUB RestoreLon ; restore Longitude
Bint = 2 : GOSUB ItoFB
GOSUB fpdiv ; divide by 2
GOSUB FtoIA ; get integer
Bint = Aint * 2 : GOSUB ItoFB ; put int * 2 in BARG, change back to float
GOSUB RestoreLon ; restore original Longitude
GOSUB fpsub ; subtract A - B
Bint = 12 : GOSUB ItoFB ; Multiply * 12
GOSUB fpmul
GOSUB FtoIA ; get integer
MH(4) = "a" + Aint ; + "a" = Fifth Character
;----[convert Latitude Sexagesimal to Decimal Degrees]--------------------------
Aint = LatMinDec : GOSUB ItoFA ; decimal portion of Minutes
Bint = 100 : GOSUB ItoFB ; divided by 100
GOSUB fpdiv
Bint = LatMin : GOSUB ItoFB ; add whole portion of Minutes
GOSUB fpadd
Bint = 60 : GOSUB ItoFB ; divide by 60
GOSUB fpdiv
Bint = LatDeg : GOSUB ItoFB ; add degrees
GOSUB fpadd
IF LatDir = "S" THEN ; if south of equator
GOSUB AtoB
Aint = 0 : GOSUB ItoFA ; subtract from 0 to negate
GOSUB fpsub
ENDIF
Bint = 90 : GOSUB ItoFB ; add 90
GOSUB fpadd
;----[Have Latitude in AARG as Float]------------------------------------------
GOSUB SaveLon ; save Latitude for later
Bint = 10 : GOSUB ItoFB ; Lat / 10
GOSUB fpdiv
GOSUB SaveAARG ; save AARG for modulus
GOSUB FtoIA
MH(1) = "A" + Aint ; + "A" = Second character
; -- do Lat // 10 --- (modulus)
Bint = Aint ; copy integer result to BARG
GOSUB ItoFB ; convert it to float
GOSUB RestoreAARG ; restore Lat / 10 to AARG
GOSUB fpsub ; subtract integer
Bint = 10 ; multiply times original divisor (10)
GOSUB ItoFB
GOSUB fpmul ; AARG now contains the modulus
GOSUB FtoIA
MH(3) = "0" + Aint ; + "0" = Fourth character
GOSUB RestoreLon ; restore original Latitude
GOSUB FtoIA ; get integer
Bint = Aint : GOSUB ItoFB ; put int in BARG, change back to float
GOSUB RestoreLon ; restore original Latitude
GOSUB fpsub ; subtract A - B
Bint = 24 : GOSUB ItoFB ; Multiply * 24
GOSUB fpmul
GOSUB FtoIA ; get integer
MH(5) = "a" + Aint ; + "a" = Sixth character
;----[Maidenhead conversion complete]-------------------------------------------
RETURN
;-------------------------------------------------------------------------------
Aexp_Copy VAR BYTE
AARGB0_Copy VAR BYTE
AARGB1_Copy VAR BYTE
AARGB2_Copy VAR BYTE
Aexp_Lon VAR BYTE
AARGB0_Lon VAR BYTE
AARGB1_Lon VAR BYTE
AARGB2_Lon VAR BYTE
SaveAARG:
Aexp_Copy = Aexp
AARGB0_Copy = AARGB0
AARGB1_Copy = AARGB1
AARGB2_Copy = AARGB2
RETURN
RestoreAARG:
Aexp = Aexp_Copy
AARGB0 = AARGB0_Copy
AARGB1 = AARGB1_Copy
AARGB2 = AARGB2_Copy
RETURN
AtoB:
Bexp = Aexp
BARGB0 = AARGB0
BARGB1 = AARGB1
BARGB2 = AARGB2
RETURN
SaveLon:
Aexp_Lon = Aexp
AARGB0_Lon = AARGB0
AARGB1_Lon = AARGB1
AARGB2_Lon = AARGB2
RETURN
RestoreLon:
Aexp = Aexp_Lon
AARGB0 = AARGB0_Lon
AARGB1 = AARGB1_Lon
AARGB2 = AARGB2_Lon
RETURN
;---------------------------------------
January:
LCDOut $fe,$80+9,DEC2 d," Jan ","20",DEC2 y
RETURN
February:
LCDOut $fe,$80+9,DEC2 d," Feb ","20",DEC2 y
RETURN
March:
LCDOut $fe,$80+9,DEC2 d," Mar ","20",DEC2 y
RETURN
April:
LCDOut $fe,$80+9,DEC2 d," Apr ","20",DEC2 y
RETURN
May:
LCDOut $fe,$80+9,DEC2 d," May ","20",DEC2 y
RETURN
June:
LCDOut $fe,$80+9,DEC2 d," Jun ","20",DEC2 y
RETURN
July:
LCDOut $fe,$80+9,DEC2 d," Jul ","20",DEC2 y
RETURN
August:
LCDOut $fe,$80+9,DEC2 d," Aug ","20",DEC2 y
RETURN
September:
LCDOut $fe,$80+9,DEC2 d," Sep ","20",DEC2 y
RETURN
October:
LCDOut $fe,$80+9,DEC2 d," Oct ","20",DEC2 y
RETURN
November:
LCDOut $fe,$80+9,DEC2 d," Nov ","20",DEC2 y
RETURN
December:
LCDOut $fe,$80+9,DEC2 d," Dec ","20",DEC2 y
RETURN
;--------------------------------------------------------------------------
ClockClear:
LCDOut $FE, 1 'Clear Screen
marker = 0
GOTO GPS
Clock:
;Display time
'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
LCDOUT $FE,$40,$03,$03,$03,$03,$03,$03,$03,$03 ' Cust Char #0
LCDOUT $FE,$48,$1F,$1F,$1B,$1B,$1B,$1B,$1B,$1B ' Cust Char #1
LCDOUT $FE,$50,$1F,$1F,$18,$18,$18,$18,$1F,$1F ' Cust Char #2
LCDOUT $FE,$58,$03,$03,$03,$03,$03,$03,$1F,$1F ' Cust Char #3
LCDOUT $FE,$60,$1F,$1F,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #4
LCDOUT $FE,$68,$1B,$1B,$1B,$1B,$1B,$1B,$1F,$1F ' Cust Char #5
LCDOUT $FE,$70,$1F,$1F,$03,$03,$03,$03,$1F,$1F ' Cust Char #6
LCDOUT $FE,$78,$1F,$1F,$03,$03,$03,$03,$03,$03 ' Cust Char #7
nDig=hh dig 1 : nPos=0 : gosub displaydigit
nDig=hh dig 0 : nPos=1 : gosub displaydigit
npos=2 : gosub colon
ndig=mm dig 1 : npos=3 : gosub displaydigit
ndig=mm dig 0 : npos=4 : gosub displaydigit
npos=5 : gosub colon
ndig=ss dig 1 : npos=6 : gosub displaydigit
ndig=ss dig 0 : npos=7 : gosub displaydigit
LCDOut $fe,$c0+9," ",#volt, ".", # voltd1,# voltd2,"v"
LCDOUT $fe,$94," G8VLQ ",STR MH\6
LCDOut $fe,$d4,DEC2 latdeg,$DF,DEC2 latmin,"'",DEC2 latsecs,NS," ",DEC2 londeg,$DF,DEC2 lonmin,"'",DEC2 lonsecs,EW ; ,#volt, ".", # voltd1,# voltd2,"v" ; d4 4th line
RETURN
displaydigit:
if ndig=0 then gosub zero
if ndig=1 then gosub one
if ndig=2 then gosub two
if ndig=3 then gosub three
if ndig=4 then gosub four
if ndig=5 then gosub five
if ndig=6 then gosub six
if ndig=7 then gosub seven
if ndig=8 then gosub eight
if ndig=9 then gosub nine
return
Zero:
LCDOUT $FE,$80+nPos,1
LCDOUT $FE,$C0+nPos,5
return
One:
LCDOUT $FE,$80+nPos,0
LCDOUT $FE,$C0+nPos,0
return
Two:
LCDOUT $FE,$80+nPos,7
LCDOUT $FE,$C0+nPos,2
return
Three:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$C0+nPos,3
return
Four:
LCDOUT $FE,$80+nPos,5
LCDOUT $FE,$C0+nPos,0
return
Five:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$C0+nPos,3
return
Six:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$C0+nPos,5
return
Seven:
LCDOUT $FE,$80+nPos,7
LCDOUT $FE,$C0+nPos,0
return
Eight:
LCDOUT $FE,$80+nPos,4
LCDOUT $FE,$C0+nPos,5
return
Nine:
LCDOUT $FE,$80+nPos,4
LCDOUT $FE,$C0+nPos,3
return
colon:
lcdout $fe,$80+nPos,$A5
lcdout $FE,$C0+nPos,$A5
return
;---------------------------------------------------------------------------
BigClockClear:
LCDOut $FE, 1 'Clear Screen
marker = 1
BigClock:
'Set up the digits (http://www.darreltaylor.com/files/CustChar.htm)
LCDOUT $FE,$40,$07,$07,$07,$07,$07,$07,$07,$07 ' Cust Char #0
LCDOUT $FE,$48,$1C,$1C,$1C,$1C,$1C,$1C,$1C,$1C ' Cust Char #1
LCDOUT $FE,$50,$03,$07,$0F,$1E,$1C,$1C,$1C,$1C ' Cust Char #2
LCDOUT $FE,$58,$18,$1C,$1E,$0F,$07,$07,$07,$07 ' Cust Char #3
LCDOUT $FE,$60,$1C,$1C,$1C,$1C,$1E,$0F,$07,$03 ' Cust Char #4
LCDOUT $FE,$68,$07,$07,$07,$07,$0F,$1E,$1C,$18 ' Cust Char #5
LCDOUT $FE,$70,$1F,$1F,$1F,$00,$00,$00,$00,$00 ' Cust Char #6
LCDOUT $FE,$78,$00,$00,$00,$00,$00,$1F,$1F,$1F ' Cust Char #7
BUTTON Pbutton,0,100,0,butt,1,ClockClear
;Display time
nDig=hh dig 1 : nPos=0 : gosub displaydigit1
nDig=hh dig 0 : nPos=3 : gosub displaydigit1
npos=6 : gosub colon1
ndig=mm dig 1 : npos=7 : gosub displaydigit1
ndig=mm dig 0 : npos=10 : gosub displaydigit1
npos=13 : gosub colon1
ndig=ss dig 1 : npos=14 : gosub displaydigit1
ndig=ss dig 0 : npos=17 : gosub displaydigit1
GOTO GPS
displaydigit1:
if ndig=0 then gosub Zero1
if ndig=1 then gosub One1
if ndig=2 then gosub Two1
if ndig=3 then gosub Three1
if ndig=4 then gosub Four1
if ndig=5 then gosub Five1
if ndig=6 then gosub Six1
if ndig=7 then gosub Seven1
if ndig=8 then gosub Eight1
if ndig=9 then gosub Nine1
RETURN
Zero1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,1
LCDOUT $FE,$C1+nPos,0
LCDOUT $FE,$94+nPos,1
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,5
RETURN
One1:
LCDOUT $FE,$80+nPos," "
LCDOUT $FE,$81+nPos,0
LCDOUT $FE,$C0+nPos," "
LCDOUT $FE,$C1+nPos,0
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos," "
LCDOUT $FE,$D5+nPos,0
RETURN
Two1:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,7
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos,1
LCDOUT $FE,$95+nPos," "
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,7
RETURN
Three1:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,7
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,7
LCDOUT $FE,$D5+nPos,5
RETURN
Four1:
LCDOUT $FE,$80+nPos,1
LCDOUT $FE,$81+nPos," "
LCDOUT $FE,$C0+nPos,4
LCDOUT $FE,$C1+nPos,7
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,1
LCDOUT $FE,$D4+nPos," "
LCDOUT $FE,$D5+nPos,1
RETURN
Five1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,6
LCDOUT $FE,$C0+nPos,1
LCDOUT $FE,$C1+nPos," "
LCDOUT $FE,$94+nPos,6
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,7
LCDOUT $FE,$D5+nPos,5
RETURN
Six1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,6
LCDOUT $FE,$C0+nPos,1
LCDOUT $FE,$C1+nPos," "
LCDOUT $FE,$94+nPos,2
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,5
RETURN
Seven1:
LCDOUT $FE,$80+nPos,6
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos," "
LCDOUT $FE,$C1+nPos,0
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos," "
LCDOUT $FE,$D5+nPos,0
RETURN
Eight1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,4
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos,2
LCDOUT $FE,$95+nPos,3
LCDOUT $FE,$D4+nPos,4
LCDOUT $FE,$D5+nPos,5
RETURN
Nine1:
LCDOUT $FE,$80+nPos,2
LCDOUT $FE,$81+nPos,3
LCDOUT $FE,$C0+nPos,4
LCDOUT $FE,$C1+nPos,5
LCDOUT $FE,$94+nPos," "
LCDOUT $FE,$95+nPos,0
LCDOUT $FE,$D4+nPos,7
LCDOUT $FE,$D5+nPos,5
RETURN
colon1:
LCDOUT $FE,$C0+nPos,$A5
LCDOUT $FE,$94+nPos,$A5
RETURN
Bookmarks