Cursovaya / МПТ
.docОмский государственный технический университет
Кафедра «Технология электронной аппаратуры»
Электронный кодовый замок с ключом Touch Memory
Пояснительная записка к курсовому проекту по курсу
«Основы микропроцессорной техники»
Р2 КП.210106.011 ПЗ
Руководитель проекта
________Гальперин Ю.А.
Автор проекта
студент гр. РЭ-418
________ Яковлев И.В.
Омск 2011
Омский государственный технический университет
Кафедра «Технология электронной аппаратуры»
ЗАДАНИЕ
на курсовое проектирование по дисциплине
«Основы микропроцессорной техники»
Студент гр. РЭ-418 Яковлев Иван Викторович
Тема проекта: Электронный кодовый замок с ключом Touch Memory
Срок сдачи законченного проекта: «__» ________ 2011 г.
Исходные данные к проекту: (см. приложение к заданию)
Содержание расчетно-пояснительной записки (перечень подлежащих разработке вопросов):
Введение
1. Анализ состояния вопроса и обзор существующих аналогов
2. Разработка схемы устройства
2.1. Разработка структурной (функциональной) схемы
2.2. Разработка электрической принципиальной схемы
2.3 Расчет параметров элементов схемы
3. Разработка конструкции устройства
4. Разработка программного обеспечения
4.1 Выбор и обоснование инструментальных средств разработки
4.2 Разработка алгоритма функционирования устройства
Заключение
Литература
Перечень графического материала с указанием обязательных чертежей:
-
Схема электрическая принципиальная
-
Перечень элементов
-
Блок-схема алгоритма
Дата выдачи задания «__» ________ 2011 г.
Руководитель проекта __________ Гальперин Ю.А.
Задание принято к исполнению «__» ________ 2011 г.
Студент гр. РЭ-418 _____________ Яковлев И.В.
Приложение к заданию №11
Исходные данные к проекту
«Электронный кодовый замок с ключом Touch Memory»
1. Цель и назначение разработки
Электронный кодовый замок предназначен для замены механических секретных устройств и обеспечения повышенного уровня секретности. В качестве ключа используется «электронная таблетка» Touch Memory фирмы Dallas Semiconductor.
2. Технические требования
2.1 Условия эксплуатации
Вид климатического исполнения аппаратной части – УХЛ, категория 4 по ГОСТ 24837-80
2.2 Технические характеристики
2.2.1 Количество запоминаемых 32-разрядных ключей, не менее 128
2.2.2 Напряжение питания, не более, В 12
2.2.3 Потребляемый ток, не более, мА 500
2.3 Требования к конструкции
2.3.1 Габаритные размеры, мм 150х100х60
2.4 Требования к надёжности
2.4.1 Наработка на отказ, ч 30 000
2.4.2 Среднее время восстановления, ч 0,5
3. Дополнительные требования
3.1 В качестве электронных ключей должны быть использованы устройства «Touch Memory» DS1990 или аналогичные.
3.2 Устройство должно иметь возможность перепрограмирования энергонезависимой памяти в случае утери ключа.
3.2 Тип производства мелкосерийное
Задание принято к исполнению «__» _______ 2011 г.
Руководитель проекта __________ Гальперин Ю.А.
Студент гр. _____ __________ Ф.И.О.
Введение
В настоящий момент широкое распространение получили электронные кодовые замки. Их устойчивость к взлому выше чем у механических замков, однако, общая надежность при использовании кода, вводимого с клавиатуры невелика, так как код легко увидеть в момент ввода. Электронный замок с ключом Touch Memory лишен этого недостатка, поскольку все взаимодействия необходимые для открывания замка происходят внутри систему ключ-замок, и недоступны для стороннего наблюдателя. Степень защиты увеличивает также уникальность каждого ключа. В данном проекте рассмотрена конструкция простого в изготовлении и эксплуатации замка, использующего ключ Touch Memory.
Анализ состояния вопроса и обзор существующих аналогов.
В настоящее время всё большую популярность приобретают электронные кодовые замки, пришедшие на смену механическим. Они основываются на применении протокола передачи данных OneWire и разработках фирмы Dallas Semiconductors – iButton [3]. Суть заключается в том, что в герметичный металлический корпус, состоящий из двух частей, помещают микрочип ПЗУ, в который записана определённая комбинация символов, называемая номером ключа. При замыкании контакта между частями корпуса эта комбинация передается по цепи, замкнувшей контакт. Если в этой цепи находится микроконтроллер, то он сможет распознать номер ключа, и выполнить соответствующую подпрограмму, если она есть.
Благодаря доступности элементной базы можно создать такой замок собственными руками. Ниже представлено несколько популярных схем подобных замков, некоторые из которых нашли коммерческое применение.
Рис.1 Замок на основе микроконтроллера семейства PIC.
Данная схема имеет существенный недостаток – общее количество номеров в памяти микроконтроллера не превышает 21, и для надежности разработчик рекомендует записывать один и тот же ключ несколько раз. Также отсутствует возможность стереть выбранный ключ отдельно от остальных.
Рис.2 Схема замка на базе микроконтроллера серии ATMega.
Этот замок позволяет установить два считывателя ключей Touch Memory. Однако управление этим замком представляет трудности, поскольку для изменения режима работы (добавление ключей в память, стирание ключей из памяти и т.д.) необходимо открывать корпус прибора и переставлять перемычку.
В данном проекте используется схема, позволяющая записать до 512 номеров ключей, за счет использования внешней микросхемы ПЗУ, осуществлять легкое добавление и стирание номеров из памяти, а также предусматривающая возможность открытия двери изнутри с помощью кнопки на панели прибора. Также данная схема предоставляет защиту от несанкционированного доступа – программирование возможно только при наличии мастер-ключа, номер которого невозможно изменить после добавления его в память. Максимальное количество ключей можно ограничить изменением переменной MAXK в программе микроконтроллера.
-
Разработка схемы устройства.
Рис.3 Схема электрическая принципиальная электронного замка, разрабатываемого в работе.
Основой конструкции является микроконтроллер DD3 типа AT89C2051 фирмы Atmel. Кнопка SB1, подключенная к порту P3.7, предназначена для программирования ключей. Хранение серийных номеров ключей осуществляется в микросхеме EEPROM DD2 типа 24C02, подключенной к портам P3.4 (SDA) и P3.5 (SCL). Внешняя панелька для iButton подключается к порту P3.3 через разъем X2 и элементы защиты VD4, R3, VD5 и VD6 [1]. Подтягивающий резистор R4 выбран согласно спецификации однопроводной шины. Параллельно внешней панели подключена еще и внутренняя панель XS1, которая используется для программирования ключей. Кнопка открывания двери подключена к порту P3.2 через разъем X1 и такие же элементы защиты, как и для iButton. Исполнительным устройством замка является электромагнит, подключенный через терминал XT1. Электомагнитом управляет ключ VT3, в качестве которого используется мощный МОП-транзистор типа IRF540. Диод VD7 защищает от выбросов самоиндукции. Ключом VT3 управляет транзистор VT2, который инвертирует сигнал, поступающий с порта P3.0 и обеспечивает управляющие уровни 0/12В на затворе VT3. Инверсия нужна для того, чтобы исполнительное устройство не срабатывало во время сброса микроконтроллера, когда на порту присутствует уровень логической единицы. 12-вольтовые управляющие уровни позволили применить обычный МОП-транзистор вместо более дефицитного низкопорогового (logick level) [1]. Для индикации открытия замка используется светодиод, который управляется тем же портом, что и электромагнит, но через транзисторный ключ VT1. Светодиод подключается через тот же разъем, что и iButton. Поскольку устройство должно работать круглосуточно без обслуживания, для повышения надежности установлен супервизор DD1 типа ADM1232. Он имеет встроенный сторожевой таймер и монитор питания. На порту P3.1 микроконтроллер формирует периодические импульсы для сброса сторожевого таймера.
Питание устройства осуществляется от встроенного блока питания, содержащего трансформатор T1, выпрямительный мост VD9-VD12 и интегральный стабилизатор DA1. В качестве резервного источника питания используется батарея BT1-BT10 из 10-ти NiMH-аккумуляторов типоразмера AA емкостью 800мА/Ч.. При питании устройства от сети батарея аккумуляторов заряжается через резистор R10 током примерно 20мА, что составляет 0.025C. Режим зарядки малым током называют капельным (trickle charge). В таком режиме аккумуляторы могут находиться сколь угодно долго, контроль конца процесса зарядки не требуется. Когда аккумуляторы оказываются полностью заряженными, забираемая ими от источника питания энергия превращается в тепло. Но поскольку ток зарядки очень маленький, выделяемое тепло рассеивается в окружающее пространство без сколько-нибудь заметного увеличения температуры аккумуляторов.
При открывании двери на электромагнит подается импульс длительностью 3 секунды. Логика работы устройства такова, что если кнопку открывания двери удерживать, то все это время электромагнит будет под напряжением и, соответственно, дверь будет открытой.
3.Разработка алгоритма работы устройства.
Код мастер-ключа записывается в ПЗУ программ микроконтроллера, начиная с адреса 2FDH. Длина кода составляет 8 байт. Последовательность цифр должна быть такая же, как и на корпусе touch-memory, читать нужно слева направо. Т.е. по адресу 2FDH заносится значение контрольной суммы, затем по адресам 2FEH – 303H шесть байт серийного номера, начиная со старшего байта, и, наконец, по адресу 304H – код семейства. Например, код в целом может выглядеть так: 67 00 00 02 D6 85 26 01.
Программа электронного замка имеет главный цикл, блок-схема которого показана на рис. 4. В основном цикле производится опрос панели, и при наличии ключа считывается его код. Затем этот код проверяется, и если он совпадает с кодом мастер-ключа или любого другого ключа (ключа пользователя), занесенного в память, замок открывается. Также проверяется состояние кнопки открывания двери, и в случае обнаружения нажатия замок тоже открывается.
Рис. 4. Блок-схема основного цикла программы.
Для обработки событий, связанных с программированием, имеются две подпрограммы: PROGT и PROGS, блок-схемы которых приведены на рис. 5. Первая вызывается при считывании кода ключа в режиме программирования, вторая – при нажатии кнопки программирования (NUMBER). Процесс программирования разбит на 3 фазы. При нажатии кнопки NUMBER осуществляется вход в программирование, т.е. переход к фазе 1. Считываемые после этого коды ключей проверяются на совпадение с кодом мастер-ключа, так как только он может позволить продолжить программирование. Если такое совпадение произошло, то осуществляется переход к фазе 2. Если снова будет зарегистрировано касание ключа, то произойдет переход к фазе 3. Еще одно касание ключа приведет к запоминанию его кода и к возврату к фазе 2. Нажатием кнопки NUMBER тоже можно вернуться к фазе 2, но без изменения содержимого памяти. Любое действие в режиме прграммирования вызывает перезагрузку таймера возврата, который имеет интервал 5 секунд и проверяется в основном цикле. Если будет обнаружено обнуление этого таймера, то происходит выход из режима программирования.
Рис.5 Блок-схема подпрограмм программирования.
Номиналы всех элементов схемы соответствуют номиналам, рекомендуемым в документации на микроконтроллер и другие микросхемы. Имеется возможность подключить к портам вывода микроконтроллера семисегментный индикатор, для облегчения процесса программирования. Однако в этом случае количество ключей будет ограниченно возможностями индикатора – 15 шт. при использовании не только цифр но и букв.
4.Разработка конструкции устройства.
Конструктивно устройство выполнено в корпусе размером 150х100х60мм. Большинство элементов, включая трансформатор питания, смонтировано на печатной плате. Аккумуляторы размещаются в стандартных пластмассовых держателях, которые закреплены внутри корпуса рядом с платой. В принципе, можно использовать и другие типы аккумуляторов, например 12-вольтовую кислотную необслуживаемую батарею, применяющуюся в охранных системах. Для подключения исполнительного устройства на плате имеются терминалы типа TB-2, все остальные внешние цепи подключаются через малогабаритные разъемы с шагом контактов 2.54мм. Разъемы расположены на печатной плате и снаружи корпуса недоступны. Провода выходят из корпуса через резиновые уплотнители. Поскольку индикатор HG1, кнопка SB1 и панелька для iButton XS1 используются только во время программирования, они размещены на плате внутри устройства. Это упрощает конструкцию корпуса и делает его более защищенным от внешних воздействий. На боковой панели корпуса размещен только светодиод индикации включения VD13.
Программирование осуществляется следующим образом:
1. Нажать кнопку программирования.
2. Коснуться мастер-ключом панельки.
3. Кнопкой выбрать нужный номер.
4. Коснуться любым ключом панельки.
5. Для выхода из режима программирования нужно просто подождать 5 секунд, после чего индикатор погаснет.
При подключении семисегментного индикатора процесс программирования можно контролировать по сигналам, появляющимся на нём. Схема внешних соединений показана на рис. 6.
Рис.6. Схема внешних соединений.
Заключение.
В данном проекте была рассмотрена конструкция электронного кодового замка с ключом Touch Memory. Данный замок подходит для защиты любых помещений или контейнеров от несанкционированного доступа.
Библиографический список.
-
П. Хоровиц, У.Хилл, Искусство схемотехники, М.: Мир, 2002,-704 с.
-
www.chipdip.ru – информация о компонентах.
-
http://www.maxim-ic.com – информация о ключах Touch Memory.
Приложение 1. Исходный текст программы.
;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 128 ;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