Interfacing with a Dallas DS2423 Dual 32-bit Counter

copyright, Garth Austin and Peter H Anderson, Baltimore, MD, Jan, 04


Introduction.

This discussion focuses on the Dallas DS2423 device. It is a member of the Dallas 1-W family and provides 512 bytes of RAM and two 32 bit externally triggered counters.

This work was performed by Garth Austin of Tobago as his capstone design project at Morgan State University. Garth has worked with me for some three years and I will miss him.

Our initial interest in the DS2423 was the two 32-bit counters which might be used in a tipping bucket to measure rainfall or as a part of an anemometer to measure wind speed or in virtually any application requiring an inexpensive counter.

However, Garth went further to implement writing to and reading from memory. With the advent of flash PICs where variables may be written to flash memory, there is some skepticism in my mind as to the utility of this RAM, but it may be of use to someone.

The DS2423 is interesting in that it uses an eight bit CRC for some data transfers and a 16-bit CRC for others and both of these were implemented using table lookup. This is contained in a separate discussion.

The DS2423 is packaged in a small 6-pin TSOC package and my initial reaction was that I just couldn't solder those leads to a DIP adaptor without damaging the device. However, it proved to be quite easy.

Detailed Discussion.

Reading the Counter.

Each RAM memory page as 32 bytes. Thus, referring to a specific page is a bit awkward as it is not to do the mental arithmetic of dropping off the five least significant bits of a specific memory address. Thus, in this discussion, the 32-bit pages are identified using the two 16-bit memory blocks within the 32 byte page. For example, page &01C - &01D identifies the page associated with memory locations &01C0 - &01DF

The external counters are associated with RAM pages &01C - &01D and &01E - &01F. They are read by issuing the read memory plus counter command (&Ha5) followed by the memory address of the start of the page (low byte, high byte) and then reading the 32 memory bytes followed by the four bytes associated with the counter. Note that these bytes are arranged least significant byte first.

This is illustrated in program DS2423_1.Bas.

' DS2423_1.Bas
'
' Reads 32 bytes in RAM page 01c0 and displays to the terminal.
' Reads four byte counter and displays the result
'
' BX24			DS2423
'
' term 13 -------------- DQ
'
' Note there is a 4.7K pull up resistor to +5 VDC on the data lead.
'
' copyright, Garth Austin, Peter H Anderson, Baltimore, MD, Dec, '03

Public Sub Main()

    Dim X as Byte, C(1 to 4) as Byte, N as Integer
    Dim Count_2423 as Long

    Do
       Call Init_1W(13)
       Call OutByte_1W(13, &Hcc)  ' skip ROM
       Call OutByte_1W(13, &Ha5)  ' read memory page plus counter
       Call OutByte_1W(13, &Hc0)  ' beginning at &H01c0
       Call OutByte_1W(13, &H01)

       For N = 1 to 32		  ' read the 32 bytes
          X = InByte_1W(13)
          Debug.Print CStr(X)
       Next

       For N = 1 to 4		  ' read the counter
          C(N) = InByte_1W(13)
       Next

       Debug.Print "****************"
       For N = 1 to 4
           Debug.Print CStr(C(N))	' display the four counter bytes
       Next

       Count_2423 = CLng(C(4)) * 256 * 256 * 256 + CLng(C(3)) * 256 * 256 + CLng(C(2)) * 256 + CLng(C(1))
       Debug.Print CStr(Count_2423)	' display as a long

       Call Sleep(10.0)
    Loop

End Sub


Sub Init_1W(ByVal Pin as Byte) ' bring Pin low for 500 usecs and then back
				' high

   Dim N as Integer
   Call PutPin(Pin, 2)	' be sure DQ is a high Z

   Call PutPin(Pin, 0)


    For N = 1 to 3	' adjust for 500 usec delay
    Next

   Call PutPin(Pin, 2)

    For N = 1 to 3
    Next

End Sub

Function InByte_1W(ByVal Pin as Byte) as Byte

   Dim N as Integer, IByte as Byte, Mask as Byte

   Mask = bx0000_0001	' least sig bit first
   IByte = 0

   For N =1 to 8

      If Get1Wire(Pin) = 1 Then
         IByte = IByte OR Mask
      End If
      Mask = Mask * 2	' shift mask left for next bit
   Next

   InByte_1W = IByte

End Function

Sub OutByte_1W(ByVal Pin as Byte, ByVal OByte as Byte)

   Dim N as Integer, Mask as Byte

   Mask = bx0000_0001

   For N = 1 to 8

     If (Mask AND OByte) <>0 Then
        Call Put1Wire(Pin, 1)
     Else
        Call Put1Wire(Pin, 0)
     End If
     Mask = Mask * 2
   Next
End Sub


The counters are set to zero on application of power. There is no other way to do this

Note that the external counters increment with every low going pulse. To avoid noise toggling the counters, I suggest the input not be left floating. That is, if a tipping bucket using a reed type relay is used, the two states are open and GRD. To avoid the float situation when the relay is open, use a pull up resistor to Vbat.

