Interfacing with a Dallas DS2450 Quad A/D


The Dallas DS2450 is a Quad A/D with a Dallas 1-W Interface.

However, any of the A/D channels might alternately be used as an open collector output. Thus, one might locate a remote DS2540 in a green house and use two A/D channels to measure temperature (perhaps an NTC thermistor) and relative humidity using a Honeywell HIH-3605 (3610) sensor and the other two channels as outputs to control a fan and an alarm.

Suppliers either do not have the DS2450 in stock or insist on a minimum of 88 pieces. In addition, the device is in a surface mount SOIC package, not the easiest thing for hobbyists to work with. If it appears there is sufficient interest, I will stock the DS2450 mounted on an SOIC to DIP converter at $12.00. Drop me an e-mail if you are interested.

In the following routines, I have only scratched the surface in illustrating the capabilities of this device.

Areas for additional work include;


Program DS2450_1.Bas.


' DS2450_1.Bas
'
' Illustrates an interface with a DS2450 Quad A/D.
'
' Configures for VDD = 5V operation by writing &H40 to memory location &H001c.
'
' Configures all four channels for 12 bit, 5.12 full scale by writing to
' locations &H0008 and 0009 for Channel A, &H000a and 000b for channel B, etc.
'
' Continually loops, setting mask to 1111 (all channels) with a preset of 0.
' Reads from locations &H0000 and 0001 for Channel A, &H0002 and 0003 for Channel B,
' etc.
'
' Displays the A/D value for each channel and the voltage on Channel D.
'
' Note that the 16-bit CRC is not implemented.
'
' Compile with SerialPort.Bas.
'
'                  +5
'                   |
'                   4.7K
'                   |
' BX24 (term 13) ------------------------ DS2450 (term 3)
'
' copyright, Peter H Anderson, Baltimore, MD, Dec, '01

const W1_PIN as Byte = 13


Sub Main()

   Dim Dummy as Byte, HighByte as Byte, LowByte as Byte
   Dim CRCRead as Integer, ADVal as Integer
   Dim Volts as Single

   Call OpenSerialPort(1, 19200)

   Call PutPin(W1_PIN, 2)
   Sleep(0.25)

   Call Init_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &Hcc)
   Call OutByte_1W(W1_PIN, &H55)
   Call OutByte_1W(W1_PIN, &H1c)	' write to 001c
   Call OutByte_1W(W1_PIN, &H00)
   Call OutByte_1W(W1_PIN, &H40)	' VCC operation

   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)		' read back data

   Init_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &Hcc)
   Call OutByte_1W(W1_PIN, &H55)	' write to locations beginning at 00 08
   Call OutByte_1W(W1_PIN, &H08)
   Call OutByte_1W(W1_PIN, &H00)

   Call OutByte_1W(W1_PIN, &H0b)	' set up Channel A for 12 bit
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H01)	' 5.12 VDC range
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H0b)	' set up Channel B for 12 bit
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H01)	' 5.12 VDC range
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H0b)	' set up Channel C for 12 bit
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H01)	' 5.12 VDC range
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H0b)	' set up Channel D for 12 bit
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H01)	' 5.12 VDC range
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

  Do
      Call Init_1W(W1_PIN)

      Call OutByte_1W(W1_PIN, &Hcc)
      Call OutByte_1W(W1_PIN, &H3c)	' convert
      Call OutByte_1W(W1_PIN, &H0f)	' All channels
      Call OutByte_1W(W1_PIN, &H01)	' preset to all zeros

      CRCRead = FetchCRCBytes(W1_PIN)

      Do
         Dummy = InByte_1W(W1_PIN)
      Loop Until (Dummy = &Hff)

      Call Sleep(0.001)

      Call Init_1W(W1_PIN)

      Call OutByte_1W(W1_PIN, &Hcc)
      Call OutByte_1W(W1_PIN, &Haa)	' read memory
      Call OutByte_1W(W1_PIN, &H00)	' Channel A
      Call OutByte_1W(W1_PIN, &H00)	' locations 0000 and 0001

      LowByte = InByte_1W(W1_PIN)
      HighByte = InByte_1W(W1_PIN)

      ADVal = CInt(HighByte)
      ADVal = ADVal * 16 + CInt(LowByte\16)

      Debug.Print "Channel A "; CStr(ADVal)

      LowByte = InByte_1W(W1_PIN)
      HighByte = InByte_1W(W1_PIN)

      ADVal = CInt(HighByte)
      ADVal = ADVal * 16 + CInt(LowByte\16)

      Debug.Print "Channel B "; CStr(ADVal)

      LowByte = InByte_1W(W1_PIN)
      HighByte = InByte_1W(W1_PIN)

      ADVal = CInt(HighByte)
      ADVal = ADVal * 16 + CInt(LowByte\16)

      Debug.Print "Channel C "; CStr(ADVal)

      LowByte = InByte_1W(W1_PIN)
      HighByte = InByte_1W(W1_PIN)

      ADVal = CInt(HighByte)
      ADVal = ADVal * 16 + CInt(LowByte\16)

      Debug.Print "Channel D "; CStr(ADVal)
      Volts = CSng(ADVal) / 4096.0 * 5.12
      PutS(Volts)
      Call NewLine()

      Call NewLine()

      Sleep(1.0)

  Loop
