Maxim DS1620 Digital Thermometer Interfacing

Updated: For a working example, please read this post next. It provides schematic and software that will display the output of the Maxim DS1620 on any Hitachi 44780-compatible LCD.

I was in the shop the other day, putting some FETs away and labeling drawers when I came across a drawer full of DS1620s. I have a bunch of them, I don’t know why. Anyway, I thought it would be fun to see what kind of effort it took to interface this device using, of course, PIC assembly language and a PIC16f690 midrange device.

The DS1620 is a digital thermometer and thermostat. if you wanted to build your own home HVAC thermostat, you might choose to use this device. It allows the developer to set high and low temperature limits that, when reached, will cause one of two limit pins on the device to go high. The usefulness should be obvious. More simple applications allow for reading of temperature in either a continuous conversion mode or by triggering a start and stop conversion, followed by a temperature read.

The CPU communicates with the DS1620 using a 3-wire protocol. Two lines are used as clock and data, while a third reset line is used to initiate and terminate communication “sessions”. The data sheet for the DS1620 is not extremely clear regarding when the bus needs to be reset, which is achieved by driving the reset pin on the device low. My experimentation suggests that a bus reset is required following every logical transaction. Some transactions are one-way and don’t require a response. Bus reset. Others require a request (read temperature) and a reply (9-bit temperature value). Bus reset. You get the idea.
So, Wiring is pretty straight forward as is indicated below by my 5-minute schematic:


A trace of the activity on the data and clock pins can be seen below. I’ll break each transaction down briefly and explain what’s going on:


The green trace is the data pin activity, the red is the clock pin. The reset is not shown, but is used to trigger the oscilloscope, as you can see by the tool bar. Let’s see what’s going on here in terms of transactions.


I’ve drawn boxes around each communication “transaction” that is taking place. Note that the first three are write-only: There is no reply from the DS1620. I know the image is a little hard to read but it can be zoomed by clicking. It’s important to note that there is a bus reset in between each box.

The first communication consists of two 8-bit messages: 0x0C and 0x00. These two mean “I’m sending a command” and “Operate in continuous mode”, respectively. The second box surrounds a request to start a temperature conversion (0xEE). There is a 60us delay between the start conversion and the third box which tells the device to stop the current conversion (0x22). The fourth box can be divided into two parts, the second of which we’ll look at more closely in a minute. The communication contained herein is a command 0xAA (read current converted temperature) and the subsequent, 9-bit reply in LSb order meaning that we’re getting the information backwards :).

For a closer look at what is being sent back, let’s analyze the receive portion of the last transaction:


I’ve noted in the clock trace the value of the data pin. As mentioned above, this is receive LSb first and there are 9 bits. Basically, the LSb is a 0.5 degree indicator, so if we want to actual value we need to first reverse this bits and then shift that one off unless we want to save the precision. That would give us b’00011011′ which equals decimal 27 or 27 degrees C which is a toasty 80.6F.

 

I hope this explanation made at least a little bit of sense, but I’m sure the actual code can fill in what I failed to convey 🙂 A zipped download is available below. Additionally, the complete source listing for each file can be found below. Note that the makefile is only included in the zip archive and requires a GPUtils installation. If you have trouble assembling the source, check to be sure that you’re executable paths have the correct separator if you are using Windows.

Download makefile and asm source for this project.

;-----------------------------------------------------------------------------
; File:     main.asm  
; Date:		01/30/2017
; Purpose:  This module programs and reads temperature from a maxim DS1620
;           thermostat temperature device.
;
; $Author: jcleland $
; $Log$ 
;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------
; This application assumes the following pinouts for P16F690
;
;                 VDD    -|----|-    VSS
;                 RA5    -|    |-    RA0
;                 RA4    -|    |-    RA1
;                 RA3    -|    |-    RA2
;          Data   RC5    -|    |-    RC0 
;         Clock   RC4    -|    |-    RC1 
;         Reset   RC3    -|    |-    RC2
;                 RC6    -|    |-    RB4 
;                 RC7    -|    |-    RB5 
;                 RB7    -|----|-    RB6 
;
;-----------------------------------------------------------------------------