To avoid counting multiple events due to switch bounce, either an RC network or a MAX6817 switch de bouncer is suggested.


Writing to and Reading from Memory.

I was somewhat disappointed to find that the memory associated with the DS2423 is not non-volatile. Dallas indicates NV memory, but it is non-volatile in the sense that the data is held if Vbat is present. Thus, I have some difficulty in appreciating the value of the memory associated with the DS2423.

Data is first written to the 32 byte scratch pad memory by issuing the &H0f command followed by the target address of the start of the memory, least significant byte first which is written to registers TA1 and TA2 followed by the data bytes. Note that in theory, only the low five bytes of the address are required to identify a location in the 32 byte scratch pad memory. However, the full address is required as it is used as a password when writing scratch pad to memory.

The scratch pad is then transferred to memory by issuing the &H5a command, followed by the low and high byte of the target address, followed by the lowest five bits associated with the last scratch pad address.

In program DS2423_2.Bas, the data is then directly read from memory using the &Hf0 command, followed by the two byte address, followed by reading the data.

The following program then prompts the user to momentarily remove power from the DS2423 and after thirty seconds, the memory is again read and displayed to the terminal. The point is to vividly illustrate that the data is not retained.

' Program DS2423_2.Bas
'
' Illustrates how to write to and read from memory.
'
' Writes 31, 30, ... 0 to scratch pad memory and then copies the scratch pad to page &H0C0 - &H0D0.
' Reads from the page and displays to the terminal.
'
' Prompts the user to momentarily remove power from the DS2423 and after 30 seconds, reads from memory
' and displays.  This illustrates that the data is not retained.
'
' copyright, Garth Austin and Peter H Anderson, Baltimore, MD, Jan, '04

Sub Main()

    Dim N as Byte, X as Byte

	' write to scratch pad
    Init_1W(13)  			   'gets the devices attention
    Call OutByte_1W(13, &Hcc)  'skip ROM
    Call OutByte_1W(13, &H0f)  ' write to scratchpad command
    Call OutByte_1W(13, &Hc0)  ' low byte of target address
    Call OutByte_1W(13, &H01)  ' high byte of target address

    For N = 0 to 31
    	Call OutByte_1W(13,31-N)
    Next

    Init_1W(13)
    Call OutByte_1W(13, &Hcc)
    Call OutByte_1W(13, &H5a)  ' copy scratch pad
    Call OutByte_1W(13, &Hc0)  ' low byte of target address
    Call OutByte_1W(13, &H01)  ' high byte of target address

    Call Outbyte_1W(13, &H1f)  'E/S register ending offset (5 least significant bits)

    Init_1W(13)				   ' read memory
    Call OutByte_1W(13, &Hcc)
    Call OutByte_1W(13, &Hf0)  ' read memory command
    Call OutByte_1W(13, &Hc0)  ' low byte of target address
    Call OutByte_1W(13, &H01)  ' high byte of target address

    For N = 0 to 31
   	   X = InByte_1W(13)
       Debug.Print CStr(N); "  "; CStr(X)
    Next

    Debug.Print "Briefly remove power from the DS2423"
    Debug.Print "30 sec delay"

    Call Sleep(30.0)

    Init_1W(13)				   ' again read memory
    Call OutByte_1W(13, &Hcc)
    Call OutByte_1W(13, &Hf0)  ' read memory command
    Call OutByte_1W(13, &Hc0)  ' low bite of target address
    Call OutByte_1W(13, &H01)  ' high bite of target address

    For N = 0 to 31
   	    X = InByte_1W(13)
        Debug.Print CStr(N); "  "; CStr(X)
    Next

    Do
       Debug.Print "Done"
       Call Sleep(5.0)
    Loop

End Sub

Sub Init_1W(ByVal Pin as Byte) ' bring Pin low for 500 usecs and then back
				' high

   Dim N as Integer
   Call PutPin(Pin, 2)	' be sure DQ is a high Z

   Call PutPin(Pin, 0)


    For N = 1 to 3	' adjust for 500 usec delay
    Next

   Call PutPin(Pin, 2)

    For N = 1 to 3
    Next

End Sub

Function InByte_1W(ByVal Pin as Byte) as Byte

   Dim N as Integer, IByte as Byte, Mask as Byte

   Mask = bx0000_0001	' least sig bit first
   IByte = 0

   For N =1 to 8

      If Get1Wire(Pin) = 1 Then
         IByte = IByte OR Mask
      End If
      Mask = Mask * 2	' shift mask left for next bit
   Next

   InByte_1W = IByte

End Function

Sub OutByte_1W(ByVal Pin as Byte, ByVal OByte as Byte)

   Dim N as Integer, Mask as Byte

   Mask = bx0000_0001

   For N = 1 to 8

     If (Mask AND OByte) <>0 Then
        Call Put1Wire(Pin, 1)
     Else
        Call Put1Wire(Pin, 0)
     End If
     Mask = Mask * 2
   Next
End Sub