/ Published in: PicBasic
Messy, yes, but it's available anyway.
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
'**************************************************************** '* 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] 'Array for the RTC time input YR VAR dateTime[0] 'RTC YEARS AS 2 HEX DIGITS MO VAR dateTime[1] 'RTC MONTH AS 2 HEX DIGITS DY VAR dateTime[2] 'RTC DAYS AS 2 HEX DIGITS DW VAR dateTime[3] 'DAY OF WEEK NOT UESD HR VAR dateTime[4] 'HOURS AS 2 HEX DIGITS MN VAR dateTime[5] 'MINUTES AS 2 HEX DIGITS SE VAR dateTime[6] '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 CON 24764 gPSSentenceString 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 RTCCE LOW RED LOW GREEN LOW 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 'Set Green LED on if there's valid FIX data HIGH GREEN ELSE LOW GREEN ENDIF IF gPSDataReceived = 1 THEN 'Set Yellow LED on if there is valid serial 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 RTC CHIP LOW RTCCLK 'SET CLK LOW HIGH RTCIO 'ENABLE WRITE HIGH RTCCE 'SELECT RTC SHIFTOUT RTCD,RTCCLK,0,[YR\8] 'YEAR AS 2 HEX DIGITS SHIFTOUT RTCD,RTCCLK,0,[MO\8] 'MONTH AS 2 HEX DIGITS SHIFTOUT RTCD,RTCCLK,0,[DY\8] 'DAY OF MONTH AS 2 HEX DIGITS SHIFTOUT RTCD,RTCCLK,0,[0\4] 'DAY OF WEEK NOT USED SET TO 0 SHIFTOUT RTCD,RTCCLK,0,[HR\8] 'HOURS 24 HOUR FORMAT 2 HEX DIGITS SHIFTOUT RTCD,RTCCLK,0,[MN\8] 'MINUTES AS 2 HEX DIGITS 'SECONDS SET TO 0 AUTOMATICALLY LOW RTCCE 'DESELECT RTC CHIP LOW RTCCLK 'LOW CLOCK LOW RTCIO 'RTC IN READ MODE FROM NOW ON RETURN 'CLOCK STARTS ON RETURN TIMEPROCESSING: FOR i = 0 to 6' 'Convert Hex time into Decimal hexNum = dateTime[i] 'copy number into converter var GOSUB HEXTOINTEGER 'Convert hex number to Dec integer dateTime[i] = decNum NEXT RETURN HEXTOINTEGER: decNum = (hexNum / 16) * 10 'Get 10s place value of hex representation decNum = decNum + (hexNum // 16) 'add 10s place to ones place RETURN '****************************************************************************** 'FROM HERE ON DOWN, THESE ARE DAN'S UTILITY ROUTINES FOR GPS, AS MODIFIED BY MIKE '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 gPSSentenceString\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 gPSSentenceChecksumValid, 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 '****************************************************************************
URL: http://www.utarc.org/wiki/index.php?title=Source_Code