End Sub

Function FetchCRCBytes(ByVal Pin as Byte) as Integer
   Dim X as Byte, Y as Byte
   Dim CRC as Integer

   X = InByte_1W(Pin)
   Y = InByte_1W(Pin)
   CRC = CInt(Y)
   CRC = CRC * 256 + CInt(X)
   FetchCRCBytes = CRC
End Function


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 an input

   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, B as Byte
   For N =1 to 8
      B = Get1Wire(Pin)
      If (B=1) then
         IByte = (IByte\2) OR bx10000000
      Else
         IByte = IByte\2
      End If
   Next

   InByte_1W = IByte

End Function

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

   Dim N as Integer, B as Byte
   For N = 1 to 8
     B = OByte AND bx00000001
     If (B=1) Then
        Call Put1Wire(Pin, 1)
     Else
        Call Put1Wire(Pin, 0)
     End If
     OByte = OByte \ 2
   Next
End Sub

Sub StrongPullUp_1W(ByVal Pin as Byte)
   ' Provide a hard logic one for 0.75 secs
   Call PutPin(Pin, 1)
   Call Sleep(0.75)
   Call PutPin(Pin, 2)
End Sub

Program DS2450_2.Bas

' DS2450_2.Bas
'
' Illustrates an interface with a DS2450 Quad A/D.  Two channels are used for
' A/D and the other two are used as outputs
'
' Configures for VDD = 5V operation by writing &H40 to memory location &H001c.
'
' Configures channels A and B for 12 bit, 5.12 full scale by writing to
' locations &H0008 and 0009 for Channel A, &H000a and 000b for channel B.
'
' Configures Channels C and D as output logic zeros.
'
' Continually loops, setting mask to 0011 (channels A and B) with a preset of 0.
' Reads from locations &H0000 and 0001 for Channel A, &H0002 and 0003 for Channel B,
'
' If the voltage on Channel A is greater 3.5 Volts, Output C is brought to a logic one.
' If less than 2.5 VDC, Output C is brought to a zero.  The same is true for measurement
' channel B and output D.
'
' Displays the A/D value for each channel and the voltage on Channel D.
'
' Note that the 16-bit CRC is not implemented.
'
' Compile with SerialPort.Bas.
'
'                  +5
'                   |
'                   4.7K
'                   |
' BX24 (term 13) ------------------------ DS2450 (term 3)
'
' copyright, Peter H Anderson, Baltimore, MD, Dec, '01

const W1_PIN as Byte = 13


