;****************************************************************** ;Кодовая панель на PIC16C84 ;Автор: Aleksander I. Gurin a_gurin@kmv.ru ;Все права на данную разработку принадлежат автору. ;Использование данного устройства в коммерческих целях ;без разрешения автора запрещено. ;(с) 17.08.99 ;****************************************************************** list p=16c84, r=dec errorlevel 0,-305 include "C:\PROGRA~1\MPLAB\p16c84.inc";здесь стоит указать путь к inc-файлу ;соответствующего процессора __config _cp_off & _wdt_on & _pwrte_off & _xt_osc count equ h'0010' ;"счетчик" опроса клавиатуры pres equ h'0011' ;текущее состояние клавиатуры push equ h'0012' ;последняя нажатая клавиша tout equ h'0013' ;счетчик задержки ctout equ h'0014' ;еще один счетчик задержки dummy equ h'0015' ;когда - как ; (обычно,- счетчик попыток набора кода) sum equ h'0016' ;регистр проверки правильности ввода кода flag equ h'0017' ;флаговый регистр ;биты регистра flag ;0 - \ ;1 - - счетчик 10-ти секундной задержки ;2 - / ;3 - зарезервирован ;4 - устанавливается, когда набрана очередная цифра кода ;5 - установлен, когда нажата любая кнопка ;6 - установлен, когда разрешена запись в EEPROM ;7 - не используется ;#define test ;установим режим отладки (после отладки эту строчку нужно закомментировать) org h'00' goto main org h'04' inter bcf intcon,3 ;подпрограмма обработки прерываний bsf status,5 bcf eecon1,4 ;сбросим флаг окончания записи в EEPROM bcf status,5 bsf flag,6 retfie read clrf count ;подпрограмма опроса клавиатуры incf count,1 clrf pres clrf push bcf flag,5 seta comf count,0 ;организуем сканирование клавиатуры "бегущим нулем" movwf porta ;установим порт RA call rest ;задержка на установление сигнала на RA scanb movf portb,0 ;прочитаем порт RB movwf pres comf pres,1 xorlw 0x70 movwf pres swapf pres,1 incf pres,1 decfsz pres,1 ;если была нажата любая кнопка - goto key ;посмотрим, что нажали bcf status,c ;если нажатия не было - rlf count,1 ;прочитаем следующий ряд кнопок btfss count,4 ;если все прочли - goto seta goto eoread ;вернемся в точку вызова. ;Результатом работы следующих семи операторов будет преобразование ;содержимого регистра push к следующему виду (в кавычках - нажатая в ;данный момент кнопка): ;"1" - 09h "2" - 0Ah "3" - 0Ch ;"4" - 11h "5" - 12h "6" - 14h ;"7" - 21h "8" - 22h "9" - 24h ;"*" - 41h "0" - 42h "#" - 44h ;В таком же формате код хранится в EEPROM ;Кстати, при прошивке процессора в EEPROM нужно записать какой-нибудь код. ;Я обычно записываю 42h по адресу 20h в EEPROM. ;Код при этом будет "0". key movf count,0 movwf push rlf push,1 rlf push,1 rlf push,1 movf pres,0 iorwf push,1 btfss flag,5 ;если клавиша нажата и мы еще не "пищали" - call beep ;немного "попищим" bsf flag,5 ;и установим бит 5 регистра flag, ; чтобы больше не "пищать" пока не отпущена ; нажатая кнопка goto scanb ;...и посмотрим не отпустили-ли кнопку eoread return beep movlw 0xff ;подпрограмма включения бипера movwf ctout ifndef test loop1 bcf portb,2 ;проинвертируем биты 1 bsf portb,1 ;и 2 порта RB call rest ;... и подождем bcf portb,1 ;снова проинвертируем биты 1 bsf portb,2 ;и 2 порта RB call rest ;... и снова подождем decfsz ctout,1 goto loop1 bcf portb,1 bcf portb,2 endif return rest movlw 0x19 ;подпрограмма задержки movwf tout loop2 nop ifndef test ;в режиме отладки обойдем эту задержку decfsz tout,1 goto loop2 endif return compare clrf sum ;подпрограмма проверки кода movlw 0x20 movwf fsr mark02 movf 0x00,0 ;просто просуммируем текущие addwf sum,1 ;значения регистров 20h-27h RAM incf fsr,1 ;результат оставим в регистре sum movlw 0x28 xorwf fsr,0 btfss status,z goto mark02 return sec nop ;подпрограмма задержки на 1 сек. ifndef test ;в режиме отладки обойдем эту задержку bsf status,5 movlw 0x0e ;установим пределитель, чтобы получить movwf 0x81 ;задержку примерно в одну секунду bcf status,5 clrwdt ;сбросим WDT sleep ;... и отдохнем endif return main bsf status,5 movlw 0x00 ;установим порт RA на вывод movwf trisa movlw 0x70 ;установим RB0-RB3 и RB7 на вывод movwf trisb ;... RB4-RB6 - на ввод bcf 0x81,7 bcf status,5 movlw 0x00 movwf intcon ;запретим прерывания movlw 0x1f movwf porta clrf portb movlw 0x03 ;число попыток ввода кода movwf dummy mark00 movlw 0x20 ;читаем 8 байт правильного кода movwf fsr ;из EEPROM (20h-27h) mark01 movf fsr,0 ;в ROM (20h-27h) побайтно movwf eeadr bsf status,5 bsf eecon1,rd bcf status,5 movf eedata,0 movwf 0x00 incf fsr,1 movlw 0x28 xorwf fsr,0 btfss status,z goto mark01 movlw 0x20 movwf fsr clrf flag ;сбросим флаги goto loop0 open movlw 0x0f ;включим зеленый светодиод movwf porta call sec ;подождем примерно секунду call beep ;"попищим" немного bsf portb,3 ;и откроем таки дрерь call sec ;примерно на секунду mark04 bsf porta,4 ;выключим зеленый светодиод clrf portb call beep ;еще раз "попищим" goto main ;... и все сначала loop0 clrf intcon ;запретим все прерывания clrwdt ;сбросим WDT call read ;и опросим клавиатуру mark09 movlw 0x00 xorwf push,0 btfss status,z ;если нажата любая кнопка - goto mark05 ;пойдем на mark05 movlw 0x10 ;сбросим RA0-RA3 movwf porta loop7 movlw 0x88 ;разрешим прерывание по RB movwf intcon bsf status,5 ;запустим WDT movlw 0x0f movwf 0x81 bcf status,5 clrwdt sleep btfsc intcon,0 ;если мы проснулись от нажатия на кнопку - goto loop0 ;опросим клавиатуру btfss flag,4 goto loop7 incf flag,1 btfsc flag,2 ;если 10 сек. нет нажатий - goto main ;то стоит навести порядок goto loop7 ;в противном случае - подождем еще... mark05 movlw 0x41 ;... и посмотрим, что нажали. xorwf push,0 btfss status,z ;если нажали "*" - goto mark06 goto mark10 ;пойдем на mark10 mark06 movlw 0x44 xorwf push,0 btfss status,z ;если нажали "#" - goto mark07 goto mark03 ;пойдем на mark03 mark07 movf push,0 ;значит набрана очередная цифра кода xorwf 0x00 ;...запишем ее в EEPROM incf fsr,1 movlw 0x10 ;сбросим счетчик 10-ти секундной задержки movwf flag goto loop0 ;... и будем ждать следующей цифры кода mark03 bcf status,c ;был набран код + "#" call compare ;проверим правильность набора кода incf sum,1 decfsz sum,1 ;если код правильный - goto mark08 goto open ;откроем дверь mark08 decfsz dummy ;"ошибочка" - вычтем одну попытку и проверим,- не была ли она последней goto mark00 ;попробуем еще раз... ; три раза неправильно введен код! ; любые действия пользователя игнорируются! movlw 0x40 movwf dummy clrf porta loop4 clrf portb call beep ;"пищим" примерно минуту call sec bsf porta,4 decfsz dummy,1 goto loop4 goto main ;... и все сначала mark10 bcf status,c ;был набран код + "*" - попытка смены кода call compare ;проверим правильность набора кода incf sum,1 decfsz sum,1 ;если "старый_код" правильный - goto main movlw 0x20 movwf fsr bcf porta,4 ;включим зеленый светодиод call beep ;радостно "пискнем" bsf porta,4 ;и выключим зеленый светодиод loop6 clrwdt call read ;опросим клавиатуру movlw 0x00 xorwf push,0 btfss status,z ;если что-то нажато - goto mark11 goto loop6 mark11 movlw 0x41 ;... проверим, не нажали-ли "*" xorwf push,0 btfss status,z ;если "*" - goto mark12 goto main ;пользователь передумал, пора навести порядок mark12 movlw 0x44 ;... проверим, не нажали-ли "#" xorwf push,0 btfss status,z ;если "#" - goto mark13 goto save ;... значит завершен набор "нового_кода" и его стоит сохранить в EEPROM mark13 movf push,0 ;если мы сюда "дошли" - значит набрана очередная цифра "нового_кода" movwf 0x00 ;запишем ее в RAM incf fsr,1 movlw 0x29 xorwf fsr,0 btfss status,z ;если была попытка ввести 9-ю цифру goto loop6 call sec ;два раза "пискнем" и не будем сохранять "новый_код" call beep call sec call beep goto main save call sec ;перепишем новый код в ееprom bcf porta,4 call beep bsf porta,4 clrwdt movlw 0x20 movwf fsr loop5 bsf status,5 ;разрешим запись (стандартная процедура записи в EEPROM) movlw 0x04 movwf eecon1 bcf status,5 bcf flag,6 movf fsr,0 movwf eeadr movf 0x00,0 movwf eedata movlw 0xc0 movwf intcon bsf status,5 movlw 0x09 movwf 0x81 movlw 0x55 movwf eecon2 movlw 0xaa movwf eecon2 bsf eecon1,wr loop8 bcf status,5 btfss flag,6 ;пока запись не завершена goto loop8 ;наматываем круги clrf intcon clrwdt bcf flag,6 incf fsr,1 ;... и так пока не перепишем байты 20h-27h из ROM в EEPROM movlw 0x28 xorwf fsr,0 btfss status,z goto loop5 bsf status,5 clrf eecon1 clrf eecon2 movlw 0x0e movwf 0x81 bcf status,5 clrwdt ;запись завершена stop bcf porta,4 ;включим зеленый светодиод call beep ;радостно "пискнем" bsf porta,4 ;и выключим зеленый светодиод call sec ;подождем секунду bcf porta,4 ;включим зеленый светодиод call beep ;радостно "пискнем" bsf porta,4 ;и выключим зеленый светодиод goto main ;... и все сначала end end -------------------------------------------------------------------------------- Автор: Aleksander I. Gurin. a_gurin@kmv.ru