;-----------------------------------------------------------------------------
;Set configuration bits
;
;-----------------------------------------------------------------------------
   __CONFIG(_PWRTE_OFF&_INTRC_OSC_NOCLKOUT&_BOR_OFF&_WDT_OFF&_MCLRE_OFF&_CP_OFF&_IESO_OFF&_FCMEN_OFF)

;Disable benign warnings
   ERRORLEVEL     -207
   ERRORLEVEL     -302

;Include processor header
#include "P16F690.inc"

;Define oscillator configuration bits for OSCON register
#define            __OSCCONFREQBITS      b'01110000'

;-----------------------------------------------------------------------------
;Local data declaration
;
.main.data        udata
loop              res   .1                ;General use register

;-----------------------------------------------------------------------------
;Include local headers
#include "util.inc"
#include "ds1620.inc"

;-----------------------------------------------------------------------------
; Program start jumps to Start label
;
;Be sure to skip to the starting point
.romStart         code 0x00
      goto        Start                   ;Startup jumps to Start label

;-----------------------------------------------------------------------------
;Jump to interrupt handler
;
.romInterrupt     code 0x04               ;Jump to interrupt handler from here
      goto        Interrupt

;-----------------------------------------------------------------------------
;Begin code section
;
.master.code      code

;-----------------------------------------------------------------------------
; Subroutine:  Start
; Purpose:
;
Start:
      ;Global Interrupt disable while configuring device. Notice that we need
      ; to loop this operation, testing the GIE bit of INTCON to be sure it is
      ; clear. The INTCON register is available across all 4 data memory banks
      ; and thus, we don't need to change bank selection bits to address it.
__WaitGIE_Disable
      bcf         INTCON,GIE              ;Clear the GIE bit of interrupt config
      btfsc       INTCON,GIE              ;Wait for bit to clear, and
       goto       __WaitGIE_Disable       ; loop while still set

      ;Disable peripheral interrupts
      bcf         INTCON,PEIE             ;Disable all peripheral interrupts

      ;Oscillator configuration. Note the use of a frequency bits macro here
      ; that is defined above specifically for the PIC16F690 device. We're
      ; configuring the device to use the internal oscillator at 4MHz. The
      ; Final two instructions in this section test for a stable oscillator
      ; before continuing.
      banksel     OSCCON                  ;Select bank
      clrf        OSCCON                  ; unset freq bits to start at 000
      movlw       __OSCCONFREQBITS        ;Load bits into accumulator
      iorwf       OSCCON, f               ; or with current bank settings
      bsf         OSCCON,SCS              ;Set for two-step startup
      bcf         OSCCON, 3

      banksel     OSCTUNE
      movlw       b'00000000'
      movwf       OSCTUNE

      btfss       OSCCON, HTS             ;Test for stable oscillator
       goto       $-1                     ; still clear, keep looping

      bsf         INTCON,PEIE             ;Enable all peripheral interrupts
      bsf         INTCON,GIE              ;Enable interrupts globally

      ;Be sure to set all pins to digital IO
      banksel     ANSELH
      clrf        ANSELH
      banksel     ANSEL
      clrf        ANSEL

      ;-----------------------------------------------------------------------
      ;Configure ports
      banksel     TRISC                   ;Select tristate bank
      movlw       b'00000000'             ;Set all port C pins to outputs
      movwf       TRISC

   __DS1620Init                           ;Initialize the DS1620

