Está en la página 1de 9

'****************************************************************

'* Name
: UTARC GPS setting Real Time Clock TEST
*
'* Author : Daniel Bowen, Mike Coffey, Carl Lyster
*
'* Notice : Copyright (c) 2007 UTARC www.utarc.org *
'*
: All Rights Reserved
*
'* Date
: 2/20/2007
*
'* Version : 1.0
*
'* Notes : Reads standard NMEA GPS information and sets Real Time Clock chip
to within 5 seconds of GPS time.
'*
:
Clock chip used is serial NJR NJU6355ED, PIC is
18F4620
'*
:
*
'****************************************************************
INCLUDE "MODEDEFS.BAS"
DEFINE OSC 20
DEFINE LOADER_USED 1
DEFINE HSER_BAUD 2400
DEFINE ADC_CLOCK 1
DEFINE ADC_BITS 10
DEFINE ADC_SAMPLEUS 50
SYMBOL LF=$0A
CMCON=$07
ADCON1=%00001100
TRISA=%00110111
TRISB=%01111101
TRISC=%10010100
TRISD=%10010100
TRISE=%00000000
'*** Pin assignments
Red VAR PORTE.0
Green VAR PORTE.1
Yellow VAR PORTE.2
RTCCE VAR PORTC.3
RTCCLK VAR PORTC.2
RTCD VAR PORTC.1
RTCIO VAR PORTC.0
GPSDataPin VAR PORTB.0

'****RTC VARIABLES****
dateTime
VAR byte[7]
YR
VAR dateTime[0]
MO
VAR dateTime[1]
DY
VAR dateTime[2]
DW
VAR dateTime[3]
HR
VAR dateTime[4]
MN
VAR dateTime[5]
SE
VAR dateTime[6]

'Array for the RTC time input


'RTC YEARS AS 2 HEX DIGITS
'RTC MONTH AS 2 HEX DIGITS
'RTC DAYS AS 2 HEX DIGITS
'DAY OF WEEK NOT UESD
'HOURS AS 2 HEX DIGITS
'MINUTES AS 2 HEX DIGITS
'SECONDS AS 2 HEX DIGITS

'***HEX-DEC Conversion Variables***


hexNum
VAR BYTE
'used for converting hex to ascii
decNum
VAR BYTE
'used for converting numbers to decimal integers
'***GPS Variables
gPSBaudMode
gPSSentenceString

CON

24764
VAR

byte[90]

gPSSentenceCheckSumValid
VAR BIT
gPSDataReceived
VAR
BIT
gPSFixValid
VAR
BIT
'value extraction variables
data_String
VAR BYTE[20]
comma_Count
VAR
BYTE
char
VAR
BYTE
charPos
VAR
BYTE
extract_Item
VAR
BYTE
bLoop
VAR
BYTE
i
VAR
Byte
checkSum
VAR
BYTE
numlen
VAR
BYTE
asciiNumber
VAR
WORD
power
var
WORD
gPSSentenceId
VAR
BYTE[5]
LOW
LOW
LOW
LOW

RTCCE
RED
GREEN
YELLOW

START:
GOSUB SETLEDSFORGPS 'Set LED status lights for GPS status
EXTRACT_ITEM = 1 'UTC time
GOSUB extract_the_Value
HSEROUT ["GPS Time: ",dec extract_Item," ",STR data_string,CR,LF]
GOSUB RTCREAD
HSEROUT ["RTC Time: ",HEX HR, HEX MN, HEX SE, CR,LF]
GOSUB SYNCRTCWITHGPS
GOSUB RTCREAD
PrintTimeLoop:
GOSUB readGPS
GOSUB RTCREAD
EXTRACT_ITEM = 1 'UTC time
GOSUB extract_the_Value
HSEROUT ["GPS : ",dec extract_Item," ",STR data_string,CR,LF]
HSEROUT ["RTC: ",HEX HR, " ", HEX MN, " ", HEX SE, CR,LF]
GOTO PrintTimeLoop
END
GOTO START

