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