; ------ Digital Thermometer ------ ; ------ Processor AT89C2051 24PC ------ ; ------ Supports Dallas DS1820 and DS1821 Thermometers ------ #DEFINE Z_SUP ;Zero suppression #INCLUDE "LIBREG.ASM" ;8051 SFR set #DEFINE LO(XXX) XXX & 0FFH #DEFINE HI(XXX) (XXX >> 8) & 0FFH CLK_KHZ = 10000 ;OSC frequency, KHZ RTC_MS = 20 ;System clock , MS RTCV = CLK_KHZ*RTC_MS RTCV = RTCV/12 RTCV = - RTCV RTCV = RTCV & 0FFFFH ; ------ Constantes ------ STACK .EQU 056H ;stack location V100MS .EQU 5 ;program timer RTPCS value 100mS/20mS=5 I2C_ADDR .EQU 0A0H ;I2C address for PCF8582 (A0,A1,A2=0) SMPTMV .EQU 5 ;x20mS thermometers sample timer value INKTMV .EQU 35 ;x20mS initial key repeat timer value KEYTMV .EQU 5 ;x20mS key repeat timer value BRKTMV .EQU 2 ;x20mS brightness key repeat timer value BLBTMV .EQU 50 ;x20mS blink begin delay timer value SAVTMV .EQU 200 ;x20mS NVM save delay timer value TMOV20 .EQU 25 ;x20mS timeout value for DS1820 TMOV21 .EQU 100 ;x20mS timeout value for DS1821 INDTMV .EQU 50 ;x20mS indication mode 2,4 delay value OFFTMV .EQU 50 ;x100mS off delay value MIN_RT .EQU 5 ;x100mS min auto change rate SKEW .EQU 20 ;brightness control skew PWM_MAX .EQU 230 ;MAX PWM value L_MAX .EQU 09AH ;MAX on and off limit L_MIN .EQU 001H ;MIN on and off limit SHIFT .EQU 037H ;unsigned limit - shift = signed limit ; ------ Ports ------ SCAN0 .EQU P3.0 ;display scan line 0 SCAN1 .EQU P3.1 ;display scan line 1 SCAN2 .EQU P3.5 ;display scan line 2 SDA .EQU SCAN0 ;I2C SDA line SCL .EQU SCAN1 ;I2C SCL line OWP1 .EQU P3.2 ;1-Wire Port 1 (EXT. THERMOMETER) OWP2 .EQU P3.7 ;1-Wire Port 2 (INT. THERMOMETER) RETL .EQU P3.4 ;keyboard return line CNTRL .EQU P3.3 ;thermostat control line ; ------ Variables ------ ;R10 used for temporary save of ONLIM and OFLIM (in PROG) ;R11 used for temporary save of DIG1 (in TCONV20, TCONV21) ;R12 used for temporary save of DIG2 (in TCONV20, TCONV21) ;R13 used for temporary save of DIG3 (in TCONV20, TCONV21) ;R14 used for temporary save of OFLIM (in PROG) PWVH .EQU R20 ;PWM timer value (off state) high PWVL .EQU R21 ;PWM timer value (off state) low PHVH .EQU R22 ;PWM timer value (on state) high PHVL .EQU R23 ;PWM timer value (on state) low PHASE .EQU R24 ;display scan phase INCODE .EQU R25 ;keyboard internal scan-code ; Bit addressing memory RTPC .EQU 020H ;Real time program counter T040M .EQU M_20H.0 ;40mS period bit T080M .EQU M_20H.1 ;80mS period bit T160M .EQU M_20H.2 ;160mS period bit T320M .EQU M_20H.3 ;320mS period bit T640M .EQU M_20H.4 ;640mS period bit T1S28 .EQU M_20H.5 ;1.28S period bit T2S56 .EQU M_20H.6 ;2.56S period bit T5S12 .EQU M_20H.7 ;5.12S period bit RTPCS .EQU 021H ;Real time program counter (100mS part) SEL_EXT .EQU M_22H.0 ;select OWP1 bit (external) MINUS .EQU M_22H.1 ;minus bit (used in TCONV20, TCONV21) PRESS .EQU M_22H.2 ;keyboard press bit BLINK .EQU M_22H.3 ;display blink bit FEN .EQU M_22H.4 ;ACHR fill enable bit LEVEL .EQU M_22H.5 ;thermostat active level NOTSV .EQU 023H ;not saved in NVM params flags byte NSV_BR .EQU M_23H.0 ;not saved in NVM brightness bit NSV_ON .EQU M_23H.1 ;not saved in NVM on limit bit NSV_OF .EQU M_23H.2 ;not saved in NVM off limit bit NSV_IM .EQU M_23H.3 ;not saved in NVM indication mode bit NSV_RT .EQU M_23H.4 ;not saved in NVM auto change rate bit PARAMS .EQU PWM ;array address (Array 024H..028H) PWM .EQU 024H ;PWM duty cycle value (1..230) ONLIM .EQU 025H ;thermostat on limit (unsigned 0-9AH) OFLIM .EQU 026H ;thermostat off limit (unsigned 0-9AH) INDMD .EQU 027H ;ind. mode (0-EXT, 1-INT, etc.) IND_INT .EQU M_27H.0 ;EXT/INT indication (0/1) IND_SET .EQU M_27H.1 ;indication/set (0/1) IND_TH1 .EQU M_27H.2 ;th1 indication (1) IND_ONL .EQU M_27H.3 ;on limit indication (1) IND_TH0 .EQU M_27H.4 ;th0 indication (1) IND_OFL .EQU M_27H.5 ;off limit indication (1) ACHR .EQU 028H ;auto change EXT/INT rate ; Internal data memory CD1 .EQU 030H ;display digit 1 (segments copy) CD2 .EQU 031H ;display digit 2 (segments copy) CD3 .EQU 032H ;display digit 3 (segments copy) DIG1 .EQU 033H ;display digit 1 (bit 7 - minus seg) DIG2 .EQU 034H ;display digit 2 (bit 7 - point seg) DIG3 .EQU 035H ;display digit 3 (bit 7 - LED EXT seg) D1_EXT .EQU 036H ;EXT temperature digit 1 D2_EXT .EQU 037H ;EXT temperature digit 2 D3_EXT .EQU 038H ;EXT temperature digit 3 D1_INT .EQU 039H ;INT temperature digit 1 D2_INT .EQU 03AH ;INT temperature digit 2 D3_INT .EQU 03BH ;INT temperature digit 3 EXT_TH .EQU 03CH ;EXT thermometer type (00H-none, 20H-DS1820, 21H-DS1821) INT_TH .EQU 03DH ;INT thermometer type (00H-none, 20H-DS1820, 21H-DS1821) EXT_T .EQU 03EH ;binary unsigned EXT temperature TMO_EXT .EQU 042H ;EXT thermometer ready timeout timer TMO_INT .EQU 043H ;INT thermometer ready timeout timer SMPTM .EQU 044H ;thermometer sample timer KEYTM .EQU 045H ;key repeat timer SAVTM .EQU 046H ;NVM save delay timer DELTM .EQU 047H ;delay timer ACHTM .EQU 048H ;auto change timer OFFTM .EQU 049H ;off timer ; ------ Vectors Area ------ .ORG 0000H ;reset vector AJMP INIT .ORG 000BH ;INT TIMER 0 vector AJMP RTC .ORG 001BH ;INT TIMER 1 vector AJMP INDSCAN ; ------ Main Program ------ INIT: MOV SP,#STACK ;stack init CLR BLINK ;clear display blink bit CLR FEN ;fill enable bit clear CLR A MOV KEYTM,A ;clear key repeat timer MOV EXT_TH,A ;no EXT thermometer MOV INT_TH,A ;no INT thermometer MOV NOTSV,A ;NVM not save flags clear MOV OFFTM,#OFFTMV ;off timer load ACALL NVMREAD ;PWM, ONLIM, OFLIM, INDMD, ACHR init ACALL GETPWM ;get PWM timer values ACALL DISP ;CD1-CD3 init MOV ACHTM,ACHR MOV TMOD,#11H ;timer 0 and timer 1 init MOV TL0,#LO(RTCV) ;timer 0 load MOV TH0,#HI(RTCV) MOV TL1,PHVL ;timer 1 load MOV TH1,PHVH MOV RTPCS,#V100MS ;100mS value load MOV TCON,#50H ;timer 0 and timer 1 start SETB PT1 ;int timer 1 hi, timer 0 low priority MOV IE,#8AH ;timer 0, timer 1 int enable (ET0,ET1,EA=1) ACALL AD_EXT ;auto detect and start external thermometer ACALL AD_INT ;auto detect and start internal thermometer MOV SMPTM,#SMPTMV ;thermometers sample timer load MAIN: MOV A,INCODE ;local keyboard test CPL A JNZ MA10 ;jump if press CLR FEN CLR PRESS SJMP MA20 ;jump if no press MA10: MOV B,A ;save keyboard code ACALL DEL10 ;debounce delay MOV A,INCODE ;read keyboard code CPL A CJNE A,B,MA20 ;no press if codes are differ MOV R7,A MOV OFFTM,#OFFTMV ;off timer load JB PRESS,SAME ;Control Functions Analysis and Processing DIF: CJNE R7,#KEY_SL,$+5H ;KEY SELECT ACALL SEL CJNE R7,#KEY_EX,$+5H ;KEY EXT/INT ACALL EXT SAME: CJNE R7,#KEY_UP,$+5H ;KEY UP ACALL UP CJNE R7,#KEY_DN,$+5H ;KEY DOWN ACALL DN CJNE R7,#KEY_UD,$+5H ;KEY UP+DOWN ACALL UPDN SETB PRESS ;set PRESS ;End of Control Functions Analysis MA20: MOV A,SMPTM ;check sample timer JNZ MA24 ;jump if no timer overflow MOV SMPTM,#SMPTMV ;timer reload ACALL CH_EXT ;check EXT thermometer JNZ MA21 ;jump if ready MOV A,TMO_EXT ;check timeout JNZ MA22 SJMP MA23 ;timeout is over, go to auto detect MA21: ACALL RD_EXT ;read EXT thermometer ACALL LIM_CHK ;thermostat control MA23: ACALL AD_EXT ;auto detect and start MA22: ACALL CH_INT ;check INT thermometer JNZ MA25 ;jump if ready MOV A,TMO_INT ;check timeout JNZ MA24 SJMP MA26 ;timeout is over, go to auto detect MA25: ACALL RD_INT ;read INT thermometer MA26: ACALL AD_INT ;auto detect and start MA24: JB IND_SET,MA33 ;jump if set mode MOV A,ACHR CLR C SUBB A,#MIN_RT JC MA40 ;jump if ACHROFLIM ;Sets DS1821 to read mode if ONLIM=OFLIM ;Input: ONLIM, OFLIM, bit LEVEL PROG: CLR CNTRL ;VDD on SETB OWP1 MOV DIG1,#CH_P MOV DIG2,#CH_r MOV DIG3,#BLANK ACALL IND1 MOV A,#(~KEY_SL) CJNE A,INCODE,$ ACALL TRESET1 ;Issue reset pulse. JC TH_PRG ;jump if no error (read mode) SETB CNTRL ;VDD off CLR EA MOV P1,#0FFH ;indication off MOV R0,#16 TOG1: CLR OWP1 INC DPTR ;delay SETB OWP1 DJNZ R0,TOG1 CLR CNTRL ;VDD on ACALL DEL10 TH_PRG: MOV A,OFLIM CJNE A,ONLIM,PRG1 MOV R1,#0CH ;Write command register CLR A ;ONLIM=OFLIM, return device to read mode ACALL COMM MOV DIG1,#CH_r MOV DIG2,#CH_d SJMP PRG2 PRG1: MOV R14,ONLIM JNC ONH ;jump if ONLIM>OFLIM (C=0) XCH A,R14 ONH: MOV LEVEL,C CLR C SUBB A,#SHIFT MOV R10,A MOV R1,#01H ;Write TH command ACALL COMM MOV R1,#0A1H ;Read TH command MOV A,#0FFH ACALL COMM CJNE A,R10,PR_ER MOV A,R14 SUBB A,#SHIFT MOV R10,A MOV R1,#02H ;Write TL command ACALL COMM MOV R1,#0A2H ;Read TL command MOV A,#0FFH ACALL COMM CJNE A,R10,PR_ER MOV R1,#0CH ;Write command register. MOV A,#04H ;Thermostat mode MOV C,LEVEL MOV ACC.1,C ACALL COMM PR_TH: MOV DIG1,#CH_t MOV DIG2,#CH_h PRG2: ACALL DEL50 ACALL IND1 SETB CNTRL ;VDD off MOV A,#(~KEY_UD) CJNE A,INCODE,$ MOV OFFTM,#OFFTMV ;off timer load AJMP EXTR RT_ER: DEC SP DEC SP PR_ER: MOV DIG1,#CH_E MOV DIG2,#CH_r MOV DIG3,#CH_r SJMP PRG2 ;Perform write/read command to DS1821 at OWP1 ;Input: R1 - command (01H - write TH, 02H - write TL ; A1H - read TH, A2H - read TL ; 0CH - write command register) ; A - byte (= 0FFH for read) ;Out: A (if read operation) COMM: ACALL TRESET1 ;Issue reset pulse. JNC RT_ER ;Fail if no part on bus. COMM_N: MOV R2,A MOV A,R1 ;Command. ACALL TOUCHBY1 ;Send command byte. MOV A,R2 ACALL TOUCHBY1 ;Send command byte. SETB C RET ;Select key processing SEL: JB IND_SET,SEL1 SETB IND_SET ;EXT/INT indication mode, SET=1 SETB IND_TH1 ;TH1=1 SJMP SEL10 SEL1: JBC IND_TH1,SEL2 JBC IND_ONL,SEL2 CLR IND_TH0 CLR IND_OFL CLR IND_SET MOV KEYTM,#0H SJMP SEL11 SEL2: SETB IND_TH0 SEL10: MOV DELTM,#INDTMV SEL11: CLR BLINK MOV SAVTM,#SAVTMV RET ;External/Internal key processing EXT: CPL IND_INT MOV ACHR,#0H SETB FEN SETB NSV_IM SETB NSV_RT EXTR: ANL INDMD,#1H SJMP SEL11 ; ------ 1-Wire Dallas Interface Support ------ #DEFINE CLK_10MHZ #DEFINE INT_DIS ; ; Uses CLK_8MHZ, CLK_10MHZ, CLK_11MHZ or CLK_12MHZ ; Uses INT_DIS for interrupts disable in time slots ; ; Main program must define: ; ; Dallas 1-Wire Port as OWP1 ; ; This library includes: ; ; TRESET1 - Reset pulse generation for port #1 ; TOUCHBY1 - Read/write byte via port #1 ; ; TRESET1: ; This procedure transmits the Reset signal to the 1-Wire ; device and watches for a presence pulse. On return, ; the Carry bit is set if a presence pulse was detected, ; otherwise the Carry is cleared. The code is timed for ; an 8, 10, 11.059 and 12 MHz crystal. ; ; TOUCHBY1: ; This procedure sends the byte in the accumulator ; to the 1-Wire device, and returns a byte from the ; 1-Wire device in the accumulator. For reading ; operation set accumulator to 0FFH. The code is ; timed for an 8, 10, 11.059 and 12 MHz crystal. ; ------ TRESET1 ------ TRESET1: CLR OWP1 ;Start the reset pulse. #IFDEF CLK_8MHZ \ MOV B,#160 \ #ENDIF ; 2. Set time interval. #IFDEF CLK_10MHZ \ MOV B,#200 \ #ENDIF ; 2. Set time interval. #IFDEF CLK_11MHZ \ MOV B,#221 \ #ENDIF ; 2. Set time interval. #IFDEF CLK_12MHZ \ MOV B,#240 \ #ENDIF ; 2. Set time interval. DJNZ B,$ ;320. 400. 442. 480. Wait with Data low. #IFDEF INT_DIS \ CLR EA \ #ENDIF ; Interrupt disable if needed SETB OWP1 ; 1. Release Data line. #IFDEF CLK_8MHZ \ MOV B,#80 \ #ENDIF ;High wait delay. #IFDEF CLK_10MHZ \ MOV B,#101 \ #ENDIF ;High wait delay. #IFDEF CLK_11MHZ \ MOV B,#111 \ #ENDIF ;High wait delay. #IFDEF CLK_12MHZ \ MOV B,#120 \ #ENDIF ;High wait delay. CLR C ; 1. Clear presence flag. WAITL1: JB OWP1,WH1 ;Exit loop if line high. DJNZ B,WAITL1 ;Hang around if line is low. #IFDEF INT_DIS \ SETB EA \ #ENDIF ; Interrupt enable if needed SJMP SHORT1 ;Line could not go high. WH1: #IFDEF INT_DIS \ SETB EA \ #ENDIF ; Interrupt enable if needed #IFDEF CLK_8MHZ \ MOV B,#80 \ #ENDIF ;Delay for presence detect. #IFDEF CLK_10MHZ \ MOV B,#101 \ #ENDIF ;Delay for presence detect. #IFDEF CLK_11MHZ \ MOV B,#111 \ #ENDIF ;Delay for presence detect. #IFDEF CLK_12MHZ \ MOV B,#120 \ #ENDIF ;Delay for presence detect. HL1: ORL C,/OWP1 ;160. 202. 222. 240. Catch presence pulse. DJNZ B,HL1 ;160. 202. 222. 240. Wait with Data high. SHORT1: RET ;Return. ; ------ TOUCHBY1 ------ TOUCHBY1: PUSH B ;Save the B register. MOV B,#8 ;Setup for 8 bits. B_LOOP1: RRC A ;1. Get bit in carry. LCALL TOUCHB1 ;2. Send bit. DJNZ B,B_LOOP1 ;2. Get next bit. RRC A ; Get final bit in ACC. POP B ;Restore B register. RET ;Return to caller. TOUCHB1: #IFDEF INT_DIS \ CLR EA \ #ENDIF ; Interrupt disable if needed CLR OWP1 ; 1. Start the time slot. NOP ; 1. Delay to make sure NOP ; 1. that the Touch Memory NOP ; 1. sees a low for at NOP ; 1. least 1 microsecond. MOV OWP1,C ; 2. Send out the data bit. NOP ; 1. Delay to give the NOP ; 1. data returned from NOP ; 1. the Touch Memory NOP ; 1. time to settle NOP ; 1. before reading NOP ; 1. the bit. MOV C,OWP1 ; 1. Sample input data bit. #IFDEF INT_DIS \ SETB EA \ #ENDIF ; Interrupt enable if needed PUSH B ; 2. Save B register. #IFDEF CLK_8MHZ \ MOV B,#13 \ #ENDIF ; 2. Delay until the end #IFDEF CLK_10MHZ \ MOV B,#16 \ #ENDIF ; 2. Delay until the end #IFDEF CLK_11MHZ \ MOV B,#18 \ #ENDIF ; 2. Delay until the end #IFDEF CLK_12MHZ \ MOV B,#20 \ #ENDIF ; 2. Delay until the end DJNZ B,$ ;26. 32. 36. 40. of the time slot. POP B ;Restore B register. SETB OWP1 ;Terminate time slot. RET ;Return to caller. ; ; Uses CLK_8MHZ, CLK_10MHZ, CLK_11MHZ or CLK_12MHZ ; Uses INT_DIS for interrupts disable in time slots ; ; Main program must define: ; ; Dallas 1-Wire Port as OWP2 ; ; This library includes: ; ; TRESET2 - Reset pulse generation for port #2 ; TOUCHBY2 - Read/write byte via port #2 ; ; TRESET2: ; This procedure transmits the Reset signal to the 1-Wire ; device and watches for a presence pulse. On return, ; the Carry bit is set if a presence pulse was detected, ; otherwise the Carry is cleared. The code is timed for ; an 8, 10, 11.059 and 12 MHz crystal. ; ; TOUCHBY2: ; This procedure sends the byte in the accumulator ; to the 1-Wire device, and returns a byte from the ; 1-Wire device in the accumulator. For reading ; operation set accumulator to 0FFH. The code is ; timed for an 8, 10, 11.059 and 12 MHz crystal. ; ------ TRESET2 ------ TRESET2: CLR OWP2 ;Start the reset pulse. #IFDEF CLK_8MHZ \ MOV B,#160 \ #ENDIF ; 2. Set time interval. #IFDEF CLK_10MHZ \ MOV B,#200 \ #ENDIF ; 2. Set time interval. #IFDEF CLK_11MHZ \ MOV B,#221 \ #ENDIF ; 2. Set time interval. #IFDEF CLK_12MHZ \ MOV B,#240 \ #ENDIF ; 2. Set time interval. DJNZ B,$ ;320. 400. 442. 480. Wait with Data low. #IFDEF INT_DIS \ CLR EA \ #ENDIF ; Interrupt disable if needed SETB OWP2 ; 1. Release Data line. #IFDEF CLK_8MHZ \ MOV B,#80 \ #ENDIF ;High wait delay. #IFDEF CLK_10MHZ \ MOV B,#101 \ #ENDIF ;High wait delay. #IFDEF CLK_11MHZ \ MOV B,#111 \ #ENDIF ;High wait delay. #IFDEF CLK_12MHZ \ MOV B,#120 \ #ENDIF ;High wait delay. CLR C ; 1. Clear presence flag. WAITL2: JB OWP2,WH2 ;Exit loop if line high. DJNZ B,WAITL2 ;Hang around if line is low. #IFDEF INT_DIS \ SETB EA \ #ENDIF ; Interrupt enable if needed SJMP SHORT2 ;Line could not go high. WH2: #IFDEF INT_DIS \ SETB EA \ #ENDIF ; Interrupt enable if needed #IFDEF CLK_8MHZ \ MOV B,#80 \ #ENDIF ;Delay for presence detect. #IFDEF CLK_10MHZ \ MOV B,#101 \ #ENDIF ;Delay for presence detect. #IFDEF CLK_11MHZ \ MOV B,#111 \ #ENDIF ;Delay for presence detect. #IFDEF CLK_12MHZ \ MOV B,#120 \ #ENDIF ;Delay for presence detect. HL2: ORL C,/OWP2 ;160. 202. 222. 240. Catch presence pulse. DJNZ B,HL2 ;160. 202. 222. 240. Wait with Data high. SHORT2: RET ;Return. ; ------ TOUCHBY2 ------ TOUCHBY2: PUSH B ;Save the B register. MOV B,#8 ;Setup for 8 bits. B_LOOP2: RRC A ;1. Get bit in carry. LCALL TOUCHB2 ;2. Send bit. DJNZ B,B_LOOP2 ;2. Get next bit. RRC A ; Get final bit in ACC. POP B ;Restore B register. RET ;Return to caller. TOUCHB2: #IFDEF INT_DIS \ CLR EA \ #ENDIF ; Interrupt disable if needed CLR OWP2 ; 1. Start the time slot. NOP ; 1. Delay to make sure NOP ; 1. that the Touch Memory NOP ; 1. sees a low for at NOP ; 1. least 1 microsecond. MOV OWP2,C ; 2. Send out the data bit. NOP ; 1. Delay to give the NOP ; 1. data returned from NOP ; 1. the Touch Memory NOP ; 1. time to settle NOP ; 1. before reading NOP ; 1. the bit. MOV C,OWP2 ; 1. Sample input data bit. #IFDEF INT_DIS \ SETB EA \ #ENDIF ; Interrupt enable if needed PUSH B ; 2. Save B register. #IFDEF CLK_8MHZ \ MOV B,#13 \ #ENDIF ; 2. Delay until the end #IFDEF CLK_10MHZ \ MOV B,#16 \ #ENDIF ; 2. Delay until the end #IFDEF CLK_11MHZ \ MOV B,#18 \ #ENDIF ; 2. Delay until the end #IFDEF CLK_12MHZ \ MOV B,#20 \ #ENDIF ; 2. Delay until the end DJNZ B,$ ;26. 32. 36. 40. of the time slot. POP B ;Restore B register. SETB OWP2 ;Terminate time slot. RET ;Return to caller. ; Common routines: TRESET: JNB SEL_EXT,TRESET2 AJMP TRESET1 TOUCHBY: JNB SEL_EXT,TOUCHBY2 AJMP TOUCHBY1 ; Autodetect and start external thermometer ; Out: EXT_TH = 21H if DS1821 external thermometer is detected ; EXT_TH = 20H if DS1820 external thermometer is detected ; EXT_TH = 00H if no external thermometer is detected AD_EXT: SETB SEL_EXT MOV EXT_TH,#00H ACALL TRESET ;Issue reset pulse. JNC ADEXT1 ;Fail if no part on bus. MOV EXT_TH,#21H MOV A,#0ACH ;Read DS1821 status command. ACALL TOUCHBY ;Send command byte. MOV A,#0FFH ;Perform read. ACALL TOUCHBY ;Read status. JB ACC.2,ADEXT2 ;Jump if not DS1821 present. ACALL START_21 MOV TMO_EXT,#TMOV21 RET ADEXT2: MOV EXT_TH,#20H ACALL START_20 MOV TMO_EXT,#TMOV20 ADEXT1: RET ; Autodetect and start internal thermometer ; Out: INT_TH = 21H if DS1821 internal thermometer is detected ; INT_TH = 20H if DS1820 internal thermometer is detected ; INT_TH = 00H if no internal thermometer is detected AD_INT: CLR SEL_EXT MOV INT_TH,#00H ACALL TRESET ;Issue reset pulse. JNC ADINT1 ;Fail if no part on bus. MOV INT_TH,#21H MOV A,#0ACH ;Read DS1821 status command. ACALL TOUCHBY ;Send command byte. MOV A,#0FFH ;Perform read. ACALL TOUCHBY ;Read status. JB ACC.2,ADINT2 ;Jump if not DS1821 present. ACALL START_21 MOV TMO_INT,#TMOV21 RET ADINT2: MOV INT_TH,#20H ACALL START_20 MOV TMO_INT,#TMOV20 ADINT1: RET ; Read external thermometer RD_EXT: SETB SEL_EXT MOV A,EXT_TH CJNE A,#20H,REXT1 ACALL READ_20 SJMP REXT3 REXT1: CJNE A,#21H,REXT2 ACALL READ_21 REXT3: MOV D1_EXT,R11 MOV D2_EXT,R12 MOV D3_EXT,R13 MOV A,R6 ADD A,#SHIFT MOV EXT_T,A REXT2: RET ; Read internal thermometer RD_INT: CLR SEL_EXT MOV A,INT_TH CJNE A,#20H,RINT1 ACALL READ_20 SJMP RINT3 RINT1: CJNE A,#21H,RINT2 ACALL READ_21 RINT3: MOV D1_INT,R11 MOV D2_INT,R12 MOV D3_INT,R13 RINT2: RET ; Check external thermometer CH_EXT: SETB SEL_EXT MOV A,EXT_TH CJNE A,#20H,CEXT1 ACALL RDY_20 RET CEXT1: CJNE A,#21H,CEXT2 ACALL RDY_21 CEXT2: RET ; Check internal thermometer CH_INT: CLR SEL_EXT MOV A,INT_TH CJNE A,#20H,CINT1 ACALL RDY_20 RET CINT1: CJNE A,#21H,CINT2 ACALL RDY_21 CINT2: RET ; ------ 1-Wire thermometer DALLAS DS1820 support ------ ; Start conversion in 1-wire thermometer DS1820. ; Calls TRESET, TOUCHBY START_20: ACALL TRESET ;Issue reset pulse. JNC STR20 ;Fail if no part on bus. MOV A,#0CCH ;Skip ROM command. ACALL TOUCHBY ;Send command byte. MOV A,#044H ;Convert T1 command. ACALL TOUCHBY ;Send command byte. SETB C STR20: RET ; Check ready 1-wire thermometer DS1820. ; Returns A=0 when device not ready. ; Calls TOUCHBY RDY_20: MOV A,#0FFH ;Perform read. ACALL TOUCHBY ;Read. RET ; Read temperature from 1-wire thermometer DS1820. ; Returns C=1 in case of valid code, else C=0. ; Returns D1_EXT,D2_EXT,D3_EXT=BCD temperature value -55.0..99.9 ; Calls TRESET, TOUCHBY READ_20: ACALL TRESET ;Issue reset pulse. JNC RDR20 ;Fail if no part on bus. MOV A,#0CCH ;Skip ROM command. ACALL TOUCHBY ;Send command byte. MOV A,#0BEH ;Read scratchpad command. ACALL TOUCHBY ;Send command byte. MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read LSB. MOV R2,A ;LSB store MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read MSB. MOV R3,A ;MSB store MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read TH. MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read TL. MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read RESERVED BYTE. MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read RESERVED BYTE. MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read COUNT REMAIN. MOV R4,A ;COUNT REMAIN store MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read COUNT PER C. MOV R5,A ;COUNT PER C store ACALL TCONV20 SETB C RDR20: RET ; Temperature HEX to BCD conversion ; Truncates T<0 ; Input R3,R2=MSB,LSB of temperature ; Input R4=COUNT REMAIN ; Input R5=COUNT PER C ; Out Dx_INT or Dx_EXT=-55.0-99.9 ; MINUS - bit D1_INT.7 TCONV20: MOV A,R3 ;MSB restore RRC A MOV MINUS,C MOV A,R2 ;LSB restore MOV C,MINUS RRC A MOV R6,A JNB MINUS,DLC4 CPL A INC A DLC4: MOV B,#10 MUL AB ;B,A=Tx10 JNB MINUS,DLC6 XCH A,B CPL A XCH A,B CPL A ADD A,#1H XCH A,B ADDC A,#0H XCH A,B DLC6: ADD A,#7 MOV R1,A MOV A,B ADDC A,#0 MOV R2,A ;R2,R1=Tx10+7 MOV A,R5 MOV B,#10 DIV AB ;A=COUNT PER C/10 MOV B,A MOV A,R4 DIV AB ;A=COUNT REMAIN/(COUNT PER C/10) XCH A,R1 SUBB A,R1 MOV R1,A MOV A,R2 SUBB A,#0H MOV R2,A ;R2,R1=T(actual)x10 ORL C,MINUS MOV MINUS,C JNC DLC3 MOV A,R2 CPL A MOV R2,A MOV A,R1 CPL A ADD A,#1H MOV R1,A MOV A,R2 ADDC A,#0H MOV R2,A DLC3: MOV R11,#0FFH ;100s init DLC1: MOV R4,R02 MOV R3,R01 INC R11 CLR C MOV A,R3 SUBB A,#100 MOV R1,A MOV A,R4 SUBB A,#0 MOV R2,A JNC DLC1 ;if C=1 then R11=N/100,R4=0 MOV A,R3 MOV B,#10 DIV AB ;A=N/10,B=N/1 SETB ACC.7 MOV R12,A MOV R13,B JNB MINUS,DLC5 MOV A,R11 SETB ACC.7 MOV R11,A DLC5: RET ; ------ 1-Wire thermometer DALLAS DS1821 support ------ ; TEMPERATURE CONVERSION COMMANDS ; ; 0EEH - start convert T ; 022H - stop convert T ; 0AAH - Read temperature ; ; THERMOSTAT COMMANDS ; ; 001H - write TH ; 002H - write TL ; 0A1H - read TH ; 0A2H - read TL ; 00CH - write status ; 0ACH - read status ; ; Status register: ; ; bit 7 - DONE 1= conversion complete ; 0= conversion in progress ; bit 6 - 1 ; ; bit 5 - NVB 1= nonvolatile memory is busy ; 0= nonvolatile memory is not busy ; bit 4 - THF 1= temperature exceeds TH (remain 1 until reset by writing 0) ; 0= normally ; bit 3 - TLF 1= temperature lower TL (remain 1 until reset by writing 0) ; 0= normally ; bit 2 - T/R 1= power up thermostat mode ; 0= power up one wire mode ; bit 1 - POL 1= thermostat output is active high ; 0= thermostat output is active low ; bit 0 - 1SHOT 1= one conversion ; 0= continuous conversion ; ; Bits THF, TLF, T/R, POL, 1SHOT are nonvolatile ; ; Temperature code format: ; ; +125 - 07DH ; +25 - 019H ; 0 - 000H ; -1 - 0FFH ; -25 - 0E7H ; -55 - 0C9H ; Init and start conversion in 1-wire thermometer DS1821. ; Calls TRESET, TOUCHBY START_21: ACALL TRESET ;Issue reset pulse. JNC STR21 ;Fail if no part on bus. MOV A,#0ACH ;Read status command. ACALL TOUCHBY ;Send command byte. MOV A,#0FFH ;Perform read. ACALL TOUCHBY ;Read status. ANL A,#1H JNZ ST_21 ;Skip write status if 1SHOT=1 ACALL TRESET ;Issue reset pulse. JNC STR21 ;Fail if no part on bus. MOV A,#0CH ;Write status command. ACALL TOUCHBY ;Send command byte. MOV A,#01H ;Set 1SHOT to 1 (one conv. per start). ACALL TOUCHBY ;Write status. ST_21: ACALL TRESET ;Issue reset pulse. JNC STR21 ;Fail if no part on bus. MOV A,#0EEH ;Start convert command. ACALL TOUCHBY ;Send command byte. SETB C STR21: RET ; Check ready 1-wire thermometer DS1821. ; Returns A=0 when device not ready. ; Calls TRESET, TOUCHBY RDY_21: ACALL TRESET ;Issue reset pulse. MOV A,#0ACH ;Read status command. ACALL TOUCHBY ;Send command byte. MOV A,#0FFH ;Perform read. ACALL TOUCHBY ;Read status. ANL A,#80H RET ; Read temperature from 1-wire thermometer DS1821. ; Returns C=1 in case of valid code, else C=0. ; Returns D1_INT,D2_INT,D3_INT,MINUS of temperature (-55..99). ; Calls TRESET, TOUCHBY READ_21: ACALL TRESET ;Issue reset pulse. JNC RDR21 ;Fail if no part on bus. MOV A,#0AAH ;Read temperature command. ACALL TOUCHBY ;Send command byte. MOV A,#0FFH ;perform read ACALL TOUCHBY ;Read temperature. ACALL TCONV21 ;HEX to BCD conversion SETB C RDR21: RET ; Temperature HEX to BCD conversion ; Input A=0..0C9H ; Returns Dx_INT or Dx_EXT ; MINUS - bit D1_INT.7 TCONV21: MOV R6,A MOV C,ACC.7 MOV MINUS,C ;minus store JNC TPL CPL A INC A TPL: MOV B,#10 ;HEX to BCD conversion DIV AB JNB MINUS,TPL1 SETB ACC.7 TPL1: MOV R11,A #IFDEF Z_SUP MOV R13,#BLANK MOV R12,B #ELSE MOV R13,#0H SETB B.7 MOV R12,B #ENDIF RET ;Check for limits and thermostat control (000H <= ONLIM, OFLIM <= 09AH) LIM_CHK: MOV A,EXT_TH JZ OFF_TH ;thermostat off if EXT_TH=0 MOV A,ONLIM CJNE A,OFLIM,CHK1 OFF_TH: SETB CNTRL ;thermostat off if ONLIM=OFLIM RET ON_TH: CLR CNTRL RET CHK1: JC CHK2 ;jump if OFLIM>ONLIM (heater mode) MOV A,EXT_T ;OFLIMONLIM (heater mode) JNC ON_TH MOV A,OFLIM CJNE A,EXT_T,$+3H CHK3: JZ OFF_TH JC OFF_TH RET ;I2C NVM memory 24C08 support ; Main program defines: ; ; I2C slave address I2C_ADDR (0A0H for first 256 bytes) ; I2C data line SDA ; I2C clock line SCL I2C_DWBD: CLR ET1 MOV P1,#0FFH SETB SDA SETB SCL PUSH ACC ;save data byte MOV A,#I2C_ADDR ;I2C device address and write mode ACALL I2C_WR ;transmission MOV A,R1 ;subaddress ACALL I2C_WR ;transmission POP ACC ;restore data byte ACALL I2C_WR ;transmission ACALL I2C_STOP SETB ET1 ACALL DEL50 ;delay 50mS RET I2C_DRDD: CLR ET1 MOV P1,#0FFH SETB SDA SETB SCL MOV A,#I2C_ADDR ;I2C device address and write mode ACALL I2C_WR ;transmission MOV A,R1 ;subaddress ACALL I2C_WR ;transmission ACALL I2C_STOP ;stop MOV A,#I2C_ADDR+1 ;I2C device address and read mode ACALL I2C_WR ;transmission ACALL I2C_LRD ;receive byte ACALL I2C_STOP ;stop SETB ET1 RET ;Write byte from A to I2C I2C_WR: MOV R3,#9H ;bit counter load SETB C ;set bit C for bit9=1 (when ACK) ACALL SDA0 ;SDA 1/0 - start I2CWR1: ACALL SCL0 ;SCL 1/0 RLC A JC OUTP1 ;jump if bit=1 ACALL SDA0 ;else SDA=0 OUTP0: ACALL SCL1 ;SCL 0/1 DJNZ R3,I2CWR1 RET OUTP1: ACALL SDA1 ;SDA=1 if bit=1 SJMP OUTP0 ;Read byte from I2C to A and no ACK (read last byte) I2C_LRD: MOV A,#1H I2CLRD1: ACALL SCL0 ACALL SDA1 ACALL SCL1 MOV C,SDA RLC A JNC I2CLRD1 ACALL SCL0 ACALL SCL1 ;SCL 0/1 when SDA=1 - no ACK RET ;Stop condition generation I2C_STOP: ACALL SCL0 ACALL SDA0 ACALL SCL1 ACALL SDA1 RET ;SDA and SCL lines drive SDA0: CLR SDA ;SDA 1/0 NOP ;delay RET SDA1: SETB SDA ;SDA 0/1 NOP ;delay RET SCL0: CLR SCL ;SCL 1/0 NOP ;delay RET SCL1: SETB SCL ;SCL 0/1 NOP ;delay RET SIGN .EQU 098H ;signature ;EEPROM address map NVM_SIG .EQU 0F0H ;signature address NVM_BR .EQU 0F1H ;brightness address NVM_ONL .EQU 0F2H ;on limit address NVM_OFL .EQU 0F3H ;off limit address NVM_IDM .EQU 0F4H ;indication mode address NVM_RTV .EQU 0F5H ;auto change rate value address SAVE: JBC NSV_BR,SV1 JBC NSV_ON,SV2 JBC NSV_OF,SV3 JBC NSV_IM,SV4 JBC NSV_RT,SV5 RET SV1: MOV R1,#NVM_BR MOV A,PWM SJMP DO_SV SV2: MOV R1,#NVM_ONL MOV A,ONLIM SJMP DO_SV SV3: MOV R1,#NVM_OFL MOV A,OFLIM SJMP DO_SV SV4: MOV R1,#NVM_IDM MOV A,INDMD ANL A,#1H SJMP DO_SV SV5: MOV R1,#NVM_RTV MOV A,ACHR DO_SV: ACALL I2C_DWBD RET NVMREAD: MOV R1,#NVM_SIG ACALL I2C_DRDD CJNE A,#SIGN,NVMINIT MOV R0,#PARAMS MOV R2,#5H NR1: INC R1 ACALL I2C_DRDD MOV @R0,A INC R0 DJNZ R2,NR1 RET NVMINIT: MOV R1,#NVM_SIG MOV A,#SIGN ACALL I2C_DWBD MOV PWM,#PWM_MAX MOV ONLIM,#SHIFT MOV OFLIM,#SHIFT CLR A MOV INDMD,A MOV ACHR,A MOV NOTSV,#1FH RET DISP: JB IND_SET,D2 JB IND_INT,D1 MOV A,EXT_TH ;INDMD=0 JNZ D3 MOV A,#CH_MIN MOV D1_EXT,A MOV D3_EXT,A SETB ACC.7 MOV D2_EXT,A D3: MOV DIG1,D1_EXT MOV DIG2,D2_EXT MOV DIG3,D3_EXT SJMP IND D1: MOV A,INT_TH ;INDMD=1 JNZ D9 MOV A,#CH_MIN MOV D1_INT,A MOV D3_INT,A SETB ACC.7 MOV D2_INT,A D9: MOV DIG1,D1_INT MOV DIG2,D2_INT MOV DIG3,D3_INT SJMP IND D2: JNB IND_TH1,D5 MOV DIG3,#1H SJMP D8 D5: JNB IND_ONL,D6 MOV A,ONLIM SJMP D4 D6: JNB IND_TH0,D7 MOV DIG3,#0H D8: MOV DIG1,#CH_t MOV DIG2,#CH_h SJMP IND D7: MOV A,OFLIM D4: CLR C SUBB A,#SHIFT MOV MINUS,C JNC DM CPL A INC A DM: MOV B,#10 DIV AB MOV C,MINUS MOV ACC.7,C MOV DIG1,A MOV DIG2,B MOV DIG3,#BLANK IND: MOV C,T320M ORL C,/BLINK JC IND1 CLR A CPL A MOV CD1,A MOV CD2,A MOV CD3,A RET IND1: MOV DPTR,#FONT MOV A,DIG1 MOV C,ACC.7 ;minus bit store CPL C CLR ACC.7 MOVC A,@A+DPTR MOV ACC+SB,C ;minus on/off MOV CD1,A MOV A,DIG2 MOV C,ACC.7 ;point bit store CPL C CLR ACC.7 MOVC A,@A+DPTR MOV ACC+SB,C ;point on/off MOV CD2,A MOV A,DIG3 MOVC A,@A+DPTR MOV C,IND_INT MOV ACC+SB,C ;LED EXT on/off MOV CD3,A RET GETPWM: MOV A,PWM MOV B,#7H ;682H/238 MUL AB ;682H/238*PWM CPL A MOV PHVL,A MOV A,B CPL A MOV PHVH,A MOV A,PHVL ADD A,#82H CPL A MOV PWVL,A MOV A,PHVH ADDC A,#06H CPL A MOV PWVH,A RET ;Delay 50mS DEL50: MOV R2,#100 SJMP DEL05 ;Delay 10mS DEL10: MOV R2,#20 SJMP DEL05 DEL05: MOV R3,#CLK_KHZ/48 DJNZ R3,$ DJNZ R2,DEL05 RET ; ------ Interrupt Holders ------ ; TIMER 0 Interrupt ; System clock (20mS) RTC: PUSH PSW PUSH ACC CLR TR0 ;timer 0 stop MOV TH0,#HI(RTCV) ;timer 0 load for 20mS MOV TL0,#LO(RTCV) SETB TR0 ;timer start INC RTPC ;Real Time Program Counter INC DJNZ RTPCS,RTC1 MOV RTPCS,#V100MS ; 100mS program counters JNB FEN,RTC11 MOV A,ACHR ADD A,#1H JC RTC12 MOV ACHR,A MOV ACHTM,A SJMP RTC12 RTC11: MOV A,ACHTM JZ RTC12 DEC ACHTM RTC12: MOV A,OFFTM JZ RTC1 DEC OFFTM ; 20mS program counters RTC1: MOV A,SMPTM JZ RTC2 DEC SMPTM RTC2: MOV A,KEYTM JZ RTC3 DEC KEYTM RTC3: MOV A,TMO_EXT JZ RTC4 DEC TMO_EXT RTC4: MOV A,TMO_INT JZ RTC5 DEC TMO_INT RTC5: MOV A,DELTM JZ RTC6 DEC DELTM RTC6: MOV A,SAVTM JZ RTC7 DEC SAVTM RTC7: POP ACC POP PSW RETI ; TIMER 1 Interrupt ; Indicators Scanning (2mS) INDSCAN: PUSH PSW PUSH ACC MOV A,PHASE JZ PH0 DEC A JZ PW0 DEC A JZ PH1 DEC A JZ PW1 DEC A JZ PH2 PW2: SETB SCAN2 MOV PHASE,#0FFH SJMP PW PW1: SETB SCAN1 SJMP PW PW0: SETB SCAN0 SJMP PW PH2: SETB SCAN1 MOV P1,CD3 CLR SCAN2 SJMP PH PH1: SETB SCAN0 MOV P1,CD2 CLR SCAN1 SJMP PH PH0: SETB SCAN2 MOV P1,CD1 CLR SCAN0 PH: CLR TR1 ;timer 1 stop MOV TH1,PHVH ;timer 1 load (PH phase) MOV TL1,PHVL SETB TR1 ;timer start SJMP EOPH PW: CLR TR1 ;timer 1 stop MOV TH1,PWVH ;timer 1 load (PW phase) MOV TL1,PWVL SETB TR1 ;timer start MOV P1,#0H MOV INCODE,#0FFH JNB RETL,KEYSCAN MOV P1,#0FFH SJMP EOPH KEYSCAN: MOV A,#0EEH KSC: MOV P1,A ;scan keyboard MOV C,RETL XCH A,INCODE RLC A XCH A,INCODE RLC A JC KSC EOPH: INC PHASE POP ACC POP PSW RETI ;Keys codes table KEY_DN .EQU 08H KEY_UP .EQU 04H KEY_SL .EQU 02H KEY_EX .EQU 01H KEY_UD .EQU 0CH ;Font table ; SEDCGABF FONT .DB 10001000B ;code 00H, character 0 .DB 11101110B ;code 01H, character 1 .DB 10010100B ;code 02H, character 2 .DB 11000100B ;code 03H, character 3 .DB 11100010B ;code 04H, character 4 .DB 11000001B ;code 05H, character 5 .DB 10000001B ;code 06H, character 6 .DB 11101100B ;code 07H, character 7 .DB 10000000B ;code 08H, character 8 .DB 11000000B ;code 09H, character 9 .DB 10100000B ;code 0AH, character A .DB 10000011B ;code 0BH, character B .DB 10011001B ;code 0CH, character C .DB 10000110B ;code 0DH, character D .DB 10010001B ;code 0EH, character E .DB 10110001B ;code 0FH, character F .DB 11110111B ;code 10H, character - .DB 11111111B ;code 11H, character blank .DB 10010011B ;code 12H, character t .DB 10100011B ;code 13H, character h .DB 10110111B ;code 14H, character r .DB 10110000B ;code 15H, character P SB .EQU 07H ;S bit position ; ------ Characters codes table ------ CH_E .EQU 00EH ;character "E" code CH_d .EQU 00DH ;character "d" code CH_MIN .EQU 010H ;character "-" code BLANK .EQU 011H ;character "blank" code CH_t .EQU 012H ;character "t" code CH_h .EQU 013H ;character "h" code CH_r .EQU 014H ;character "r" code CH_P .EQU 015H ;character "P" code .END