Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

курсовой проект / МП замок / lock_asm-ТЕКСТ ПРОГРАММЫ

.htm
Скачиваний:
21
Добавлен:
21.02.2014
Размер:
15.55 Кб
Скачать

; ------ DALLAS DS1990A based lock ------ ; ------ Supports 9 keys + 1 master-key ----- ; ------ wubblick@yahoo.com ------- ;TARGET = AT89C2051 DEBUG = 0 ;0-off, 1-rdfn ports, 2-on #INCLUDE "LIBR51.ASM" ;8051 SFR set CLK_KHZ = 10000 ;OSC frequency, KHZ RTC_MS = 20 ;system clock, MS RTCV = -(CLK_KHZ*RTC_MS)/12 ;Macros: #DEFINE LO(XXX) XXX & 0FFH #DEFINE HI(XXX) (XXX >> 8) & 0FFH #IF (DEBUG>1) #INCLUDE "LIBDEF.ASM" #ENDIF ; ------ Constantes ------ MAXK .EQU 9 ;max number of keys I2C_ADDR .EQU 0A0H ;I2C address for 24C02 (A0,A1,A2=0) TMATMV .EQU 25 ;x20mS TM access delay time AENTMV .EQU 2 ;x20mS TM access enable delay OPNTMV .EQU 150 ;x20mS open pulse duration RETTMV .EQU 250 ;x20mS return to normal mode delay ; ------ Ports ------ DDATA .EQU P1 ;display data port KEYOP .EQU INT0 ;key OPEN OWP .EQU INT1 ;1-Wire port SDA .EQU T0 ;I2C SDA line SCL .EQU T1 ;I2C SCL line SOLEN .EQU RXD ;solenoid control line WD .EQU TXD ;watchdog line KEYSL .EQU P3.7 ;key SELECT ; ------ Variables ------ ;Bit addressing memory: RTPC .EQU 020H ;Real time program counter T040M .EQU O20H.0 ;40mS period bit T080M .EQU O20H.1 ;80mS period bit T160M .EQU O20H.2 ;160mS period bit T320M .EQU O20H.3 ;320mS period bit T640M .EQU O20H.4 ;640mS period bit T1S28 .EQU O20H.5 ;1.28S period bit T2S56 .EQU O20H.6 ;2.56S period bit T5S12 .EQU O20H.7 ;5.12S period bit RTPCS .EQU 021H ;Real time program counter (100mS part) FLAGS1 .EQU 022H PROG .EQU O22H.0 ;program mode flag SNUM .EQU O22H.1 ;set number flag BLINK .EQU O22H.2 ;display blink bit SLKPR .EQU O22H.3 ;SELECT press flag OPNPR .EQU O22H.4 ;OPEN press flag ;Internal Data Memory: .ORG 0030H ;data memory segment ROMD .DS 8 ;touch memory ROM data TEMP .DS 1 ;temporary byte (used in ACCESS90) TMATM .DS 1 ;touch memory access timer AENTM .DS 1 ;TM access enable timer OPNTM .DS 1 ;open timer RETTM .DS 1 ;return timer NUM .DS 1 ;current PRG number (1..9) ;Debugger variables: #IF (DEBUG>1) DBGVA .DS 1 ;debugger variable address in internal memory DBGVV .DS 1 ;debugger variable value in internal memory DBGA .EQU 0FFFFH ;debugger address in external memory #ENDIF STACK: ;stack location ; ------ Vectors Area ------ .ORG 0000H ;reset vector LJMP INIT .ORG 000BH ;INT TIMER 0 vector LJMP RTC ; ------ Main Program ------ INIT: MOV SP,#STACK ;stack init #IF (DEBUG>1) DEBUGINIT ;debug init #ENDIF ;Variables init: CLR A MOV FLAGS1,A ;clear flags 1 MOV TMATM,A ;touch memory access timer clear MOV AENTM,A ;touch memory access delay timer clear MOV OPNTM,A ;open timer clear MOV RETTM,A ;return timer clear ;Periferal setup: CLR TR0 ;timer 0 stop CLR TR1 ;timer 1 stop MOV TMOD,#11H ;timer 0 and timer 1 init MOV TL0,#LO(RTCV) ;timer 0 load MOV TH0,#HI(RTCV) SETB TR0 ;timer 0 start CLR PT0 ;int. timer 0 low priority SETB ET0 ;int. timer 0 enable SETB EA ;interrupts enable ; ------ Main Loop ------ ;Read touch memory: MAIN: LCALL ACCESS90 ;read touch memory JNC NOTCH ;no touch JB PROG,PRG ;jump to process PROG mode LCALL CHKMAS ;check for master code JC OPN LCALL CHKMEM ;check for member code JC OPN SJMP NOTCH PRG: LCALL PROGT ;process PROG mode when touch SJMP NOTCH OPN: LCALL OPEN ;open door ;Check open key: NOTCH: LCALL CHKOPK ;check open key JNC NOOPN LCALL OPEN ;open door ;Check select key: NOOPN: LCALL CHKSLK ;check select key JNC NOSEL LCALL PROGS ;process PROG mode when select ;Open timer check: NOSEL: MOV A,OPNTM JNZ NOCLS LCALL CLOSE ;solenoid off ;Return timer check: NOCLS: MOV A,RETTM JNZ NORET LCALL RETMD ;return to normal mode ;Display, watchdog wakeup: NORET: LCALL DISP ;display LCALL WAKEUP ;watchdog wakeup LJMP MAIN ; ------ Subroutines Area ------ ;Process PROG mode when touch: PROGT: JB SNUM,PRGT1 ;SNUM = 1 ? LCALL CHKMAS ;check for master JC PRGT3 RET PRGT3: SETB SNUM ;set "set number" flag CLR BLINK ;clear blink flag MOV NUM,#1 ;clear number MOV RETTM,#RETTMV ;load return delay RET PRGT1: JB BLINK,PRGT2 ;PROG = 1, BLINK = 0 ? SETB BLINK ;set blink flag MOV RETTM,#RETTMV ;load return delay RET PRGT2: LCALL SAVE ;NVM[NUM] <- new key CLR BLINK ;clear blink flag MOV RETTM,#RETTMV ;load return delay RET ;Process PROG mode when select: PROGS: JB PROG,PRGS1 ;PROG = 1 ? SETB PROG ;set program mode flag CLR SNUM ;clear "set number" flag CLR BLINK ;clear blink flag MOV RETTM,#RETTMV ;load return delay RET PRGS1: JNB SNUM,PRGS2 ;SNUM = 0 ? CLR BLINK ;clear blink flag INC NUM ;NUM + 1 MOV A,NUM CJNE A,#MAXK+1,PRGS2 MOV NUM,#1 PRGS2: MOV RETTM,#RETTMV ;load return delay RET ;Return to normal mode: RETMD: CLR BLINK ;clear blink flag CLR PROG ;clear program mode flag CLR SNUM ;clear "set number" flag RET ;Open door: OPEN: CLR SOLEN MOV OPNTM,#OPNTMV ;load open pulse duration RET ;Solenoid off: CLOSE: SETB SOLEN RET ;Check open key: ;Returns C=1 if pressed CHKOPK: JNB KEYOP,OP1 ;jump if key OPEN pressed CLR OPNPR ;clear OPEN pressed flag OP3: CLR C RET OP1: JB OPNPR,OP2 LCALL DEL15 ;delay 15 mS JB KEYOP,OP3 SETB OPNPR ;set OPEN pressed flag OP2: SETB C ;C <- 1 if key OPEN pressed RET ;Check select key: ;Returns C=1 if pressed CHKSLK: JNB KEYSL,SL1 ;jump if key SELECT pressed CLR SLKPR ;clear SELECT pressed flag SL2: CLR C RET SL1: JB SLKPR,SL2 LCALL DEL15 ;delay 15 mS JB KEYSL,SL2 SETB SLKPR ;set SELECT pressed flag SETB C ;C <- 1 if key SELECT pressed RET ;Watchdog wakeup: WAKEUP: MOV C,T040M MOV WD,C RET ; ------ 1-Wire bus support ------ ;Send reset pulse to OWP and receive presence pulse ;Out: C = 1 if OK TRESET: PUSH B CLR OWP ;OWP <- 0 MOV B,#CLK_KHZ/48 DJNZ B,$ ;delay 500 uS CLR EA ;interrupt disable SETB OWP ;OWP <- 1 (0uS) MOV B,#CLK_KHZ/2000 DJNZ B,$ ;delay MOV C,OWP ;read OWP (14 uS) JNC FAIL ;fail if OWP = 0 MOV B,#CLK_KHZ/500 DJNZ B,$ ;delay MOV C,OWP ;read OWP (66 uS) JC FAIL ;fail if OWP = 1 SETB EA ;interrupts enable MOV B,#CLK_KHZ/100 DJNZ B,$ ;delay MOV C,OWP ;read OWP (312 uS or more) JC RESOK ;OK if OWP = 1 FAIL: CLR C SETB EA ;interrupts enable (if fail) RESOK: POP B RET ;Read/Write byte via 1-Wire bus ;Input: A - input byte ; R4 - CRC ;Out: A - output byte ; R4 - updated CRC TBYTE: PUSH B MOV B,#8 ;perform to read 8 bit TBYTE1: RRC A ;C <- bit LCALL TBIT ;transmit bit DJNZ B,TBYTE1 ;next bit RRC A ;A <- last bit POP B RET ;Read/Write bit via 1-Wire bus ;Input: C - input bit. ; R4 - CRC ;Out: C - output bit ; R4 - updated CRC TBIT: PUSH ACC CLR EA ;interrupts disable CLR OWP ;OWP <- 0 (begin of time slot) NOP ;delay to be sure... NOP ;that thermometr... NOP ;looks low level JC TB_1 SJMP TB_0 ;if data bit = 0 then OWP <- 0 TB_1: SETB OWP ;if data bit = 1 then OWP <- 1 NOP ;delay for data setup TB_0: NOP NOP NOP NOP ; NOP ;10 MHz ! ; NOP MOV C,OWP ;read port 15 uS later PUSH B ;save register B MOV B,#CLK_KHZ/706 DJNZ B,$ ;delay to complete 60 uS slot POP B ;restore register B SETB OWP ;OWP <- 1, end of time slot SETB EA ;interrupts enable PUSH PSW ;update CRC, save C RLC A ;ACC.0 <- C XRL A,R4 ;~ACC.0 if CRC.0 = 1 RRC A ;ACC.0 -> C MOV A,R4 ;A <- CRC JNC BCRC0 XRL A,#18H ;update CRC BCRC0: RRC A ;shift CRC MOV R4,A ;CRC <- new value POP PSW ;restore C POP ACC RET ; Accesses to DALLAS DS1990A touch memory. ; Returns C=1 in case of valid code, else C=0. ; Out: ROMD (8 bytes) ACCESS90: CLR C ;indicate failure MOV A,AENTM ;check access enable timer JNZ RET90 ;exit if AENTM > 0 MOV AENTM,#AENTMV ;reload access enable timer LCALL TRESET ;issue reset pulse JNC RET90 ;leave if no parts on bus CLR C ;indicate failure MOV A,TMATM ;check TM access timer JNZ DIS90 ;exit if TMATM > 0 MOV A,#033H ;read ROM command LCALL TBYTE ;send command byte MOV R0,#ROMD ;init pointer MOV R1,#8 ;init counter MOV R4,#0 ;initialize CRC variable RDMORE: MOV A,#0FFH ;prepare to read a byte LCALL TBYTE ;read byte MOV @R0,A ;save byte INC R0 ;next address DJNZ R1,RDMORE ;repeat until finished MOV A,R4 ;get CRC value in ACC JZ CRC_OK ;jump if successful CLR C ;indicate failure SJMP RET90 CRC_OK: LCALL CHKZ ;check code for zero JNC RET90 ;invalid code DIS90: MOV TMATM,#TMATMV RET90: RET ;return to caller ;Check TM code for zero: CHKZ: MOV R0,#ROMD ;init pointer MOV R1,#8 ;init counter NEXTZ: MOV A,@R0 ADD A,#0FFH ;C = 1 if A>0 JC OKZ INC R0 ;next address DJNZ R1,NEXTZ OKZ: RET ; I2C NVM memory 24C02 support: ; ; I2C - bus supported subroutines: ; ; I2C_WR - Write byte from A via I2C bus ; I2C_RD - Read byte to A via I2C bus ; I2C_LRD - Read last byte to A via I2C bus (no ASK) ; I2C_SUB - Send subaddress from R1 to I2C device ; I2C_SUBR - Send subaddress from R1 and perform read. ; I2C_STOP - Stop condition generation on I2C bus ; ; I2C slave address I2C_ADDR (0A0H for 24C02 A0,A1,A2=0) ; I2C data line SDA ; I2C clock line SCL ;Send subaddress to I2C device. ;Input: R1 - subaddress. I2C_SUB: MOV A,#I2C_ADDR ;I2C device address, write mode LCALL I2C_WR ;send device address MOV A,R1 ;subaddress LCALL I2C_WR ;send subaddress RET ;Send subaddress and perform read. ;Input: R1 - subaddress. I2C_SUBR: LCALL I2C_SUB ;send subaddress LCALL I2C_STOP ;stop MOV A,#I2C_ADDR+1 ;I2C device address, read mode LCALL I2C_WR ;send device address RET ;Send byte from A via I2C bus. I2C_WR: PUSH B MOV B,#9H ;bit counter load SETB C ;set C, for bit 9 = 1 (when ACK) LCALL SDA0 ;SDA 1 -> 0 - start I2CWR1: LCALL SCL0 ;SCL 1 -> 0 RLC A JC OUTP1 ;jump if bit = 1 LCALL SDA0 ;else SDA=0 SJMP OUTP0 OUTP1: LCALL SDA1 ;SDA=1, if bit = 1 OUTP0: LCALL SCL1 ;SCL 0 -> 1 DJNZ B,I2CWR1 ;loop POP B RET ;Read byte via I2C to A. I2C_RD: MOV A,#1H ;A init to receive 8 bit I2CRD1: LCALL SCL0 ;SCL 1 -> 0 LCALL SDA1 ;SDA=1 - SDA line release LCALL SCL1 ;SCL 0 -> 1 MOV C,SDA ;move bit from SDA line to C RLC A ;shift bit C into A JNC I2CRD1 ;loop until C = 1 LCALL SCL0 ;SCL 1 -> 0 LCALL SDA0 ;SDA=0 - ACK generation LCALL SCL1 ;SCL 0 -> 1 RET ;Read byte via I2C to A without ASK ;(receive last byte). I2C_LRD: MOV A,#1H ;A init to receive 8 bit I2CLRD1: LCALL SCL0 ;SCL 1 -> 0 LCALL SDA1 ;SDA=1 - SDA line release LCALL SCL1 ;SCL 0 -> 1 MOV C,SDA ;move bit from SDA line to C RLC A ;shift bit C into A JNC I2CLRD1 ;loop until C = 1 LCALL SCL0 ;SCL 1 -> 0 LCALL SCL1 ;SCL 0 -> 1 when SDA=1: no ACK RET ;STOP condition generation: I2C_STOP: LCALL SCL0 LCALL SDA0 LCALL SCL1 LCALL SDA1 RET ;SDA and SCL lines control: SDA0: CLR SDA ;SDA 1/0 RET SDA1: SETB SDA ;SDA 0/1 RET SCL0: CLR SCL ;SCL 1/0 RET SCL1: SETB SCL ;SCL 0/1 RET ;EEPROM address map: ;00H - page not used ;08H - touch memory code 1 ;10H - touch memory code 2 ;... ;Save new key: ;NUM - key number (1..9) SAVE: MOV A,NUM MOV B,#8 MUL AB ;NUM x 8 MOV R1,A ;R1 <- subaddress LCALL I2C_SUB ;send subaddress MOV R1,#8 ;init counter MOV R0,#ROMD ;init pointer DOWR: MOV A,@R0 LCALL I2C_WR ;send data INC R0 DJNZ R1,DOWR LCALL I2C_STOP ;stop LCALL DEL15 ;delay 15mS to page write RET ;Check for member: ;Returns C=1 if code O.K. CHKMEM: MOV R2,#1 ;init key counter NEXT: MOV A,R2 MOV B,#8 MUL AB ;NUM x 8 MOV R1,A ;R1 <- subaddress LCALL I2C_SUBR ;send subaddress and read mode MOV R1,#8 ;init counter MOV R0,#ROMD ;init pointer DORD: LCALL I2C_RD ;read data XRL A,@R0 JNZ INVAL ;jump if invalid code INC R0 ;next address DJNZ R1,DORD LCALL I2C_LRD ;stop read LCALL I2C_STOP SETB C ;valid code, C <- 1 RET INVAL: LCALL I2C_LRD ;stop read LCALL I2C_STOP INC R2 ;next key MOV A,R2 CJNE A,#MAXK+1,NEXT CLR C ;invalid code, C <- 0 RET ;Check for master: CHKMAS: MOV R1,#8 ;init counter MOV DPTR,#MK ;init pointer to ROM MOV R0,#ROMD+7 ;init pointer to RAM DOCM: CLR A MOVC A,@A+DPTR ;read ROM XRL A,@R0 ;ROM[DPTR] = RAM[R0] ? JNZ INVM ;jump if invalid code INC DPTR ;next ROM address DEC R0 ;next RAM address DJNZ R1,DOCM SETB C ;valid master code, C <- 1 RET INVM: CLR C ;invalid master code, C <- 0 RET ;Display support: ;Input: NUM = value ;if PROG = 0 display is blanked ;if PROG = 1 and BLINK = 1 display is blinking DISP: MOV A,#BLANK ;blank display if PROG = 0 JNB PROG,IND MOV A,#CH_P ;display "P" if SNUM = 0 JNB SNUM,IND MOV A,NUM ;display NUM if PROG = 1 and SNUM = 1 IND: MOV C,T320M ;load blink period bit ORL C,/BLINK ;check blink enable bit JC IND1 MOV A,#BLANK IND1: MOV DPTR,#FONT ;font table pointer MOVC A,@A+DPTR ;read font MOV DDATA,A ;indicator control RET ;Delay 15mS: DEL15: PUSH B PUSH ACC MOV B,#30 DEL05: MOV A,#CLK_KHZ/48 DJNZ ACC,$ LCALL WAKEUP ;watchdog wakeup DJNZ B,DEL05 POP ACC POP B RET ; ------ Interrupt Holders ------ ; TIMER 0 Interrupt ; System clock (20mS) RTC: 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 ;advance Real Time Program Counter ; 20mS program counters RTC1: MOV A,TMATM JZ RTC2 DEC TMATM RTC2: MOV A,AENTM JZ RTC3 DEC AENTM RTC3: MOV A,OPNTM JZ RTC4 DEC OPNTM RTC4: MOV A,RETTM JZ RTC5 DEC RETTM RTC5: POP ACC RETI ; FGABSCDE FONT .DB 01001000B ;code 00H, character 0 .DB 11101011B ;code 01H, character 1 .DB 10001100B ;code 02H, character 2 .DB 10001001B ;code 03H, character 3 .DB 00101011B ;code 04H, character 4 .DB 00011001B ;code 05H, character 5 .DB 00011000B ;code 06H, character 6 .DB 11001011B ;code 07H, character 7 .DB 00001000B ;code 08H, character 8 .DB 00001001B ;code 09H, character 9 .DB 00001010B ;code 0AH, character A .DB 00111000B ;code 0BH, character B .DB 01011100B ;code 0CH, character C .DB 10101000B ;code 0DH, character D .DB 00011100B ;code 0EH, character E .DB 00011110B ;code 0FH, character F .DB 11111111B ;code 10H, character blank .DB 10111111B ;code 11H, character - .DB 00001110B ;code 12H, character P ;Characters codes table: BLANK .EQU 010H ;character "blank" code CH_MIN .EQU 011H ;character "-" code CH_P .EQU 012H ;character "P" code ;Master key code: MK .DB 062H,000H,000H,002H,0D6H,089H,029H,001H #IF (DEBUG>1) #INCLUDE "LIBDBG16.ASM" #ENDIF .END