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