SYNCRTCWITHGPS:
'This will sync Real Time Clock with the GPS to +/-5s
GOSUB readGPS
EXTRACT_ITEM = 1 'UTC time
GOSUB extract_the_Value
'convert hours, and minutes to hex
'Remove seconds from data string, then send hours/minutes to be converted
GOSUB asciiHextoInteger 'Will truncate to just Min and Sec in asciiNumber
variable
SE = asciiNumber & $00FF 'save seconds
data_string[4] = 0
data_String[5]= 0
GOSUB asciiHextoInteger

MN = asciiNumber & $00FF 'Removes the first two hex digits, Save minutes
HR = asciiNumber >> 8
'Shift hours over to be only digits, save hours
'asciiNumber = asciiNumber >> 8
HSEROUT ["GPS HR: ", HEX HR, " MN: ",HEX MN, " SE: ", HEX SE, CR,LF]
'Increment the minutes to be saved, making sure not to exceed 59.
IF MN = $59 THEN
MN = $0
ELSE
MN = MN + $1 'set minute to the next one just arrived at
ENDIF
'wait for minutes to increment, then sync with RTC
WHILE SE < $55 'Keep Looping until the end of this minute
GOSUB readGPS
EXTRACT_ITEM = 1 'UTC time
GOSUB extract_the_Value
'
GOSUB asciiHextoInteger
'Take ascii text string and convert it to
integer number
SE = asciiNumber & $00FF 'Time in this variable currently only contains
minutes and seconds
'HSEROUT [" ",HEX SE]
WEND
'HSEROUT ["Time to sync! GPS Seconds: ", HEX SE,cr,lf]
SELECT CASE SE
'PAUSE remaining Seconds till next minute, this doesn't
really work very well
CASE 55
PAUSE 4900 'Pause 4.9 seconds
CASE 56
PAUSE 3900 'Pause 3.9 seconds
CASE 57
PAUSE 2900 'Pause 2.9 seconds
CASE 58
PAUSE 1900 'Pause 1.9 seconds
CASE 59
PAUSE 900 'Pause 0.9 seconds
END SELECT
GOSUB RTCSET
RETURN

SETLEDSFORGPS:
gPSSentenceId[0] = "G"
gPSSentenceId[1] = "P"
gPSSentenceId[2] = "G"
gPSSentenceId[3] = "G"
gPSSentenceId[4] = "A"
extract_Item = 6 'Fix good or bad
GOSUB readGPS
GOSUB extract_the_value
GOSUB ASCIIDECTOINTEGER
IF ASCIINUMBER > 0 then
HIGH GREEN
ELSE

'Set Green LED on if there's valid FIX data

LOW GREEN
ENDIF
IF gPSDataReceived = 1 THEN

'Set Yellow LED on if there is valid seria

