| SX/B Example: Thermometer | Examples Index |
' =========================================================================
'
' File...... THERMOMETER.SXB
' Purpose... Dual-mode digital thermometer
' Author.... (c) Parallax, Inc. -- All Rights Reserved
' E-mail.... support@parallax.com
' Started...
' Updated... 05 JUL 2006
'
' =========================================================================
' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
'
' Displays the temperature from a DS1620 thermo chip on a multiplexed 7-
' segment display. The display is multiplexed by interrupt code so that
' no additional components are required. A mode input allows the temper-
' ature to be displayed in Celsius or Fahrenheit.
'
' When the temperature falls below 0C (32F) "-Lo-" is displayed. When the
' temp is above 49C (120 F) "-Hi-" is displayed.
' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------
DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ 4_000_000
ID "THERMO"
' -------------------------------------------------------------------------
' IO Pins
' -------------------------------------------------------------------------
DQ VAR RC.7 ' DS1620.1
Clock VAR RC.6 ' DS1620.2
Rst VAR RC.5 ' DS1620.3
DispMode VAR RC.4 ' display mode, C or F
Segs VAR RB ' display segments
DigCtrl VAR RA ' digit control (cathode)
' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------
Blank CON %00000000 ' blank display
Dash CON %01000000 ' pattern for "-"
Ltr_C CON %00111001 ' pattern for "C"
Ltr_F CON %01110001 ' pattern for "F"
Ltr_L CON %00111000 ' pattern for "L"
Ltr_o CON %01011100 ' pattern for "o"
Ltr_H CON %01110110 ' pattern for "H"
Ltr_i CON %00010000 ' pattern for "i"
TC CON 0 ' mode = Celsius
TF CON 1 ' mode = Fahrenheit
' *** DS1620 Commands ***
RdTmp CON $AA ' read temperature
WrHi CON $01 ' write TH (high temp)
WrLo CON $02 ' write TL (low temp)
RdHi CON $A1 ' read TH
RdLo CON $A2 ' read TL
StartC CON $EE ' start conversion
StopC CON $22 ' stop conversion
WrCfg CON $0C ' write config register
RdCfg CON $AC ' read config register
' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------
display VAR Byte(4) ' multiplexed segments
digPntr VAR Byte ' digit pointer
digLimit VAR Byte ' 0 - 3
theTemp VAR Byte ' temperature
tSign VAR Byte ' sign in bit 0
work VAR Byte
tmpB1 VAR Byte ' subroutine work vars
tmpB2 VAR Byte
tmpW1 VAR Word
' =========================================================================
INTERRUPT 200
' =========================================================================
' Points to next digit of display every 5 milliseconds (200 times/sec).
ISR_Start:
INC digPntr ' point to next digit
IF digPntr < digLimit THEN Update_Segs ' update digit
digPntr = 0 ' wrap if needed
Update_Segs:
Segs = Blank ' blank segs
READ DigMap + digPntr, DigCtrl ' select display element
Segs = display(digPntr) ' output new digit segs
ISR_Exit:
RETURNINT
' =========================================================================
PROGRAM Start
' =========================================================================
' -------------------------------------------------------------------------
' Subroutines
' -------------------------------------------------------------------------
INIT_1620 SUB 0 ' initialize DS1620
RD_1620 SUB 0 ' get temp from DS1620
NEW_DISPLAY SUB 2 ' update display
' -------------------------------------------------------------------------
' Program Code
' -------------------------------------------------------------------------
Start:
DigCtrl = %1111 ' disable all digits
TRIS_A = %0000 ' make dig pins outputs
Segs = Blank ' clear seg drivers
TRIS_B = %00000000 ' make seg pins outputs
TRIS_C = %10011111 ' clock and rst are outputs
INIT_1620
PUT display(0), Blank, Blank, Blank, Blank ' clear display
digLimit = 4 ' use all digits (1 - 4)
digPntr = 3
Main:
DO
theTemp = RD_1620 ' read temperature
NEW_DISPLAY theTemp, tSign ' display value
PAUSE 500 ' delay between reads
LOOP
' -------------------------------------------------------------------------
' Subroutine Code
' -------------------------------------------------------------------------
' Initialize DS1620 for free-run mode and for use with a host CPU
INIT_1620:
Rst = 1 ' select device
SHIFTOUT DQ, Clock, LSBFIRST, WrCfg ' write to config register
SHIFTOUT DQ, Clock, LSBFIRST, %00000010 ' with CPU; free-run
Rst = 0 ' deselect device
PAUSE 10 ' allow DS1620 EE to write
Rst = 1 ' reselect
SHIFTOUT DQ, Clock, LSBFIRST, StartC ' start conversion
Rst = 0 ' deselect
RETURN
' -------------------------------------------------------------------------
' Use: theTemp = RD1620
' -- returns temp in whole degrees C in 'theTemp'
RD_1620:
Rst = 1 ' select device
SHIFTOUT DQ, Clock, LSBFIRST, RdTmp ' send read temp command
SHIFTIN DQ, Clock, LSBPRE, tmpB1 ' get temp (C x 0.5)
SHIFTIN DQ, Clock, LSBPRE, tSign\1 ' get sign bit
Rst = 0 ' deselect device
tmpB1 = tmpB1 + tmpB1.0 ' round up
tmpB1 = tmpB1 >> 1 ' remove half bit
RETURN tmpB1
' -------------------------------------------------------------------------
' Use: NEW_DISPLAY temperature, sign
' -- puts 'temperature' in display (pass value in degrees C)
' -- display mode (C or F) controlled by RC.4 input
NEW_DISPLAY:
tmpB1 = __PARAM1 ' temperature
tmpB2 = __PARAM2 ' sign bit
IF tmpB2 = 1 THEN ' negative temp?
digLimit = 4
PUT display(0), Dash, Ltr_o, Ltr_L, Dash ' show "-Lo-"
GOTO Display_Done
ENDIF
IF tmpB1 > 49 THEN ' too high?
digLimit = 4
PUT display(0), Dash, Ltr_i, Ltr_H, Dash ' show "-Hi-"
GOTO Display_Done
ENDIF
Check_Mode:
IF DispMode = TC THEN ' check mode input switch
display(0) = Ltr_C
ELSE
display(0) = Ltr_F
tmpW1 = tmpB1 */ $1CC ' temp x 1.8 (9/5)
tmpB1 = tmpW1_LSB + 32
ENDIF
Set_Display: ' blank leading zeros
digLimit = 2 ' 1-digit temp
IF tmpB1 < 10 THEN Show_Temp
INC digLimit ' 2-digit temp
IF tmpB1 < 100 THEN Show_Temp
INC digLimit ' 3-digit temp
Show_Temp:
tmpB2 = tmpB1 / 100 ' get hundreds digit
tmpB1 = __REMAINDER ' save 10's and 1's
READ SegMap + tmpB2, display(3) ' get segment map 100's
tmpB2 = tmpB1 / 10 ' get 10's digit
tmpB1 = __REMAINDER ' save 1's
READ SegMap + tmpB2, display(2) ' get segment map for 10's
READ SegMap + tmpB1, display(1) ' get segment map for 1's
Display_Done:
RETURN
' =========================================================================
' User Data
' =========================================================================
SegMap: ' segments maps
' .gfedcba
DATA %00111111 ' 0
DATA %00000110 ' 1
DATA %01011011 ' 2
DATA %01001111 ' 3
DATA %01100110 ' 4
DATA %01101101 ' 5
DATA %01111101 ' 6
DATA %00000111 ' 7
DATA %01111111 ' 8
DATA %01100111 ' 9
DigMap: ' digit select map
DATA %11111110
DATA %11111101
DATA %11111011
DATA %11110111