Interface with a Dallas DS1602 Elapsed Time Counter

copyright, Peter H Anderson, Baltimore, MD, May, '04


Program DS1602_1.Bas illustrates all of the capabilities of the DS1602 elapsed time counter.

A discussion will follow.

Program DS1602_2.Bas uses the DS1602 to perform the timing when periodic tasks are to be performed. For example, performing a data measurement sequence every hour.

Another future application is an event logger where when an event occurs, the elapsed time is fetched from the DS1602 and logged to EEPROM.


' DS1602_1.BAS
'
' Illustrates how to interface with DS1602 3-Wire Elapsed Time Counter
'
' Sets Oscillator Trim to mid scale.
'
' Clears Continuous and Vcc counter (32-bits).  After nominally 60 seconds
' the Vcc counter is read and displayed.  After another 60 seconds, the
' continuous counter is read and displayed.
'
' Both counters are preloaded with values and after periods of time, they are
' read and displayed.
'
'
' PICAXE-18X                             DS1602
'
' Out2 (term 8) ----- 4.7K ----------- DQ (term 2)
'                           |
' Input6 (term 15)----------
' Out1 (term 7) ---------------------- CLK (term 3)
' Out0 (term 6) ---------------------- RST (term 1)
'

'
' Copyright, Peter H. Anderson, Baltimore, MD
'
    Symbol HiCount = W0
    Symbol LoCount = W1

    Symbol OSCTrim = B4
    Symbol Counter = B4

    Symbol OByte = B5
	Symbol LSBit = B6

    Symbol IByte = B7

    Symbol N = B8

    Symbol RST = 0
    Symbol CLK = 1
    Symbol DQOut = 2
    Symbol DQIn = Pin6

    Symbol CONT_CNTR = 0     ' continuous counter
    Symbol V_CC_CNTR = 1    ' V_cc counter

    ' DS1602 commands
    Symbol SetTrimBits = $C0
    Symbol ClrContinuousCounter = $04
    Symbol ClrVccCounter = $02
    Symbol ReadContinuousCounter = $81
    Symbol ReadVccCounter = $41
    Symbol WriteContinuousCounter = $80
    Symbol WriteVccCounter = $40

    Pause 6000