l data
HIGH YELLOW
ELSE
LOW YELLOW
ENDIF
RETURN
RTCREAD:
'READ THE REAL TIME CLOCK CHIP
LOW RTCCLK
'SET CLOCK LOW
LOW RTCIO
'SET I/O TO READ
HIGH RTCCE
'ENABLE CHIP
SHIFTIN RTCD,RTCCLK,1,[YR\8]
'READ YEAR AS 2 HEX DIGITS
SHIFTIN RTCD,RTCCLK,1,[MO\8]
'READ MONTH AS 2 HEX DIGITS
SHIFTIN RTCD,RTCCLK,1,[DY\8]
'READ DAY OF MONTH AS 2 HEX DIGITS
SHIFTIN RTCD,RTCCLK,1,[DW\4]
'WE WILL NOT USE THE DAY OF WEEK
SHIFTIN RTCD,RTCCLK,1,[HR\8]
'READ HOURS AS 2 HEX DIGITS
SHIFTIN RTCD,RTCCLK,1,[MN\8]
'READ MINS AS 2 HEX DIGITS
SHIFTIN RTCD,RTCCLK,1,[SE\8]
'READ SECONDS AS 2 HEX DIGITS
LOW RTCCE
'DISABLE RTC CHIP
LOW RTCIO
'RTC CHIP TO READ MODE
RETURN
RTCSET:
'SET DATE AND TIME OF
LOW RTCCLK
HIGH RTCIO
HIGH RTCCE
SHIFTOUT RTCD,RTCCLK,0,[YR\8]
SHIFTOUT RTCD,RTCCLK,0,[MO\8]
SHIFTOUT RTCD,RTCCLK,0,[DY\8]
SHIFTOUT RTCD,RTCCLK,0,[0\4]
SHIFTOUT RTCD,RTCCLK,0,[HR\8]
SHIFTOUT RTCD,RTCCLK,0,[MN\8]
'SECONDS SET TO 0
LOW RTCCE
LOW RTCCLK
LOW RTCIO
RETURN
TIMEPROCESSING:
FOR i = 0 to 6'
hexNum = dateTime[i]
GOSUB HEXTOINTEGER
dateTime[i] = decNum
NEXT
RETURN
HEXTOINTEGER:
decNum = (hexNum / 16) * 10
decNum = decNum + (hexNum // 16)
RETURN

RTC CHIP
'SET CLK LOW
'ENABLE WRITE
'SELECT RTC
'YEAR AS 2 HEX DIGITS
'MONTH AS 2 HEX DIGITS
'DAY OF MONTH AS 2 HEX DIGITS
'DAY OF WEEK NOT USED SET TO 0
'HOURS 24 HOUR FORMAT 2 HEX DIGITS
'MINUTES AS 2 HEX DIGITS
AUTOMATICALLY
'DESELECT RTC CHIP
'LOW CLOCK
'RTC IN READ MODE FROM NOW ON
'CLOCK STARTS ON RETURN

'Convert Hex time into Decimal


'copy number into converter var
'Convert hex number to Dec integer

'Get 10s place value of hex representation


'add 10s place to ones place

'******************************************************************************
'FROM HERE ON DOWN, THESE ARE DAN'S UTILITY ROUTINES FOR GPS, AS MODIFIED BY MIK
E

'DO NOT ENTER UNLESS YOU ARE VERY BRAVE!!!


'**************************************************************************
' FUNCTION:
READGPS
' INPUT:
gPSDataPin CON, gPSBaudMode CON,
'
gPSSentenceId BYTE array - GPS Sentence name
'
Serial data stream on gPSDataPin, accepts up to 90 bytes
'
starting with gPSSentenceId, and ending with CRLF
' OUTPUT:
gPSSentenceString BYTE array of requested sentence.
' PURPOSE:
Capture desired GPS sentence from ASCII GPS serial data.
'
Calls functions to verify the sentence checksum.
'**************************************************************************
READGPS:
SERIN2 GPSDataPin, gPSBaudMode, 3000, NoData, [WAITSTR gPSSentenceId\5, STR gPSS
entenceString\90 ]
gpsDataReceived = 1 'Note that we have received serial data from the GPS.
'hserin 3000, NoData, [WAITSTR gPSSentenceId\5, STR gPSSentenceString\90 ]
GOSUB GPSCOMPUTECHECKSUM
GOSUB GPSMATCHCHECKSUM
RETURN
'----[EXTRACT A VALUE BASED ON THE COMMA THAT IT FOLLOWS]---------------------' Locates and extracts the value following the comma placed in EXTRACT_ITEM
' The extracted text is returned in array DATA_STRING with a NULL terminator
' If an invalid value is found, then 000000 will be returned in the array
EXTRACT_THE_VALUE:
FOR i = 0 to 19 STEP 1
DATA_STRING[i] = 0
NEXT
COMMA_COUNT = 0 ' Reset the comma counting variable
CHARPOS = 0 ' Start at the beginning of the array
WHILE CHARPOS < 199
CHAR = gPSSentenceString[CHARPOS] ' Scan the array to parse
If CHAR == "," Then
COMMA_COUNT = COMMA_COUNT + 1
ENDIF ' Increment COMMA_COUNT if a comma is found
If COMMA_COUNT == EXTRACT_ITEM Then ' Have we found the correct comma ?
BLOOP = 0 ' Yes. So....
'
Repeat ' Form a loop
WHILE CHARPOS < 199
CHARPOS = CHARPOS + 1' Skip over the comma and keep scanning the array
CHAR = gPSSentenceString[CHARPOS] ' Extract the pieces of the value into
CHAR
If CHAR = 0 Then Break
If CHAR = "," Then Break
DATA_STRING[BLOOP] = CHAR ' Fill DATA_STRING with the value
BLOOP = BLOOP + 1 ' Point to the next data piece
'
Until CHARPOS >= 199 ' Keep looping until a terminator is found
WEND
DATA_STRING[BLOOP] = 0 ' Add a NULL to DATA_STRING
Endif
CHARPOS = CHARPOS + 1
WEND
BREAK:
Return
GOTO START

'**************************************************************************
' FUNCTION:
ASCIIHEXTOINTEGER
' INPUT:
data_String BYTE array of ASCII HEX number characters
' OUTPUT:
asciiNumber WORD var with hex integer value of ascii
' PURPOSE:
Converts ascii hex string of numbers into integer WORD
'**************************************************************************
ASCIIHEXTOINTEGER:
numlen = 0
asciiNumber = 0
char = 1
While char !=0
char = data_string[numlen]
numlen = numlen +1
WeND
pause 200
power = 1
' Power of ten initially starting with 16^0
'**********************
' This subtracts integer 48 from ascii numerals, which have ascii values
' 0=48 1=49 2=50 etc. Then multiplies it times the place value of that
' number - 1's, 16's, 256's, 4096's etc using increasing powers of 16.
'**********************
for i = numlen-2 to 0 STEP -1
IF data_string[i] > 57 THEN 'ASCII exceeds decimal numbers, must be hex
'subtract 55 from ascii hex letters to get numbers
asciiNumber = asciiNumber + ((data_string[i]-55) * power)
else
asciiNumber = asciiNumber + ((data_string[i]-48) * power)
endif
power = power * 16
NEXT
RETURN

'**************************************************************************
' FUNCTION:
ASCIIDECTOINTEGER
' INPUT:
data_String BYTE array of ASCII decimal number characters
' OUTPUT:
asciiNumber WORD var with integer value of ascii text number
' PURPOSE:
Converts ascii string of decimal numbers into integer WORD
' NOTE:
Will stop when a non-decimal character is encountered.
'**************************************************************************
ASCIIDECTOINTEGER:
numlen = 0
asciiNumber = 0
char = "1"
While (char !=0 AND (char >= "0" AND char <="9"))
char = data_string[numlen]
numlen = numlen +1
WeND
power = 1
' Power of ten initially starting with 10^0
'**********************
' This subtracts integer 48 from ascii numerals, which have ascii values
' 0=48 1=49 2=50 etc. Then multiplies it times the place value of that
' number - 1's, 10's, 100's, 1000's etc using increasing powers of 10.
'**********************
for i = numlen-2 to 0 STEP -1
asciiNumber = asciiNumber + ((data_string[i]-48) * power)

power = power * 10
NEXT
RETURN
'**************************************************************************
' FUNCTION:
GPSCOMPUTECHECKSUM
' INPUT:
gPSSentenceID BYTE array, 5 byte
'
gPSSentenceString BYTE array
' OUTPUT:
checkSum BYTE var, containing computed hex checksum
'
gPSSentenceCheckSumValid BIT var
' PURPOSE:
Computes checksum of GPS Sentence ID plus sentence data.
'
Uses bitwise XOR of each successive character.
'**************************************************************************
GPSCOMPUTECHECKSUM:
Checksum = 0
CHARPOS = 0 'first compute the checksum of the GPS Sentence ID
WHILE CHARPOS < 5
CHAR = gPSSentenceId[charpos]
IF char = 0 THEN FIRSTCHECKDONE
checkSum = checkSum ^ CHAR
'Bitwise XOR checksum
charpos = charpos + 1
WEND
FIRSTCHECKDONE:
'************************
'Compute the checksum of the rest of the sentence
' starting with the checksum from the GPS Sentence ID.
'************************
charPos = 0
WHILE CHARPOS < 80
CHAR = gPSSentenceString[charpos]
IF CHAR = "*" THEN CHECKDONE
IF char = 0 THEN CHECKDONE
checkSum = checkSum ^ CHAR
'Bitwise XOR checksum
charpos = charpos + 1
WEND
CHECKDONE:
RETURN
'**************************************************************************
' FUNCTION:
GPSMATCHCHECKSUM
' INPUT:
gPSSentenceString BYTE array with whole NMEA Sentence
'
checksum BYTE var computed checksum
' OUTPUT:
gPSsentenceCheckSumValid BIT var
' PURPOSE:
Find checksum in NMEA string, starts with asterisk.
'
compares reported checksum to computed checksum
'**************************************************************************
GPSMATCHCHECKSUM:
i=0
char = 1
WHILE char !="*"
'Search for asterisk checksum in array
char = gPSSentenceString[i]
i =i+1
IF char = 0 THEN
GOSUB GpsBadChecksum
'If no * found, abort checking
endif
WEND
data_string[0] = gPSSentenceString[i]
'transfer checksum from discovered
data_string[1] = gPSSentenceString[i+1]
'location.
data_String[2] = 0 'end with null

GOSUB ASCIIHEXTOINTEGER
'converts the ascii hex to integer
IF checksum = asciiNumber THEn
gPSSentenceChecksumValid = 1 'valid
ELSE
GOSUB GpsBadChecksum 'not valid
ENDIF
'HSEROUT ["Converted HEX: ",HEX2 asciiNumber, " Checksum Match: ",DEC gPSSentenc
eChecksumValid, CR]
RETURN
NoData:
gPSDataReceived = 0
HSEROUT ["No Serial data is being received at all!",CR]
RETURN
GpsBadChecksum:
gPSsentenceChecksumValid = 0
HSEROUT ["Corrupted data received from GPS.",CR]
RETURN
GpsNoFix:
gPSFixValid = 0
HSEROUT ["The GPS is working, but we don't have a position fix.",CR]
RETURN
GOTO START