Main:
   __Delay500us                           ;Delay in reset for 500us each cycle

      ;This block of code issues two command bytes: The first indicates that
      ; there is a configuration command to follow and the second tells the
      ; DS1620 to operate in continuous conversion mode.
      banksel     ds1620cmd               
      movlw       0x0c
      movwf       ds1620cmd
   __Delay10us
   __DS1620WriteCommand

      banksel     ds1620cmd
      movlw       0x00
      movwf       ds1620cmd
   __Delay10us
   __DS1620WriteCommand

   __DS1620BusReset

      ;The next pair of commands are seperated by a 60 microsecond delay. The
      ; first tells the processor to begin temperature conversion and the 
      ; second tells it to stop. We stop conversion before reading the temp
      ; value.
      banksel     ds1620cmd
      movlw       0xee
      movwf       ds1620cmd
   __Delay10us
   __DS1620WriteCommand

      banksel     ds1620cmd
      movlw       0x22
      movwf       ds1620cmd
   __Delay60us
   __DS1620WriteCommand

   __DS1620BusReset

      ;Finally, we issue a 0xAA (read temperature) instruction, then read the
      ; 9-bit result from the device.
      banksel     ds1620cmd
      movlw       0xaa
      movwf       ds1620cmd
   __Delay10us
   __DS1620WriteCommand

   __Delay10us
   __DS1620ReadWordData

   __DS1620BusReset
      goto        Main                    ;Back to main, start over

;-----------------------------------------------------------------------------
; Function:    Interrupt
; Purpose:
;-----------------------------------------------------------------------------
Interrupt:
   retfie                                 ;Return from interrupt handler

   end ;Stop assembly

;-----------------------------------------------------------------------------
; File:     util.inc 
; Date:		01/30/2017
; Purpose:  Contains utility functions for delays, etc
;
; $Author: jcleland $
;-----------------------------------------------------------------------------

;Include once
#ifndef		__UTIL_INC
   #define  __UTIL_INC

;-----------------------------------------------------------------------------
;Local data declaration
;
.util.data        udata
_sleep_time_us    res   .2                ;General use register

;-----------------------------------------------------------------------------
; Macro:    __TuneOscillator
; Purpose:  This macro produces a pulse on the specified pin at 4 instruction
;				cycles, useful for tuning the internal oscillator.
;-----------------------------------------------------------------------------
__TuneOscillator macro port, pin
   local __label1
      banksel		port
__label1
      bsf			port, pin
      nop
      nop
      nop
      bcf			port, pin
      nop
      goto			__label1
   endm

;-----------------------------------------------------------------------------
; Macro:    __Delay2us
; Purpose:  Wastes 2us of time
; Accuracy: Dead-on
;-----------------------------------------------------------------------------
__Delay2us macro
   local __label1
   local __label2
      goto __label1
__label1      
      goto __label2
__label2      
   endm

;-----------------------------------------------------------------------------
; Macro:    _Delay4us
; Purpose:  Wastes 4us of time
; Accuracy: Dead-on
;-----------------------------------------------------------------------------
__Delay4us macro
     __Delay2us   
     __Delay2us   
   endm

;-----------------------------------------------------------------------------
; Macro:    __Delay10us
; Purpose:  Wastes 10us of time
; Accuracy: Dead-on
;-----------------------------------------------------------------------------
__Delay10us macro
   local __loop
      banksel     _sleep_time_us    ;Select bank (2 cycles)
      movlw       .5                ;Load accumulator for 5 loops
      movwf       _sleep_time_us    ; store in counter register, 2 cycles
__loop
      decfsz      _sleep_time_us,f  ;Decrement the counter and loop
       goto       __loop            ; each loop takes 3 cycles, last one is 2
      nop                           ;Extra cycle
      nop                           ;Extra cycle
   endm                             ;Cycles=2+2+(5*3-1)+2=20=10us

;-----------------------------------------------------------------------------
; Macro:    __Delay60us
; Purpose:  Wastes 60us of time
; Accuracy: Dead-on
;-----------------------------------------------------------------------------
__Delay60us macro
   local __loop
      banksel     _sleep_time_us    ;Select bank (2 cycles)
      movlw       .39               ;Load accumulator with loop count
      movwf       _sleep_time_us    ; store in counter register (2 cycles)