Sub Main()

   Dim Dummy as Byte, HighByte as Byte, LowByte as Byte
   Dim CRCRead as Integer, ADVal as Integer
   Dim ChAVoltage as Single, ChBVoltage as Single

   Call OpenSerialPort(1, 19200)

   Call PutPin(W1_PIN, 2)
   Sleep(0.25)

   Call Init_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &Hcc)
   Call OutByte_1W(W1_PIN, &H55)
   Call OutByte_1W(W1_PIN, &H1c)	' write to 001c
   Call OutByte_1W(W1_PIN, &H00)
   Call OutByte_1W(W1_PIN, &H40)	' VCC operation

   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)		' read back data

   Init_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &Hcc)
   Call OutByte_1W(W1_PIN, &H55)	' write to locations beginning at 00 08
   Call OutByte_1W(W1_PIN, &H08)
   Call OutByte_1W(W1_PIN, &H00)

   Call OutByte_1W(W1_PIN, &H0b)	' set up Channel A for 12 bit
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H01)	' 5.12 VDC range
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H0b)	' set up Channel B for 12 bit
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H01)	' 5.12 VDC range
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H80)	' set up Channel C for output 0
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H00)	' this is don't care
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H80)	' set up Channel D for output logic one (open)
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

   Call OutByte_1W(W1_PIN, &H00)	' this is don't care
   CRCRead = FetchCRCBytes(W1_PIN)
   Dummy = InByte_1W(W1_PIN)

  Do
      Call Init_1W(W1_PIN)

      Call OutByte_1W(W1_PIN, &Hcc)
      Call OutByte_1W(W1_PIN, &H3c)	' convert
      Call OutByte_1W(W1_PIN, &H03)	' channels A, B
      Call OutByte_1W(W1_PIN, &H01)	' preset to all zeros

      CRCRead = FetchCRCBytes(W1_PIN)

      Do
         Dummy = InByte_1W(W1_PIN)
      Loop Until (Dummy = &Hff)

      Call Sleep(0.001)

      Call Init_1W(W1_PIN)

      Call OutByte_1W(W1_PIN, &Hcc)
      Call OutByte_1W(W1_PIN, &Haa)	' read memory
      Call OutByte_1W(W1_PIN, &H00)	' Channel A
      Call OutByte_1W(W1_PIN, &H00)	' locations 0000 and 0001

      LowByte = InByte_1W(W1_PIN)
      HighByte = InByte_1W(W1_PIN)

      ADVal = CInt(HighByte)
      ADVal = ADVal * 16 + CInt(LowByte\16)

      ChAVoltage = CSng(ADVal) / 4096.0 * 5.12
      Debug.Print "Channel A = "; CStr(CInt(1000.0 * ChAVoltage)); "mV"


      LowByte = InByte_1W(W1_PIN)
      HighByte = InByte_1W(W1_PIN)

      ADVal = CInt(HighByte)
      ADVal = ADVal * 16 + CInt(LowByte\16)

      ChBVoltage = CSng(ADVal) / 4096.0 * 5.12
      Debug.Print "Channel B = "; CStr(CInt(1000.0 * ChBVoltage)); "mV"

      If (ChAVoltage > 3.5) Then

         Init_1W(W1_PIN)

         Call OutByte_1W(W1_PIN, &Hcc)
         Call OutByte_1W(W1_PIN, &H55)	' write to location  00 0c
         Call OutByte_1W(W1_PIN, &H0c)
         Call OutByte_1W(W1_PIN, &H00)
         Call OutByte_1W(W1_PIN, &Hc0)	' bring Ch C ouput to high
         CRCRead = FetchCRCBytes(W1_PIN)
         Dummy = InByte_1W(W1_PIN)

      ElseIf (ChAVoltage < 2.5) Then

         Init_1W(W1_PIN)

         Call OutByte_1W(W1_PIN, &Hcc)
         Call OutByte_1W(W1_PIN, &H55)	' write to location  00 0c
         Call OutByte_1W(W1_PIN, &H0c)
         Call OutByte_1W(W1_PIN, &H00)
         Call OutByte_1W(W1_PIN, &H80)	' bring Ch C ouput to 0
         CRCRead = FetchCRCBytes(W1_PIN)
         Dummy = InByte_1W(W1_PIN)

      End If

      If (ChBVoltage > 3.5) Then

         Init_1W(W1_PIN)

         Call OutByte_1W(W1_PIN, &Hcc)
         Call OutByte_1W(W1_PIN, &H55)	' write to location  00 0e
         Call OutByte_1W(W1_PIN, &H0e)
         Call OutByte_1W(W1_PIN, &H00)
         Call OutByte_1W(W1_PIN, &Hc0)	' bring Ch D ouput to high
         CRCRead = FetchCRCBytes(W1_PIN)
         Dummy = InByte_1W(W1_PIN)

      ElseIf (ChBVoltage < 2.5) Then

         Init_1W(W1_PIN)

         Call OutByte_1W(W1_PIN, &Hcc)
         Call OutByte_1W(W1_PIN, &H55)	' write to location  00 0e
         Call OutByte_1W(W1_PIN, &H0e)
         Call OutByte_1W(W1_PIN, &H00)
         Call OutByte_1W(W1_PIN, &H80)	' bring Ch D ouput to 0
         CRCRead = FetchCRCBytes(W1_PIN)
         Dummy = InByte_1W(W1_PIN)

      End If

      Call NewLine()

      Call NewLine()

      Sleep(1.0)

  Loop
End Sub

Function FetchCRCBytes(ByVal Pin as Byte) as Integer
   Dim X as Byte, Y as Byte
   Dim CRC as Integer

   X = InByte_1W(Pin)
   Y = InByte_1W(Pin)
   CRC = CInt(Y)
   CRC = CRC * 256 + CInt(X)
   FetchCRCBytes = CRC
End Function


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 an input

   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, B as Byte
   For N =1 to 8
      B = Get1Wire(Pin)
      If (B=1) then
         IByte = (IByte\2) OR bx10000000
      Else
         IByte = IByte\2
      End If
   Next

   InByte_1W = IByte

End Function

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

   Dim N as Integer, B as Byte
   For N = 1 to 8
     B = OByte AND bx00000001
     If (B=1) Then
        Call Put1Wire(Pin, 1)
     Else
        Call Put1Wire(Pin, 0)
     End If
     OByte = OByte \ 2
   Next
End Sub

Sub StrongPullUp_1W(ByVal Pin as Byte)
   ' Provide a hard logic one for 0.75 secs
   Call PutPin(Pin, 1)
   Call Sleep(0.75)
   Call PutPin(Pin, 2)
End Sub