' GPRMC
'RMC = Recommended Minimum Specific GPS/TRANSIT Data
'
'1
= UTC of position fix
'2
= Data status (V=navigation receiver warning)
'3
= Latitude of fix
'4
= N or S
'5
= Longitude of fix
'6
= E or W
'7
= Speed over ground in knots
'8
= Track made good in degrees True
'9
= UT date
'10 = Magnetic variation degrees (Easterly var. subtracts from true course)
'11 = E or W
'12 = Checksum
'****************************************************************************
' GPGGA
'GGA = Global Positioning System Fix Data
'
'1
= UTC of Position
'2
= Latitude
'3
= N or S
'4
= Longitude
'5
= E or W
'6
= GPS quality indicator (0=invalid; 1=GPS fix; 2=Diff. GPS fix)
'7
= Number of satellites in use [not those in view]
'8
= Horizontal dilution of position
'9
= Antenna altitude above/below mean sea level (geoid)

'10 = Meters (Antenna height unit)


'11 = Geoidal separation (Diff. between WGS-84 earth ellipsoid and
'
mean sea level. -=geoid is below WGS-84 ellipsoid)
'12 = Meters (Units of geoidal separation)
'13 = Age in seconds since last update from diff. reference station
'14 = Diff. reference station ID#
'15 = Checksum
'****************************************************************************

También podría gustarte