__loop
      decfsz      _sleep_time_us,f  ;Decrement the counter and loop
       goto       __loop            ; each loop takes 3 cycles, last one is 2
   endm                             ;Cycles=2+2+(39*3-1)=120=60us
   
;-----------------------------------------------------------------------------
; Macro:    __Delay500us
; Purpose:  Wastes 500us of time
; Accuracy: Dead-on
;-----------------------------------------------------------------------------
__Delay500us macro
   local __loop
      banksel     _sleep_time_us    ;Select bank (2 cycles)
      movlw       .249              ;Load accumulator for 249 loops
      movwf       _sleep_time_us    ; store in counter register, 2 cycles
__loop
      nop                           ;Waste cycle  
      decfsz      _sleep_time_us,f  ;Decrement the counter and loop
       goto       __loop            ; each loop takes 3 cycles, last one is 2
      nop                           ;Extra cycle
   endm                             ;Cycles=2+2+(249*4-1)+1=1000=500us
   
;Include once
#endif

 

;-----------------------------------------------------------------------------
; File:     ds1620.inc 
; Date:		01/30/2017
; Purpose:  
;
; $Author: jcleland $
;-----------------------------------------------------------------------------

;Include once
#ifndef		__DS1620_INC
   #define	__DS1620.INC

;Include util for delays
#include "util.inc"

;-----------------------------------------------------------------------------
;Constants declaration
;
DSPORT				equ	PORTC
DSTRIS				equ	(DSPORT|0x80)
DSRST					equ	3
DSCLK					equ	4
DSDAT					equ	5

;-----------------------------------------------------------------------------
;Local data declaration
;
.ds1620.data      udata
ds1620loop			res	.2						;Loop counter register
ds1620cmd			res	.1						;Command data register
ds1620data			res	.2						;Data register

;-----------------------------------------------------------------------------
; Macro:    __DS1620Init
; Purpose:  Configures the device port and sets the 3-wire bus in reset
;-----------------------------------------------------------------------------
__DS1620Init macro
      ;Select the tristate register and configure all 3-wire pins as outputs
      banksel		DSTRIS
      movlw			(1<<DSRST) & (1<<DSCLK) & (1<<DSDAT)
      iorwf			DSTRIS, f

      ;Set the initial state for the bus: reset low and clock high. We don't
      ; care how the data pin in configured at this point
      banksel		DSPORT
      bcf			DSPORT,DSRST
   __Delay2us
      bsf			DSPORT,DSCLK
   __Delay2us
   endm
;-----------------------------------------------------------------------------
; Macro:    __DS1620BusReset
; Purpose:  Resets the 3-wire bus state and terminates any active transaction
;				with the device. The reset line is left low, clock is left high,
;				the data line is unchanged.
;-----------------------------------------------------------------------------
__DS1620BusReset macro
      ;Reset the initial state for the bus: reset low and clock high. We don't
      ; care how the data pin in configured.
      banksel		DSPORT
      bcf			DSPORT,DSRST
   __Delay2us
      bsf			DSPORT,DSCLK
   __Delay2us
   endm

;-----------------------------------------------------------------------------
; Macro:    __DS1620WriteCommand
; Purpose:  This macro writes the command data in the ds1620cmd file register
;				to the device. It does not reset the bus prior to sending the
;				command.
;-----------------------------------------------------------------------------
__DS1620WriteCommand macro
   local __bitLoop, __dataLow, __dataHigh, __clockData
      
      ;Load the loop register for 8 bits to send 
      banksel		ds1620loop
      movlw			.8
      movwf			ds1620loop

      ;Select the port bank and drive the reset pin high to begin 
      ; communication
      banksel		DSPORT
      bsf			DSPORT,DSRST
   __Delay2us
      
