PicBasic Interfacing PICMicro 18F to RTC and GPS


/ Published in: PicBasic
Save to your folder(s)

Messy, yes, but it's available anyway.


Copy this code and paste it in your HTML
  1. '****************************************************************
  2. '* Name : UTARC GPS setting Real Time Clock TEST *
  3. '* Author : Daniel Bowen, Mike Coffey, Carl Lyster *
  4. '* Notice : Copyright (c) 2007 UTARC www.utarc.org *
  5. '* : All Rights Reserved *
  6. '* Date : 2/20/2007 *
  7. '* Version : 1.0 *
  8. '* Notes : Reads standard NMEA GPS information and sets Real Time Clock chip to within 5 seconds of GPS time.
  9. '* : Clock chip used is serial NJR NJU6355ED, PIC is 18F4620
  10. '* : *
  11. '****************************************************************
  12.  
  13. INCLUDE "MODEDEFS.BAS"
  14. DEFINE OSC 20
  15. DEFINE LOADER_USED 1
  16. DEFINE HSER_BAUD 2400
  17. DEFINE ADC_CLOCK 1
  18. DEFINE ADC_BITS 10
  19. DEFINE ADC_SAMPLEUS 50
  20. SYMBOL LF=$0A
  21. CMCON=$07
  22. ADCON1=%00001100
  23. TRISA=%00110111
  24. TRISB=%01111101
  25. TRISC=%10010100
  26. TRISD=%10010100
  27. TRISE=%00000000
  28.  
  29. '*** Pin assignments
  30. Red VAR PORTE.0
  31. Green VAR PORTE.1
  32. Yellow VAR PORTE.2
  33. RTCCE VAR PORTC.3
  34. RTCCLK VAR PORTC.2
  35. RTCD VAR PORTC.1
  36. RTCIO VAR PORTC.0
  37. GPSDataPin VAR PORTB.0
  38.  
  39.  
  40.  
  41. '****RTC VARIABLES****
  42. dateTime VAR byte[7] 'Array for the RTC time input
  43. YR VAR dateTime[0] 'RTC YEARS AS 2 HEX DIGITS
  44. MO VAR dateTime[1] 'RTC MONTH AS 2 HEX DIGITS
  45. DY VAR dateTime[2] 'RTC DAYS AS 2 HEX DIGITS
  46. DW VAR dateTime[3] 'DAY OF WEEK NOT UESD
  47. HR VAR dateTime[4] 'HOURS AS 2 HEX DIGITS
  48. MN VAR dateTime[5] 'MINUTES AS 2 HEX DIGITS
  49. SE VAR dateTime[6] 'SECONDS AS 2 HEX DIGITS
  50.  
  51. '***HEX-DEC Conversion Variables***
  52. hexNum VAR BYTE 'used for converting hex to ascii
  53. decNum VAR BYTE 'used for converting numbers to decimal integers
  54.  
  55. '***GPS Variables
  56. gPSBaudMode CON 24764
  57. gPSSentenceString VAR byte[90]
  58. gPSSentenceCheckSumValid VAR BIT
  59. gPSDataReceived VAR BIT
  60. gPSFixValid VAR BIT
  61. 'value extraction variables
  62. data_String VAR BYTE[20]
  63. comma_Count VAR BYTE
  64. char VAR BYTE
  65. charPos VAR BYTE
  66. extract_Item VAR BYTE
  67. bLoop VAR BYTE
  68. i VAR Byte
  69. checkSum VAR BYTE
  70. numlen VAR BYTE
  71. asciiNumber VAR WORD
  72. power var WORD
  73. gPSSentenceId VAR BYTE[5]
  74.  
  75.  
  76. LOW RTCCE
  77. LOW RED
  78. LOW GREEN
  79. LOW YELLOW
  80.  
  81. START:
  82.  
  83.  
  84. GOSUB SETLEDSFORGPS 'Set LED status lights for GPS status
  85. EXTRACT_ITEM = 1 'UTC time
  86. GOSUB extract_the_Value
  87. HSEROUT ["GPS Time: ",dec extract_Item," ",STR data_string,CR,LF]
  88. GOSUB RTCREAD
  89. HSEROUT ["RTC Time: ",HEX HR, HEX MN, HEX SE, CR,LF]
  90. GOSUB SYNCRTCWITHGPS
  91. GOSUB RTCREAD
  92. PrintTimeLoop:
  93. GOSUB readGPS
  94. GOSUB RTCREAD
  95. EXTRACT_ITEM = 1 'UTC time
  96. GOSUB extract_the_Value
  97. HSEROUT ["GPS : ",dec extract_Item," ",STR data_string,CR,LF]
  98. HSEROUT ["RTC: ",HEX HR, " ", HEX MN, " ", HEX SE, CR,LF]
  99. GOTO PrintTimeLoop
  100. END
  101. GOTO START
  102.  
  103.  
  104.  
  105. SYNCRTCWITHGPS: 'This will sync Real Time Clock with the GPS to +/-5s
  106. GOSUB readGPS
  107. EXTRACT_ITEM = 1 'UTC time
  108. GOSUB extract_the_Value
  109.  
  110. 'convert hours, and minutes to hex
  111. 'Remove seconds from data string, then send hours/minutes to be converted
  112. GOSUB asciiHextoInteger 'Will truncate to just Min and Sec in asciiNumber variable
  113. SE = asciiNumber & $00FF 'save seconds
  114. data_string[4] = 0
  115. data_String[5]= 0
  116. GOSUB asciiHextoInteger
  117. MN = asciiNumber & $00FF 'Removes the first two hex digits, Save minutes
  118. HR = asciiNumber >> 8 'Shift hours over to be only digits, save hours
  119. 'asciiNumber = asciiNumber >> 8
  120. HSEROUT ["GPS HR: ", HEX HR, " MN: ",HEX MN, " SE: ", HEX SE, CR,LF]
  121.  
  122. 'Increment the minutes to be saved, making sure not to exceed 59.
  123. IF MN = $59 THEN
  124. MN = $0
  125. ELSE
  126. MN = MN + $1 'set minute to the next one just arrived at
  127. ENDIF
  128.  
  129. 'wait for minutes to increment, then sync with RTC
  130. WHILE SE < $55 'Keep Looping until the end of this minute
  131. GOSUB readGPS
  132. EXTRACT_ITEM = 1 'UTC time
  133. GOSUB extract_the_Value '
  134. GOSUB asciiHextoInteger 'Take ascii text string and convert it to integer number
  135. SE = asciiNumber & $00FF 'Time in this variable currently only contains minutes and seconds
  136. 'HSEROUT [" ",HEX SE]
  137. WEND
  138. 'HSEROUT ["Time to sync! GPS Seconds: ", HEX SE,cr,lf]
  139. SELECT CASE SE 'PAUSE remaining Seconds till next minute, this doesn't really work very well
  140. CASE 55
  141. PAUSE 4900 'Pause 4.9 seconds
  142. CASE 56
  143. PAUSE 3900 'Pause 3.9 seconds
  144. CASE 57
  145. PAUSE 2900 'Pause 2.9 seconds
  146. CASE 58
  147. PAUSE 1900 'Pause 1.9 seconds
  148. CASE 59
  149. PAUSE 900 'Pause 0.9 seconds
  150. END SELECT
  151.  
  152.  
  153. GOSUB RTCSET
  154.  
  155. RETURN
  156.  
  157.  
  158.  
  159.  
  160. SETLEDSFORGPS:
  161. gPSSentenceId[0] = "G"
  162. gPSSentenceId[1] = "P"
  163. gPSSentenceId[2] = "G"
  164. gPSSentenceId[3] = "G"
  165. gPSSentenceId[4] = "A"
  166. extract_Item = 6 'Fix good or bad
  167. GOSUB readGPS
  168. GOSUB extract_the_value
  169. GOSUB ASCIIDECTOINTEGER
  170.  
  171. IF ASCIINUMBER > 0 then 'Set Green LED on if there's valid FIX data
  172. HIGH GREEN
  173. ELSE
  174. LOW GREEN
  175. ENDIF
  176.  
  177. IF gPSDataReceived = 1 THEN 'Set Yellow LED on if there is valid serial data
  178. HIGH YELLOW
  179. ELSE
  180. LOW YELLOW
  181. ENDIF
  182. RETURN
  183.  
  184. RTCREAD: 'READ THE REAL TIME CLOCK CHIP
  185. LOW RTCCLK 'SET CLOCK LOW
  186. LOW RTCIO 'SET I/O TO READ
  187. HIGH RTCCE 'ENABLE CHIP
  188. SHIFTIN RTCD,RTCCLK,1,[YR\8] 'READ YEAR AS 2 HEX DIGITS
  189. SHIFTIN RTCD,RTCCLK,1,[MO\8] 'READ MONTH AS 2 HEX DIGITS
  190. SHIFTIN RTCD,RTCCLK,1,[DY\8] 'READ DAY OF MONTH AS 2 HEX DIGITS
  191. SHIFTIN RTCD,RTCCLK,1,[DW\4] 'WE WILL NOT USE THE DAY OF WEEK
  192. SHIFTIN RTCD,RTCCLK,1,[HR\8] 'READ HOURS AS 2 HEX DIGITS
  193. SHIFTIN RTCD,RTCCLK,1,[MN\8] 'READ MINS AS 2 HEX DIGITS
  194. SHIFTIN RTCD,RTCCLK,1,[SE\8] 'READ SECONDS AS 2 HEX DIGITS
  195. LOW RTCCE 'DISABLE RTC CHIP
  196. LOW RTCIO 'RTC CHIP TO READ MODE
  197. RETURN
  198.  
  199. RTCSET: 'SET DATE AND TIME OF RTC CHIP
  200. LOW RTCCLK 'SET CLK LOW
  201. HIGH RTCIO 'ENABLE WRITE
  202. HIGH RTCCE 'SELECT RTC
  203. SHIFTOUT RTCD,RTCCLK,0,[YR\8] 'YEAR AS 2 HEX DIGITS
  204. SHIFTOUT RTCD,RTCCLK,0,[MO\8] 'MONTH AS 2 HEX DIGITS
  205. SHIFTOUT RTCD,RTCCLK,0,[DY\8] 'DAY OF MONTH AS 2 HEX DIGITS
  206. SHIFTOUT RTCD,RTCCLK,0,[0\4] 'DAY OF WEEK NOT USED SET TO 0
  207. SHIFTOUT RTCD,RTCCLK,0,[HR\8] 'HOURS 24 HOUR FORMAT 2 HEX DIGITS
  208. SHIFTOUT RTCD,RTCCLK,0,[MN\8] 'MINUTES AS 2 HEX DIGITS
  209. 'SECONDS SET TO 0 AUTOMATICALLY
  210. LOW RTCCE 'DESELECT RTC CHIP
  211. LOW RTCCLK 'LOW CLOCK
  212. LOW RTCIO 'RTC IN READ MODE FROM NOW ON
  213. RETURN 'CLOCK STARTS ON RETURN
  214.  
  215.  
  216. TIMEPROCESSING:
  217. FOR i = 0 to 6' 'Convert Hex time into Decimal
  218. hexNum = dateTime[i] 'copy number into converter var
  219. GOSUB HEXTOINTEGER 'Convert hex number to Dec integer
  220. dateTime[i] = decNum
  221. NEXT
  222. RETURN
  223.  
  224. HEXTOINTEGER:
  225. decNum = (hexNum / 16) * 10 'Get 10s place value of hex representation
  226. decNum = decNum + (hexNum // 16) 'add 10s place to ones place
  227. RETURN
  228.  
  229.  
  230. '******************************************************************************
  231. 'FROM HERE ON DOWN, THESE ARE DAN'S UTILITY ROUTINES FOR GPS, AS MODIFIED BY MIKE
  232. 'DO NOT ENTER UNLESS YOU ARE VERY BRAVE!!!
  233. '**************************************************************************
  234. ' FUNCTION: READGPS
  235. ' INPUT: gPSDataPin CON, gPSBaudMode CON,
  236. ' gPSSentenceId BYTE array - GPS Sentence name
  237. ' Serial data stream on gPSDataPin, accepts up to 90 bytes
  238. ' starting with gPSSentenceId, and ending with CRLF
  239. ' OUTPUT: gPSSentenceString BYTE array of requested sentence.
  240. ' PURPOSE: Capture desired GPS sentence from ASCII GPS serial data.
  241. ' Calls functions to verify the sentence checksum.
  242. '**************************************************************************
  243. READGPS:
  244. SERIN2 GPSDataPin, gPSBaudMode, 3000, NoData, [WAITSTR gPSSentenceId\5, STR gPSSentenceString\90 ]
  245. gpsDataReceived = 1 'Note that we have received serial data from the GPS.
  246. 'hserin 3000, NoData, [WAITSTR gPSSentenceId\5, STR gPSSentenceString\90 ]
  247. GOSUB GPSCOMPUTECHECKSUM
  248. GOSUB GPSMATCHCHECKSUM
  249. RETURN
  250.  
  251.  
  252. '----[EXTRACT A VALUE BASED ON THE COMMA THAT IT FOLLOWS]----------------------
  253. ' Locates and extracts the value following the comma placed in EXTRACT_ITEM
  254. ' The extracted text is returned in array DATA_STRING with a NULL terminator
  255. ' If an invalid value is found, then 000000 will be returned in the array
  256.  
  257. EXTRACT_THE_VALUE:
  258. FOR i = 0 to 19 STEP 1
  259. DATA_STRING[i] = 0
  260. NEXT
  261. COMMA_COUNT = 0 ' Reset the comma counting variable
  262. CHARPOS = 0 ' Start at the beginning of the array
  263. WHILE CHARPOS < 199
  264. CHAR = gPSSentenceString[CHARPOS] ' Scan the array to parse
  265. If CHAR == "," Then
  266. COMMA_COUNT = COMMA_COUNT + 1
  267. ENDIF ' Increment COMMA_COUNT if a comma is found
  268. If COMMA_COUNT == EXTRACT_ITEM Then ' Have we found the correct comma ?
  269. BLOOP = 0 ' Yes. So....
  270. ' Repeat ' Form a loop
  271. WHILE CHARPOS < 199
  272. CHARPOS = CHARPOS + 1' Skip over the comma and keep scanning the array
  273. CHAR = gPSSentenceString[CHARPOS] ' Extract the pieces of the value into CHAR
  274. If CHAR = 0 Then Break
  275. If CHAR = "," Then Break
  276. DATA_STRING[BLOOP] = CHAR ' Fill DATA_STRING with the value
  277. BLOOP = BLOOP + 1 ' Point to the next data piece
  278. ' Until CHARPOS >= 199 ' Keep looping until a terminator is found
  279. WEND
  280. DATA_STRING[BLOOP] = 0 ' Add a NULL to DATA_STRING
  281.  
  282. Endif
  283. CHARPOS = CHARPOS + 1
  284. WEND
  285. BREAK:
  286. Return
  287. GOTO START
  288.  
  289.  
  290.  
  291. '**************************************************************************
  292. ' FUNCTION: ASCIIHEXTOINTEGER
  293. ' INPUT: data_String BYTE array of ASCII HEX number characters
  294. ' OUTPUT: asciiNumber WORD var with hex integer value of ascii
  295. ' PURPOSE: Converts ascii hex string of numbers into integer WORD
  296. '**************************************************************************
  297. ASCIIHEXTOINTEGER:
  298.  
  299. numlen = 0
  300. asciiNumber = 0
  301. char = 1
  302. While char !=0
  303. char = data_string[numlen]
  304. numlen = numlen +1
  305. WeND
  306. pause 200
  307. power = 1 ' Power of ten initially starting with 16^0
  308. '**********************
  309. ' This subtracts integer 48 from ascii numerals, which have ascii values
  310. ' 0=48 1=49 2=50 etc. Then multiplies it times the place value of that
  311. ' number - 1's, 16's, 256's, 4096's etc using increasing powers of 16.
  312. '**********************
  313. for i = numlen-2 to 0 STEP -1
  314. IF data_string[i] > 57 THEN 'ASCII exceeds decimal numbers, must be hex
  315. 'subtract 55 from ascii hex letters to get numbers
  316. asciiNumber = asciiNumber + ((data_string[i]-55) * power)
  317. else
  318. asciiNumber = asciiNumber + ((data_string[i]-48) * power)
  319. endif
  320. power = power * 16
  321. NEXT
  322. RETURN
  323.  
  324.  
  325.  
  326. '**************************************************************************
  327. ' FUNCTION: ASCIIDECTOINTEGER
  328. ' INPUT: data_String BYTE array of ASCII decimal number characters
  329. ' OUTPUT: asciiNumber WORD var with integer value of ascii text number
  330. ' PURPOSE: Converts ascii string of decimal numbers into integer WORD
  331. ' NOTE: Will stop when a non-decimal character is encountered.
  332. '**************************************************************************
  333. ASCIIDECTOINTEGER:
  334. numlen = 0
  335. asciiNumber = 0
  336. char = "1"
  337. While (char !=0 AND (char >= "0" AND char <="9"))
  338. char = data_string[numlen]
  339. numlen = numlen +1
  340. WeND
  341. power = 1 ' Power of ten initially starting with 10^0
  342. '**********************
  343. ' This subtracts integer 48 from ascii numerals, which have ascii values
  344. ' 0=48 1=49 2=50 etc. Then multiplies it times the place value of that
  345. ' number - 1's, 10's, 100's, 1000's etc using increasing powers of 10.
  346. '**********************
  347. for i = numlen-2 to 0 STEP -1
  348. asciiNumber = asciiNumber + ((data_string[i]-48) * power)
  349. power = power * 10
  350. NEXT
  351. RETURN
  352.  
  353. '**************************************************************************
  354. ' FUNCTION: GPSCOMPUTECHECKSUM
  355. ' INPUT: gPSSentenceID BYTE array, 5 byte
  356. ' gPSSentenceString BYTE array
  357. ' OUTPUT: checkSum BYTE var, containing computed hex checksum
  358. ' gPSSentenceCheckSumValid BIT var
  359. ' PURPOSE: Computes checksum of GPS Sentence ID plus sentence data.
  360. ' Uses bitwise XOR of each successive character.
  361. '**************************************************************************
  362. GPSCOMPUTECHECKSUM:
  363. Checksum = 0
  364. CHARPOS = 0 'first compute the checksum of the GPS Sentence ID
  365. WHILE CHARPOS < 5
  366. CHAR = gPSSentenceId[charpos]
  367. IF char = 0 THEN FIRSTCHECKDONE
  368. checkSum = checkSum ^ CHAR 'Bitwise XOR checksum
  369. charpos = charpos + 1
  370. WEND
  371. FIRSTCHECKDONE:
  372. '************************
  373. 'Compute the checksum of the rest of the sentence
  374. ' starting with the checksum from the GPS Sentence ID.
  375. '************************
  376. charPos = 0
  377. WHILE CHARPOS < 80
  378. CHAR = gPSSentenceString[charpos]
  379. IF CHAR = "*" THEN CHECKDONE
  380. IF char = 0 THEN CHECKDONE
  381. checkSum = checkSum ^ CHAR 'Bitwise XOR checksum
  382. charpos = charpos + 1
  383. WEND
  384. CHECKDONE:
  385. RETURN
  386.  
  387.  
  388. '**************************************************************************
  389. ' FUNCTION: GPSMATCHCHECKSUM
  390. ' INPUT: gPSSentenceString BYTE array with whole NMEA Sentence
  391. ' checksum BYTE var computed checksum
  392. ' OUTPUT: gPSsentenceCheckSumValid BIT var
  393. ' PURPOSE: Find checksum in NMEA string, starts with asterisk.
  394. ' compares reported checksum to computed checksum
  395. '**************************************************************************
  396. GPSMATCHCHECKSUM:
  397. i=0
  398. char = 1
  399. WHILE char !="*" 'Search for asterisk checksum in array
  400. char = gPSSentenceString[i]
  401. i =i+1
  402. IF char = 0 THEN
  403. GOSUB GpsBadChecksum 'If no * found, abort checking
  404. endif
  405. WEND
  406. data_string[0] = gPSSentenceString[i] 'transfer checksum from discovered
  407. data_string[1] = gPSSentenceString[i+1] 'location.
  408. data_String[2] = 0 'end with null
  409. GOSUB ASCIIHEXTOINTEGER 'converts the ascii hex to integer
  410. IF checksum = asciiNumber THEn
  411. gPSSentenceChecksumValid = 1 'valid
  412. ELSE
  413. GOSUB GpsBadChecksum 'not valid
  414. ENDIF
  415. 'HSEROUT ["Converted HEX: ",HEX2 asciiNumber, " Checksum Match: ",DEC gPSSentenceChecksumValid, CR]
  416. RETURN
  417.  
  418. NoData:
  419. gPSDataReceived = 0
  420. HSEROUT ["No Serial data is being received at all!",CR]
  421. RETURN
  422.  
  423. GpsBadChecksum:
  424. gPSsentenceChecksumValid = 0
  425. HSEROUT ["Corrupted data received from GPS.",CR]
  426. RETURN
  427.  
  428. GpsNoFix:
  429. gPSFixValid = 0
  430. HSEROUT ["The GPS is working, but we don't have a position fix.",CR]
  431. RETURN
  432.  
  433.  
  434. GOTO START
  435.  
  436.  
  437.  
  438.  
  439.  
  440. ' GPRMC
  441. 'RMC = Recommended Minimum Specific GPS/TRANSIT Data
  442. '
  443. '1 = UTC of position fix
  444. '2 = Data status (V=navigation receiver warning)
  445. '3 = Latitude of fix
  446. '4 = N or S
  447. '5 = Longitude of fix
  448. '6 = E or W
  449. '7 = Speed over ground in knots
  450. '8 = Track made good in degrees True
  451. '9 = UT date
  452. '10 = Magnetic variation degrees (Easterly var. subtracts from true course)
  453. '11 = E or W
  454. '12 = Checksum
  455. '****************************************************************************
  456. ' GPGGA
  457. 'GGA = Global Positioning System Fix Data
  458. '
  459. '1 = UTC of Position
  460. '2 = Latitude
  461. '3 = N or S
  462. '4 = Longitude
  463. '5 = E or W
  464. '6 = GPS quality indicator (0=invalid; 1=GPS fix; 2=Diff. GPS fix)
  465. '7 = Number of satellites in use [not those in view]
  466. '8 = Horizontal dilution of position
  467. '9 = Antenna altitude above/below mean sea level (geoid)
  468. '10 = Meters (Antenna height unit)
  469. '11 = Geoidal separation (Diff. between WGS-84 earth ellipsoid and
  470. ' mean sea level. -=geoid is below WGS-84 ellipsoid)
  471. '12 = Meters (Units of geoidal separation)
  472. '13 = Age in seconds since last update from diff. reference station
  473. '14 = Diff. reference station ID#
  474. '15 = Checksum
  475. '****************************************************************************

URL: http://www.utarc.org/wiki/index.php?title=Source_Code

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.