Main:
	OSCTrim = $03
	GoSub SetOSCTrim	' adjust oscillator trim to nominal

	Counter = CONT_CNTR	' clear continuous counter
	GoSub ClearCounter

	Counter = V_CC_CNTR	' clear V_cc counter
	Gosub ClearCounter

	Pause 60000		' pause for a minute

	Counter = CONT_CNTR	' read and display count from continuous
	GoSub ReadCounter	' counter

	SerTxD (#HiCount, "  ", #LoCount, 13, 10)

	Pause 60000		' wait some more time to let counter count

	Counter = V_CC_CNTR	' read and display count from V_cc counter
	GoSub ReadCounter

	SerTxD (#HiCount, "  ", #LoCount, 13, 10)

	HiCount = 34567
	LoCount = 45678

	Counter = CONT_CNTR	' write a value to each counter
	GoSub WriteCounter

	HiCount = 43210
	LoCount = 54321

	Counter = V_CC_CNTR
	GoSub WriteCounter

	Pause 60000		' pause for a minute

	Counter = CONT_CNTR	' read and display count from continuous
	GoSub ReadCounter	' counter

	SerTxD (#HiCount, "  ", #LoCount, 13, 10)

	Pause 60000		' wait some more time

	Counter = V_CC_CNTR	' read and display count from V_cc counter
	GoSub ReadCounter

	SerTxD (#HiCount, "  ", #LoCount, 13, 10)
Done:
	Goto Done

SetOSCTrim:	' sets trim of osc to value contained in osc_trim

	GoSub BeginSequence
	OByte = OSCTrim * 8
	OByte = OByte | SetTrimBits	' 11 OSC2 OSC1 OSC0 X X 0
	GoSub OutByte
	GoSub EndSequence
	Return

ClearCounter:  	' clears specified counter, $04 - continuous counter
					  ' $02 - V_cc counter
	LookUp Counter, (ClrContinuousCounter, ClrVccCounter), OByte
	Gosub BeginSequence
    LookUp Counter, (ClrContinuousCounter, ClrVccCounter), OByte
    GoSub OutByte
    GoSub EndSequence
    Return

ReadCounter:	' reads 32 bits from specified counter
		' result placed in hi_count and lo_count

	GoSub BeginSequence
	LookUp Counter, (ReadContinuousCounter, ReadVccCounter), OByte
      GoSub OutByte

	'now shift in 32 bits beginning with least significant bit

	GoSub GetByte
	LoCount = IByte		'lo byte of lo word
	Gosub GetByte
	LoCount = Ibyte * 256 | LoCount  'hi byte of lo word

	GoSub GetByte
	HiCount = IByte		'lo byte of hi word
	Gosub GetByte
	HiCount = Ibyte * 256 | HiCount  'hi byte of hi word


	GoSub EndSequence
	Return

WriteCounter:	' writes 32 bits contained in HiCount and LoCount
		' to specified counter, beginning with least sig bit

	GoSub BeginSequence
	LookUp Counter, (WriteContinuousCounter, WriteVccCounter), OByte
      GoSub OutByte
	'now shift out 32 bits beginning with least significant bit

	OByte = LoCount % 256	' lo byte of lo word
	Gosub OutByte
	OByte = LoCount / 256   ' hi byte of lo word
	GoSub OutByte

	OByte = HiCount % 256	' lo byte of hi word
	Gosub OutByte
	OByte = HiCount / 256   ' hi byte of hi word
	GoSub OutByte

	GoSub EndSequence
	Return


OutByte:                ' outputs byte in o_byte, beginning with least
			            ' significant bit
    For N = 0 to 7
       LSBit = OByte & $01
       If LSBit = 1 Then OutByte_1
       ' else
       Low DQOut
       GoTo OutByte_2

OutByte_1:
       High DQOut
       GoTo OutByte_2

OutByte_2:
       Low CLK
	   High CLK
       OByte = OByte / 2      'shift data 1 place right
    Next
	Return

GetByte:		' reads 8 bits from DS1602 beginning with least
			    ' significant bit
    High DQOut
    For N = 0 to 7
       Low CLK
       IByte = IByte / 2

       If DQIn = 0 Then GetByte_1
       ' else
       IByte = IByte | $80
       SerTxd ("0")
       GoTo GetByte_2
GetByte_1:
       SerTxD ("1")
GetByte_2:
       High CLK
    Next
    SerTxD (13, 10)
    Return

BeginSequence:
	Low RST
    High CLK
    High RST 	' initiate by bringing RST high
	Return

EndSequence:
	High CLK
	Low RST
	Return


' DS1602_2.BAS
'
' Illustrates how to interface with DS1602 3-Wire Elapsed Time Counter to
' perform timing between performing events.  In this case an LED is operated after
' 73 seconds.  It is then turned off 24 secs later.  This is continually repeated.
'
' This could be extended to a far more complex sequence.
'
' Realistic times were used for verifying the operation.  However, this could be
' extended to any value up to 2^32 secs, or about 104 years!
'
' Sets Oscillator Trim to mid scale.
'
' Writes 2s compliment of 73 to continuous counter. $ffff $ffb7.
'
' Processor then does other things, periodically reading the countinuous counter.
' If the HiWord is $0000, there was a rollover and the LED is turned on.  The LoCount
' is read and the 2s  compliment of 24 - current count is written to LoCount and $ffff
' is written to HiCount.
'
' Note that for 12 hours the values are $ffff $5740
' For one day $fffe $ae80
'
' A typical application might be to turn on a lamp every 24 hours for 3 hours.
'
'
' PICAXE-18X                             DS1602
'
' Out2 (term 8) ----- 4.7K ----------- DQ (term 2)
'                           |
' Input6 (term 15)----------
' Out1 (term 7) ---------------------- CLK (term 3)
' Out0 (term 6) ---------------------- RST (term 1)
'

'
' Copyright, Peter H. Anderson, Baltimore, MD, May, '04
'
      Symbol HiCount = W0
      Symbol LoCount = W1

      Symbol OSCTrim = B4
      Symbol Counter = B4

      Symbol OByte = B5
      Symbol LSBit = B6

      Symbol IByte = B7

      Symbol N = B8

      Symbol RST = 0
      Symbol CLK = 1
      Symbol DQOut = 2
      Symbol DQIn = Pin6

      Symbol LED = 7

      Symbol CONT_CNTR = 0     ' continuous counter
      Symbol V_CC_CNTR = 1    ' V_cc counter

      ' DS1602 commands
      Symbol SetTrimBits = $C0
      Symbol ClrContinuousCounter = $04
      Symbol ClrVccCounter = $02
      Symbol ReadContinuousCounter = $81
      Symbol ReadVccCounter = $41
      Symbol WriteContinuousCounter = $80
      Symbol WriteVccCounter = $40

      Pause 6000		' used for debugging
Main:

      Low LED		' be sure LED is off

      OSCTrim = $03
      GoSub SetOSCTrim	' adjust oscillator trim to nominal

      HiCount = $ffff		' 2s compliment of 73 secs
      LoCount = $ffb7

      Counter = CONT_CNTR	' write a value to each counter
      GoSub WriteCounter

Main_1:
      ' now perform other tasks
      Pause 1000
      SerTxD (".")

      Counter = CONT_CNTR	' read and display count from continuous
      GoSub ReadCounter	' counter

      If HiCount <> 0 Then Main_1
      ' else
      LoCount = 24 - LoCount
      LoCount = LoCount ^ $ffff + 1
      HiCount = $ffff

      Counter = CONT_CNTR	' write a value to each counter
      GoSub WriteCounter

      High LED		' turn on the LED
Main_2:
      ' now perform other tasks
      Pause 3000
      SerTxD ("!")

      Counter = CONT_CNTR	' read and display count from continuous
      GoSub ReadCounter	' counter

      If HiCount <> 0 Then Main_2
      ' else
      LoCount = 73 - LoCount
      LoCount = LoCount ^ $ffff + 1
      HiCount = $ffff

      Counter = CONT_CNTR	' write a value to each counter
      GoSub WriteCounter

      Low LED

      GoTo Main_1


SetOSCTrim:	' sets trim of osc to value contained in osc_trim

      GoSub BeginSequence
      OByte = OSCTrim * 8
      OByte = OByte | SetTrimBits	' 11 OSC2 OSC1 OSC0 X X 0
      GoSub OutByte
      GoSub EndSequence
      Return

ClearCounter:  	' clears specified counter, $04 - continuous counter
					  ' $02 - V_cc counter
      LookUp Counter, (ClrContinuousCounter, ClrVccCounter), OByte
      Gosub BeginSequence
      LookUp Counter, (ClrContinuousCounter, ClrVccCounter), OByte
      GoSub OutByte
      GoSub EndSequence
      Return

ReadCounter:	' reads 32 bits from specified counter
		' result placed in hi_count and lo_count

      GoSub BeginSequence
      LookUp Counter, (ReadContinuousCounter, ReadVccCounter), OByte
      GoSub OutByte

      'now shift in 32 bits beginning with least significant bit

      GoSub GetByte
      LoCount = IByte		'lo byte of lo word
      Gosub GetByte
      LoCount = Ibyte * 256 | LoCount  'hi byte of lo word

      GoSub GetByte
      HiCount = IByte		'lo byte of hi word
      Gosub GetByte
      HiCount = Ibyte * 256 | HiCount  'hi byte of hi word


      GoSub EndSequence
      Return

WriteCounter:	' writes 32 bits contained in HiCount and LoCount
		' to specified counter, beginning with least sig bit

      GoSub BeginSequence
      LookUp Counter, (WriteContinuousCounter, WriteVccCounter), OByte
      GoSub OutByte
      'now shift out 32 bits beginning with least significant bit

      OByte = LoCount % 256	' lo byte of lo word
      Gosub OutByte
      OByte = LoCount / 256   ' hi byte of lo word
      GoSub OutByte

      OByte = HiCount % 256	' lo byte of hi word
      Gosub OutByte
      OByte = HiCount / 256   ' hi byte of hi word
      GoSub OutByte

      GoSub EndSequence
      Return

OutByte:                ' outputs byte in o_byte, beginning with least
			' significant bit
      For N = 0 to 7
         LSBit = OByte & $01
         If LSBit = 1 Then OutByte_1
         ' else
         Low DQOut
         GoTo OutByte_2

OutByte_1:
         High DQOut
         GoTo OutByte_2

OutByte_2:
         Low CLK
         High CLK
         OByte = OByte / 2      'shift data 1 place right
      Next
      Return

GetByte:		' reads 8 bits from DS1602 beginning with least
			' significant bit
      High DQOut
      For N = 0 to 7
         Low CLK
         IByte = IByte / 2

         If DQIn = 0 Then GetByte_1
         ' else
         IByte = IByte | $80
         ' SerTxd ("1")
         GoTo GetByte_2
GetByte_1:
         ' SerTxD ("0")
GetByte_2:
         High CLK
      Next
	' SerTxD (13, 10)
      Return

BeginSequence:
      Low RST
      High CLK
      High RST 	' initiate by bringing RST high
      Return

EndSequence:
      High CLK
      Low RST
      Return