__bitLoop
      ;Send the command data LSb first, branch on bit 0. We'll shift through
      ; each bit so what is bit 1 will be bit 0 on the next iteration. We'll
      ; do this 8 times.
      banksel		ds1620cmd
      btfss			ds1620cmd,0
         goto		__dataLow
      goto			__dataHigh

__dataLow
      banksel		DSPORT
      bcf			DSPORT,DSDAT		
      goto			__clockData

__dataHigh
      banksel		DSPORT
      bsf			DSPORT,DSDAT

__clockData
   __Delay2us

      ;Now that the data pin is set to 0 or 1 for the current bit, strobe the
      ; clock line for 2 microseconds, allowing the device to read the current
      ; data bit.
      bcf			DSPORT,DSCLK
   __Delay2us
      bsf			DSPORT,DSCLK

      ;Rotate the command byte right, shifting bit 0 into the carry flag. All
      ; bits move down one position so bit 1 is now bit 0 and soforth.
      banksel		ds1620cmd
      rrf			ds1620cmd, f

      ;Check the counter to see if we've sent all 8 bits. If not, loop back 
      ; to __bitLoop and send the next bit in the command byte.
      banksel		ds1620loop
      decfsz		ds1620loop, f
         goto		__bitLoop
   endm
   
;-----------------------------------------------------------------------------
; Macro:    __DS1620ReadWordData
; Purpose:  This macro reads word data from the device into the ds1620data
;				file register. The data is read LSB first, but stored MSB
;-----------------------------------------------------------------------------
__DS1620ReadWordData macro
   local __bitLoop, __dataLow, __dataHigh, __byteRead

      banksel		ds1620loop					;Select loop buffer bank
      movlw			.8								;Load for 8 bit read in low byte
      movwf			ds1620loop					;

      banksel		ds1620data					;Select data bank
      clrf			ds1620data					;Clear the output register word
      clrf			ds1620data+1				; bytes

      movlw			ds1620data+1				;Load the address of data buffer
      movwf			FSR							; into FSR for indirect addressing

      banksel		DSTRIS						;Select tristate register bank
      bsf			DSTRIS,DSDAT				; and switch data pin to input

   __Delay2us

__bitLoop
      banksel		DSPORT						;Clock low to read first byte
      bcf			DSPORT,DSCLK				;Set clock low to read bit
   __Delay2us
      btfss			DSPORT,DSDAT
         goto		__dataLow
      goto			__dataHigh

__dataLow
      bcf			STATUS, C					;Bit is low, clear carry and
      rlf			INDF, f						; rotate carry flag into data
      goto			__byteRead

__dataHigh
      bsf			STATUS, C					;Bit is low, clear carry and
      rlf			INDF, f						; rotate carry flag into data

__byteRead
   __Delay2us
      bsf			DSPORT,DSCLK	   		;Set clock bit to finish read

      banksel		ds1620loop
      decfsz		ds1620loop, f
         goto		__bitLoop

      ;Decrement the register pointer for MSB
      decf			FSR, f

      
      ;Finished with low byte, just read one bit and store in MSB
      banksel		DSPORT
      bcf			DSPORT,DSCLK
   __Delay2us

      bcf			STATUS, C					;Clear carry, default is 0
      btfsc			DSPORT,DSDAT
         bsf		STATUS, C

      rlf			INDF, f						;Rotate the bit that we set in the
                                          ; carry flag into the 9'th bit
                                          ; which is bit 0 of the MSB
   __Delay2us
      bsf			DSPORT,DSCLK

      banksel		DSTRIS						;Select tristate register bank
      bcf			DSTRIS,DSDAT				; and switch data pin to input

   endm

;Include once
#endif

 

Leave a Reply

Your email address will not be published. Required fields are marked *

© Zillow, Inc., 2006-2016. Use is subject to Terms of Use
What's a Zestimate?