$TITLE(INTR_0.A51) ; Module INTR_0.A51 Rev 2.0 $XREF ; By Frank Fritz -- Copyright 1997 (C) Frank Fritz $DEBUG ; $NOLIST ; switch off generation of the listing file $NOMOD51 ; switch off 8051 controller defaults and use... $INCLUDE (c:\fsi\inc\reg51.inc) ; Include the 8051 register definitions/declarations. $LIST ; switch on listing. EXTRN DATA (temperature, intr_count, disp_val, ee_address, ee_lsb, ee_msb, ee_cntrl, pwm_cntr, error, cv, duty_cycle, i_old_h, i_old_l) EXTRN DATA (active_pb, limit_cntr_lo, limit_cntr_hi, old_temp, h_list_dptr, c_list_dptr, ai_cntr_hi, ai_cntr_lo) EXTRN XDATA (h_list, c_list) EXTRN BIT (on_targ_flag, pid_error_flag, limit_flag, DS1620_FLAG, eesv_flag, neg_flag, while_flag1, mode, while_dtt_flag, ai_tl_flag) EXTRN BIT (error_flag, test_bit) EXTRN NUMBER (TL0_val, TH0_val, TL1_val, TH1_val, intr_service, read_ee, write_ee, ewen, ewds, setpoint) EXTRN NUMBER (gain_p, gain_i, deadband_val, limit_lo_val, limit_hi_val) EXTRN CODE (pid, dtt) PUBLIC timer0int, clock_strobe ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------- ; TIMER 0 INTERRUPT ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------- int0_code_seg SEGMENT CODE ; segment for interrupt function RSEG int0_code_seg ; switch to this code segment USING 1 ; register bank for interrupt routine ; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ; Module: INTR_0 ; Revision: 2.0 ; Date: August 9, 1997 ; By: Frank Fritz ; About: Interrupt timer 0 controls the event counters, services the EEPROM, display, digital thermometer, PID control, ; and provides control to the AI operating system in determining which device should be active, when the AI ; learning algorithm should be implemented, and when the operating mode (heat or cool) should be changed. ; ; Program Flow ; Called From: Interrupt 0 overflow (FFFF to 0) ; Input: Nothing ; Output: Nothing ; Modifies: Nothing ; Calls: dtt, PID. ; ; History Date Comments ; ---------------- -------------------------------------------------------------------------------------------------------------------------------- ; 08/08/97 Developed code. ; 08/09/97 Cleaned up algo 3,4,5,6 (timer code) added disable interrupt to intr_0 (no intr_1 while intr_0). ; ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- timer0int: CLR EA ; Disable Interrupts. PUSH PSW ; Save environment. MOV PSW,#08H ; Switch to register bank 1 PUSH ACC ; Save environment. PUSH B ; - PUSH DPH ; - PUSH DPL ; - CLR TR0 ; Turn off (stop) Timer 0. MOV TL0,#TL0_val ; Reload interrupt timer. MOV TH0,#TH0_val ; - SETB TR0 ; Turn on (run) Timer 0. MOV A,intr_count ; Count-down interrupt service counter. DEC A ; Count = count -1. MOV intr_count,A ; Save value. JNZ tm0_a ; If not 0 exit, else.... SJMP tm0_b tm0_a: LJMP tm0int_x tm0_b: MOV intr_count,#intr_service ; Reload timeout value. CLR while_flag1 ; Reset the WHILE General-Purpose Timer Flag bit. JNB eesv_flag,tm0int_1 ; If the EEPROM flag is set, then service the EEPROM. LCALL eeprom ; Service the 93C46 EEPROM. tm0int_1: LCALL dtt ; Service the DALLAS DTT. JB error_flag,tm0int_2 ; Don't display temperature if there's an error. MOV disp_val,temperature ; Show the current temperature. tm0int_2: LCALL display ; Service the 2-Digit Hex Display. DJNZ ai_cntr_lo,test_for_limit ; Service the AI stability counter. DEC ai_cntr_hi ; - test_for_limit: DJNZ limit_cntr_lo, test_for_ai ; Count down limit timeout counter. DEC limit_cntr_hi ; - test_for_ai: JB ai_tl_flag,reload_count ; If doing the AI Training / Learning algorithm, then don't do control. JNB pid_error_flag,reload_count ; No error condition - all's well. JNB mode,heat_0 ; PID timeout error at heating condition. ; PID timeout error at cooling condition. cool_0: JNB neg_flag,algo_50 ; Execute algorithm #5 (+E). SJMP algo_60 ; Execute algorithm #6 (-E). heat_0: JNB neg_flag,algo_40 ; Execute algorithm #4 (+E). SJMP algo_30 ; Execute algorithm #3 (-E). ; ---------------------------------------------------- Algorithm #4 (Heat with +E) -------------------------------------------------------------------------------- algo_40: CLR C ; Algorithm #4 - Test temperature conditions. MOV A,temperature ; Is Temp = Old_Temp? SUBB A,old_temp ; - JZ algo_tm10 ; If temp = old_temp then see if timeout. JNC reload_count ; - LCALL algo_10 ; Execute algorithm #1. SJMP reload_count ; Fin. ; ---------------------------------------------------- Algorithm #3 (Heat with -E) -------------------------------------------------------------------------------- algo_30: CLR C ; Algorithm #3 - Test temperature conditions. MOV A,temperature ; Is Temp = Old_Temp? SUBB A,old_temp ; - JZ algo_tm20 ; If temp = old_temp then see if timeout. JC reload_count ; - LCALL algo_20 ; Execute algorithm #1. SJMP reload_count ; Done. ; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- reload_count: MOV limit_cntr_lo,#limit_lo_val ; Reload the limit timeout counter. MOV limit_cntr_hi,#limit_hi_val ; - update_temp: MOV old_temp,temperature ; Update the old temperature value. LJMP tm0int_x ; Done. ; ---------------------------------------------------- Algorithm #5 (Cool with +E) -------------------------------------------------------------------------------- algo_50: CLR C ; Algorithm #5 - Test temperature conditions. MOV A,temperature ; Is Temp = Old_Temp? SUBB A,old_temp ; - JZ algo_tm20 ; If temp = old_temp then see if timeout. JNC reload_count ; - LCALL algo_20 ; Execute algorithm #2. SJMP reload_count ; Exit. algo_tm20: MOV A,limit_cntr_hi ; Has counter timed out? JNZ update_temp ; No timeout. LCALL algo_20 ; Check List for another bit. SJMP reload_count ; Exit. ; ---------------------------------------------------- Algorithm #6 (Cool with -E) -------------------------------------------------------------------------------- algo_60: CLR C ; Algorithm #6 - Test temperature conditions. MOV A,temperature ; Is Temp = Old_Temp? SUBB A,old_temp ; - JZ algo_tm10 ; If temp = old_temp then see if timeout. JC reload_count ; - LCALL algo_10 ; Execute algorithm #1. SJMP reload_count algo_tm10: MOV A,limit_cntr_hi ; Has counter timed out? JNZ update_temp ; No. LCALL algo_10 ; Check List for another bit. SJMP reload_count ; Exit. ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- tm0int_x: POP DPL ; Return from interrupt. POP DPH ; - POP B ; - POP ACC ; Restore MAINLINE environment. POP PSW SETB EA ; Re-enable interrupts. RETI ; ------------------------------------------------------ Subroutine Algorithm 1 -------------------------------------------------------------------------------------- ; Is there another PORT-BIT above current list position? algo_10: JB mode,algo_11 ; Branch if mode = cool. MOV DPTR,#h_list ; Check heat-list. MOV A,h_list_dptr ; Acc = current heat list position. ADD A,DPL ; - SJMP algo_12 ; Continue. algo_11: MOV DPTR,#c_list ; Check cool-list. MOV A,c_list_dptr ; Acc = current cool list position. ADD A,DPL ; - algo_12: INC A ; Acc points to next (above) position. MOV DPL,A ; DPL has low address. MOV R0,A ; Save position. MOVX A,@DPTR ; Get data from RAM. MOV R1,A ; Save the port bit position. CJNE A,#0AAH,algo_13 ; If next data list entry uninitialized (not valid) then do the AI, TL stuff. SETB ai_tl_flag ; Enable (call) the AI TL algorithm within MAINLINE. RET ; Exit. algo_13: JB mode,algo_14 ; There IS another port bit. Make the next bit the active port bit. MOV h_list_dptr,R0 ; Mode is heat, update the heat-list dptr. SJMP algo_15 ; Continue. algo_14: MOV A,R0 ; Acc = List address. CLR C ; C = 0 SUBB A,#08H ; Subtract Base c_list address from list address. MOV c_list_dptr,A ; Mode is cool, update the cool-list dptr. algo_15: MOV active_pb,R1 ; Change the active bit. MOV i_old_h,#00H ; Reset Integrator. MOV i_old_l,#00H ; - CLR pid_error_flag ; Reset error (limit) flag. RET ; Done. ; ------------------------------------------------------ Subroutine Algorithm 2 -------------------------------------------------------------------------------------- ; Is there another PORT-BIT below current list position? algo_20: JB mode,algo_21 ; Branch if mode = cool. MOV DPTR,#h_list ; Check heat-list. MOV A,h_list_dptr ; Acc = current heat list position. ADD A,DPL ; Index DPTR. SJMP algo_22 ; Continue. algo_21: MOV DPTR,#c_list ; Check cool list. MOV A,c_list_dptr ; Acc = current cool list position. ADD A,DPL ; Index DPTR. algo_22: DEC A ; Acc points to previous (below) position. MOV DPL,A ; DPL has low address. MOV R0,A ; Save list address in R0. MOVX A,@DPTR ; Get data from RAM. MOV R1,A ; Save the port bit position in R1. CJNE A,#0AAH,algo_23 ; If next data list entry uninitialized (not valid) then change mode, get low list. CPL mode ; Change mode from heat to cool, or cool to heat. JB mode,algo_26 ; Make the next bit the active port bit. MOV DPTR,#h_list+1 ; Set data pointer to Heat-List address first item. MOV h_list_dptr,#01H ; Mode is heat, get the low-list (1st) port bit). SJMP algo_27 ; Continue. algo_26: MOV DPTR,#c_list+1 ; Set data pointer to Cool-List address first item. MOV c_list_dptr,#01H ; Mode is cool, get the low-list(1st) port bit). algo_27: MOVX A,@DPTR ; Get the port position stored at location #1. MOV active_pb,A ; Change the active bit. MOV i_old_h,#00H ; Reset Integrator. MOV i_old_l,#00H ; CLR pid_error_flag ; Reset error (limit) flag. RET ; Exit. algo_23: JB mode,algo_24 ; There IS another port bit below. Make the next bit the active port bit. MOV h_list_dptr,R0 ; Mode is heat, update the heat-list dptr. SJMP algo_25 ; Continue. algo_24: MOV A,R0 ; Acc = List address. CLR C ; C = 0 SUBB A,#08H ; Subtract Base c_list address from list address. MOV c_list_dptr,A ; Mode is cool, update the cool-list dptr. algo_25: MOV active_pb,R1 ; Change the active bit. MOV i_old_h,#0FFH ; Reset Integrator. MOV i_old_l,#0FFH ; CLR pid_error_flag ; Reset error (limit) flag. RET ; Done. ; -------------------------------------------------------------- Service the 93C46 EEPROM ---------------------------------------------------------------------- ; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ; Module: eeprom ; Revision: 1.0 ; Date: August 8, 1997 ; By: Frank Fritz ; About: This routine services the 93C46 serial EEPROM in functions: READ, WRITE, WRITE-ENABLE, WRITE-DISABLE. ; ; Program Flow ; Called From: INTR_0, controlled from: INIT, MAIN. ; Input: ee_cntrl, ee_msb, ee_lsb. ; Output: ee_msb, ee_lsb. ; Modifies: ee_msb, ee_lsb, R0. ; Calls: clock_strobe. ; ; History Date Comments ; ---------------- -------------------------------------------------------------------------------------------------------------------------------- ; 08/08/97 Developed code. ; ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- eeprom: MOV A,ee_cntrl ; Get the device function control code. (Codes: 01 02 04 08 only) CJNE A,#read_ee,eeprom_2 ; If not 01 (READ) then test for WRITE -- LCALL ee_read ; else do a READ. RET ; Done. eeprom_2: CJNE A,#write_ee,eeprom_4 ; If not 02 (WRITE) then test for EWEN -- LCALL ee_write ; else do a WRITE. RET ; Done. eeprom_4: CJNE A,#ewen,eeprom_8 ; If not 04 (EWEN) then test for EWDS -- LCALL ee_ewen ; else do a EWEN. RET ; Done. eeprom_8: LCALL ee_ewds ; Perform the EWDS function at code 08H or by default. RET ; Done. ; -------------------------------------------------------------- READ the MSB and LSB at ADDRESS ----------------------------------------------------------- ee_read: MOV A,ee_address ; Get the memory address. ANL A,#00111111B ; Mask upper two bits. ORL A,#10000000B ; Set command op-code to READ (1 0 A5 A4 A3 A2 A1 A0). LCALL ee_ws ; Now, clock out the Opcode and address. ; Now read the next 16 data bits (MSB first). SETB P3.2 ; Setup port bit P3.2 for input (DO) mode. LCALL ee_r2 ; Get the MSB from EE memory. MOV ee_msb,A ; Save first 8 bits as MSB. LCALL ee_r2 ; Get the LSB from EE memory. MOV ee_lsb,A ; Save the last 8 bits as LSB. CLR P3.5 ; Disable the 93C46 EEPROM (CS=0). CLR eesv_flag ; Signal EEPROM service complete. RET ; Done with a READ cycle. ee_r2: MOV R0,#08H ; R0 is bit counter for MSB. ee_r3: LCALL clock_strobe ; Clock the next bit in from the EEPROM. MOV C,P3.2 ; Carry has data bit. RLC A ; Rotate carry into Acc. DJNZ R0,ee_r3 ; Check for complete 8 bit xfr. RET ; Done. ; ------------------------------------------------------- Set the EEPROM to the WRITE-ENABLE Function --------------------------------------------- ee_ewen: MOV A,#00110000B ; Perform the EWEN (WRITE Enable) instruction. LCALL ee_ws ; Send the START bit and Opcode out to the EEPROM. CLR P3.5 ; Disable the 93C46 EEPROM (CS=0). CLR eesv_flag ; Signal EEPROM service complete. RET ; Done with an EWEN cycle. ; -------------------------------------------------------------- WRITE the MSB and LSB at ADDRESS ----------------------------------------------------- ee_write: MOV A,ee_address ; Get the memory address. ANL A,#00111111B ; Mask upper two bits. ORL A,#01000000B ; Set command op-code to WRITE (0 1 A5 A4 A3 A2 A1 A0). LCALL ee_ws ; Send START bit and Opcode. ; Now write the next 16 data bits (MSB first). MOV A,ee_msb ; Load the first 8 bits as MSB. LCALL ee_wc ; Write the MSB to EE memory (MSBit first). MOV A,ee_lsb ; Load the last 8 bits as LSB. LCALL ee_wc ; Write the LSB to EE memory. CLR P3.5 ; Disable the 93C46 EEPROM (CS=0). CLR eesv_flag ; Signal EEPROM service complete. RET ; Done with an EWEN cycle. ; Common EEPROM routines. ee_ws: SETB P3.4 ; Set the START BIT. SETB P3.5 ; Enable the 93C46 EEPROM (CS=1). LCALL clock_strobe ; Send the start bit. ee_wc: MOV R0,#08H ; R0 is the bit counter. ee_wl: RLC A ; Rotate MSBit into C. MOV P3.4,C ; Set DI (P3.4 port bit) to next bit value. LCALL clock_strobe ; Clock the next bit out to the EEPROM. DJNZ R0,ee_wl ; Check for complete 8 bit xfr. RET ; Done. ; ------------------------------------------------------- Set the EEPROM to the WRITE-DISABLE Function ----------------------------------------- ee_ewds: MOV A,#00000000B ; Perform the EWDS (WRITE Disable) instruction. LCALL ee_ws ; Send START bit and Opcode. CLR P3.5 ; Disable the 93C46 EEPROM (CS=0). CLR eesv_flag ; Signal EEPROM service complete. RET ; Done with a WRITE and DISABLE WRITE cycle. ; ------------------------------------------------ Service the 2-Digit LED Display ------------------------------------------------------------------------------- ; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ; Module: Display ; Revision: 1.0 ; Date: August 8, 1997 ; By: Frank Fritz ; About: This routine services the 2-digit display. ; ; Program Flow ; Called From: Interrupt 0 (INTR_0) ; Input: disp_val ; Output: Serial data on port bit P3.4 ; Modifies: R0 ; Calls: disp_1, clock strobe. ; ; History Date Comments ; ---------------- -------------------------------------------------------------------------------------------------------------------------------- ; 08/08/97 Developed code. ; ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- display: SETB P3.1 ; Set the display CS to enable. MOV A,disp_val ; Setup ram address. ANL A,#0F0H ; Mask the LSB. Acc now index value. SWAP A ; Move nibble to correct position for offset value. MOV C,ai_tl_flag ; Display "AI Training / Learning Function" on MSD dp. LCALL disp_1 ; Call common commands (send out MSD). MOV A,disp_val ; Setup ram address. ANL A,#0FH ; Mask the MSB. Acc now index value. MOV C, on_targ_flag ; Display "on target flag" at LSD dp. LCALL disp_1 ; Call common commands (send out LSD). CLR P3.1 ; Disable the display. RET ; Exit. disp_1: MOV DPTR,#disp_table ; Load Data Pointer with table address. MOVC A,@A+DPTR ; Get the display data byte. MOV ACC.0,C ; Move status flag to dp position. MOV R0,#08H ; R0 is the bit counter. disp_2: RRC A ; Rotate the LSBit to the Carry bit. MOV P3.4,C ; Move Carry bit to DATA_OUT bit. LCALL clock_strobe ; Send the bit out to the display. DJNZ R0,disp_2 ; Repeat for remaining bits. RET ; Return from common. ; Display table for serial output digit segments. ; Format: ACC. 7 6 5 4 3 2 1 0 ; LED Segment A B C D E F G dp ; ------------------------------------------------------------ disp_table: DB 11111100B ; 1111 1100 - digit: 0 DB 01100000B ; 0110 0000 - digit: 1 DB 11011010B ; 1101 1010 - digit: 2 DB 11110010B ; 1111 0010 - digit: 3 DB 01100110B ; 0110 0110 - digit: 4 DB 10110110B ; 1011 0110 - digit: 5 DB 10111110B ; 1011 1110 - digit: 6 DB 11100000B ; 1110 0000 - digit: 7 DB 11111110B ; 1111 1110 - digit: 8 DB 11110110B ; 1111 0110 - digit: 9 DB 11101110B ; 1110 1110 - digit: A DB 00111110B ; 0011 1110 - digit: B DB 10011100B ; 1001 1100 - digit: C DB 01111010B ; 0111 1010 - digit: D DB 10011110B ; 1001 1110 - digit: E DB 10001110B ; 1000 1110 - digit: F ; -------------------------------------------- Service the 3-wire data link clock line -------------------------------------------------------------- ; ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ; Module: Clock_Strobe ; Revision: 1.0 ; Date: August 8, 1997 ; By: Frank Fritz ; About: This is the common routine to strobe the clock port bit for the clock function of the 3-wire serial bus. ; ; Program Flow ; Called From: EEPROM, dtt, display ; Input: Nothing ; Output: Clock pulse on bit P3.0 ; Modifies: Nothing ; Calls: Nothing ; ; History Date Comments ; ---------------- -------------------------------------------------------------------------------------------------------------------------------- ; 08/08/97 Developed code. ; ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- clock_strobe: NOP ; Routine to toggle the clock line (CLK Strobe). SETB P3.0 ; Set clock line to '1'. NOP ; Delay for 3 usec. NOP ; - NOP ; - CLR P3.0 ; Set clock line back to '0'. RET ; Return with clock in '0' state ; -------------------------------------------------------------------------------------------------------------------------------------------------------------------- END