Читаем Микроконтроллеры AVR: от простого к сложному полностью

.INCLUDE "1200def.inc"; AT90S1200 @ 1 МГц

.CSEG

.EQU evReset=1

.EQU evPassed=3

.EQU evDenied=5

.EQU KeyRing=1; Код клавиши звонка

.EQU KeyEnter=9; Код клавиши сброса

.EQU NewPassKey=2; Код клавиши, нажимаемой для ввода нового пароля

.EQU KeyLen=5; Длина секретного кода не должна быть больше 5 цифр

.EQU FreqKeyPressed=50; Константа частоты для выдачи писка при нажатии кнопок

.EQU Note_1=227; Константы частот и длительности нот

.EQU Note_la0 = Note_1

.EQU Note_2=202

.EQU Note_ci0 = Note_2

.EQU Note_3=191

.EQU Note_do1 = Note_3

.EQU Note_4=170

.EQU Note_re1 = Note_4

.EQU Note_5=152

.EQU Notejni.1 = Note_5

.EQU Note_6=143

.EQU Note_fa1 = Note_6

.EQU Note_7=128

.EOU Note_sol1 = Note_7

.EOU Note_8=114

.EOU Note_la1=Note_8

.EOU Note9=101

.EOU Sote_ci1=Note_9

.EOU Note_10=96

.EOU Note_do2 = Note_10

.EGU Note_11=85

.EOU Note_re2 = Note_11

.EOU Note_12=76

.EOU Note_mi2 = Note_12

.EOU Note_13=72

.EOU Note_fa2 = Note_13

.EOU Note_14=64

.EOU Note_sol2 = Note_14

.EOU DURATION = 350

.EOU Time_1=1000/Note_1

.EOU Time_2=1000/Not e_2

.EOU Time_3=1000/Note_3

.EOU Time_4=1 000/Not e_4

.EOU Tinve_5=1000/Note_5

.EOU Time_6=1000/Note_6

.EOU Time_7=1000/Note_7

.DEF KeyPass=r0

.DEF tmp=r0

.DEF KeyPass1=r1

.DEF KeyPass2=r2

.DEF KeyPass3=r3

.DEF KeyPass4=r4

.DEF KeyPass5=r5

.DEF SSRE6=r6

.DEF DelayVar=r7

.DEF IntUse0=r8

.DEF LastKey=r9

.DEF ZerReg=r10

.DEF Time0=r16; Время, увеличивается 3815 раз в секунду

.DEF Time1=r17; Время, увеличивается раз в 67 секунд

.DEF Time2=r18; Время, увеличивается раз в 47721 час,

; насыщается за 50 суток

.DEF EEadr=r20; Адрес для записи в EEPROM, равен 255.

; если в текущий момент запись не производится

.DEF EventType=r21

.OEF BeepVar=r21

.DEF TimerEEByte=r22

.DEF TimerEEBit=r23

.DEF Key=r24

.DEF BeepDuration=r25

.DEF FreqConst=r26

.DEF IntUse1=r27

;.DEF PassLoopCounter=r28

.DEF Flags=r29

; bit 0 — Password accepted

.ORG 000

          clr ZerReg

          rjmp RESET

.ORG 002

;======================

; Здесь оказываемся при возникновении прерывания от таймера 3 раза в секунду

;======================

; Таймер используется как RTC и для вывода информации EEPR0N

; Увеличение счетчика времени

         in SSREG.SREG

         subi Time0,1

         adc Time1,ZerReg

         абс Time2,ZerReg

         brcc TimeOk

         com Time1; Если проело переполнение, счетчик времени остановлен

         com Time2

TimeOk:

;Чтение данных из EEPROM и выдача на внешний порт.

;Процедура обработки прерывания будет вызвана не раннее, чей через 300-3∙4 мс

;после последнего обращения к EEPROM, поэтому проверка готовности EEPROM не

;производится, она должна быть уже готова.

         andi TimerEEByte,$3F

         out EEAR,TiirerEEByte

         sbi EECR,EERE;set EEPROH Read strobe

         sbi EECR,EERE;set EEPROH Read strobe 2nd time

         in IntUse0,EEDR;get data

         andi TimerEEBit,7

         brne Bitlop

         inc TimerEEByte

Bitlop: inc TimerEEBit; =1.8

         mov IntUsel, TimerEEBit

         rol IntUse0

BitShift:; Выбираем посылаемый бит

         ror IntUse0; Используется как текущий считанный EEPROM байт

         dec IntUse1; Используется как счетчик

         brne BitSbift

         in IntUse1,PORTD

         bst IntUse0,0

         bid IntUse1,0

         out PORTD,IntUsel

         out SREG.SSREG

         reti

;===============

;Здесь оказываемся при включении питания схемы

;===============

RESET:

;Настройка микросхемы и программы.

         Idi r31,$8F; Настраиваем направление работы портов

         out DDRB,r31

         ldi r31,$03

         out DDRD,r31

         ldi r31,$05; Настраиваем таймер

         out TCCRO,r31

         ldi r31,$02

         out TIMSK,r31; Разрешаем прерывания при переполнении таймера

         ldi r31.2

         mov KeyPass1,r31 ; Загружаем пароль по умолчанию

         ldi r31,3

         mov KeyPass2,r31

         ldi г31.2

         mov KeyPass3,r31

         ldi r31,3

         mov KeyPass4,r31

         ldi r31,2

         clr Time1; Сбрасываем счетчик времени

         clr Time2

         rcall WrireEEPROM

         sei; Разрешаем прерывания

Mainloop:

         ; Подготавливаемся к вводу пароля.

         clr r30,0

         clr r31,0

         ori Flags,1; При предъявлении пароля пока ошибок не было

         clr KeyPass

         clr LastKey

Passloop:; Цикл ввода пароля

         rcall GetKey; Записывает в переменную Key код нажатой клавиши

         brtc Passloop; и устанавливает бит Т, если клавиша нажата

         cp Key,LastKey

         breq Passloop; Если предыдущая клавиша еще не отпущена

         cpi Key,KeyEnter

         breq MainLoop; Если нажат сброс, начинаем ввод строки с начала

         ldi FreqConst,FreqKeyPressed

         ldi BeepDuration,5

         rcall Beep; Выдача короткого звукового сигнала

         mov LastKey,Key

         inc r30

         ld KeyPass.Z

         cpse Key,KeyPass; Сравниваем введенную цифру и цифру пароля из ОЗУ.

         andi Flags,~1; если ошибка, сбрасываем бит успешности пароля.

         cpi r30,Keylen; Длина секретного кода.

         brne PassLoop

         ; Вывод бита на внешний вывод порта и запись события в EEPROM

         ldi EventType,evDenied

         bst Flags,0

         brtc PasswordDenied

         sbi PORTD,1; Если пароль совпал, включаем соленоид

         ldi EventType,evPassed

PasswordDenied:

         rcall WrireEEPROW

          ; Открытие двери при совпадении кода или цикл ожидания при ошибке

          ldi Key,5

Openloop:

          rcall Delay100

          ldi BeepDuration,Time_7/2

          ldi FreqConst,Note_7

          rcall Beep

          dec Key

      sbic PIND,2; Если сработал концевик (открылась дверь), то выходим

          brne Openloop; или выходим из цикла по тайм-ауту

          cbi PORTD,1; Отключаем соленоид

          ; Нажатие на клавишу NewPassKey в этой месте приводит к загрузке

          rcall GetKey; нового секретного кода

          brtc NainLoop

          cpi Key,NewPassKey

          brne Mainloop

          sbrs Flags,0; Если старый был предъявлен верно

          rjmp Mainloop

;Ввод нового, секретного кода,

          ldi FreqConst,Note_3;Проигрывание "приглашения" для изменения пароля

          ldi BeepDuration,20

          rcall Beep

          ldi FreqConst,Note_5

          ldi BeepDuration,20

          rcall Beep

          ldi FreqConst.Note_7

          ldi BeepDuration,20

          rcall Beep

          rcall Delay100

NewPassword:

          clr LastKey

          clr r30

          clr r31

NewPassLoop:

          rcall GetKey

          brtc NewPassLoop; Ожидаем нажатия клавиши

          cp Key,LastKey

          breq NewPassLoop; Если клавиша еще не отпущена, продолжаем цикл

          cpt Key,KeyEnter

          breq NewPassword; Если сброс, начинаем ввод строки с начала

          mov LastKey,Key

          ldi BeepDuration,2*10

          ldi FreqConst,2*FreqKeyPressed

          rcall Beep; Удлиненный звуковой сигнал

          inc r30

          St Z,Key; Сохраняем введенную цифру

          cpi r30,Keylen; Длина секретного кода

          brne NewPassLoop

          rcall Delay100

          ldi FreqConst,Note_7; Проигрывание мелодии, говорящей об

          ldi BeepDuration,20; успешной изменении пароля

          rcall Beep

          ldi FreqCoost, Note_5

          ldi BeepDuration,20

          rcall Beep

          ldi FreqConst,Note_3

          ldi BeepDuration,20

          rcall Beep

          rjmp MainLoop

;==============

;Дальше идут процедуры, вызываемые из основной программы

;==============

Веер:; Выдача звукового сигнала

          ldi BeepVar,20

Beep1: mov DelayVar.FreqConst

Delay2: rjmp NopJmp1; 2 +

NopJmp1:dec DelayVar; 1 + = 5 мкс

          brne Delay2;2 +

          sbi P0RTB.7

          mov DelayVar.FreqConst

Delay3: rjrep NopJmp2

NopJmp2:dec DelayVar

          brne Delay3

          cbi P0RTB.7

          dec BeepVar

          brne Beep1

          dec BeepDuration

          brne Beep

          sei

          ret

;================

; Задержка на время порядка секунды

Delay100:

          ldi BeepOuration,3

D100_3: clr FreqConst

D100_2: clr DelayVar

D100_1: dec DelayVar

          brne D100_1

          dec FreqConst

          brne D100_2

          dec BeepDuration

          brne D100_3

          ret

;================

; проверка приема данных от клавиатуры

GetKey:

          clt; Сброс признака, что была нажата клавиша

          ldi r31,$0Е; Младшая тетрада — запрос в порт, старшая -

          rcall GetKeyAnswer; смещение ответа

          brne KeyPressed

          ldi r31,$3D

          rcall GetKeyAnswer

          brne KeyPressed

          ldi r31,$6B

          rcall GetKeyAnswer

          brne KeyPressed

          ldi r31,$97

          rcall GetKeyAnswer

          brne KeyPressed

          ret

KeyPressed:

          set

          swap r31

          andi r31,$0F

          swap Key

          andi Key,$07

CCFind: inc r31; Поиск, какой конкретно бит установлен

          lsr Key

          brcc CCFind

          breq NoMu1

          clt; Если нажато несколько клавиш, то не нажата ни одна

NoNul: mov Key,r31

; Проверка, нажата ли кнопка Ring, если нажата, то будет выдан звуковой сигнал

; без сообщения об этом вызывающей функции

          cpi Key,KeyRiog

          breq Ring

          rjmp NoRing

Ring: sbrc KeyPass1,0; Выбор типа мелодии в зависимости от четности

          rjmp SimpleRing; старей цифры секретного кода

          rcall Delay100

;Проигрываем сложную мелодию (Отговорила роща золотая)

;1 ми 1/8

          ldi FreqConst,Note_mi1

          ldi BeepDuration,2*DURATI0N/Note_mi1

          rcall Beep_Del

;1 ми 1/8

          ldi F reqConst,Note_mi1

          ldi BeepDuration,2*DURATION/Note_mi1

          rcall Beep_Del

; 1 ми 1/8

          ldi FreqConst,Notejnii

          ldi BeepDuration.2*DURATION/Note_mi1

          rcall Beep_Del

;1 фа 3/8

          Idi FreqConst,Note_fa1

          ldi BeepDuration,6*DURATI0N/Note_fa1

          rcall Beep_Del

;1 ми 1/8

          ldi F reqConst,Note_mi1

          ldi BeepDuration,2*DURATION/Note_mi1

          rcall Beep_Del

;1 фа 3/8

          Idi FreqConst,Note_fa1

          ldi BeepDuration,6*DURATI0N/Note_fa1

          rcall Beep_Del

;1 ми 1/16 (1/8)

          ldi FreqCoost,Note_mi1

          ldi BeepDuration,2*DURATI0N/Note_mi1

          rcall Beep_Del

;1 ре 1/8

          ldi FreqConst,Note_re1

          ldi BeepDuration,2*DURATlON/Note_re1

          rcall Beep_Del

;1 до 1/8

          ldi FreqConst,Note_do1

          ldi BeepDuration,2*DURATION/Note_do1

          rcall Beep_Del

;1 си 1/4

          ldi FreqConst,Note_ci0

          ldi BeepOuration,4*DURATION/Note_ci0

          rcall Beep_Del

; 1 фа 3/8

          ldi FreqConst.Note_fa1

          ldi BeepDuration,6*DIRATION/Note_fa1

          rcall Beep_Del

;1 Фа 1/8

          ldi FreqConst,Note_fa1

          ldi BeepDuration,2*DURATION/Note_fa1

          rcall Beep_Del

; 1 ми 3/8

          ldi FreqConst.Note_mi1

          ldi BeepDuration,6*DURATIOIN/Note_mi1

          rcall Beep_Del

;1 ми 1/6

          ldi FreqConst.Note.mil

          ldi BeepDoration. 3*DURATI0N/Note_mi1

          rcall Beep_Del

; 1 ми 1/8

          ldi FreqConst.Note_mi1

          ldi BeepDuration,2*DURATIOIN/Note_mi1

          rcall Beep_Del

;1 Фа 1/8

          ldi FreqConst,Note_fa1

          ldi BeepDuration,2*DURATION/Note_fa1

          rcall Beep_Del

;1 си 1/8

          ldi FreqConst,Note_ci0

          ldi BeepOuration,2*DURATION/Note_ci0

          rcall Beep_Del

;1 ре 1/8

          ldi FreqConst,Note_re1

          ldi BeepDuration,2*DURATlON/Note_re1

          rcall Beep_Del

;1 Фа 1/8

         ldi FreqConst,Note_fa1

         ldi BeepDuration,2*DURATION/Note_fa1

         rcall Beep_Del

; 1 ми 5/8

         ldi FreqConst.Note_mi1

         ldi BeepDuration,10*DURATIOIN/Note_mi1

         rcall Beep_Del

         rjmp EndRing

SimpleRing:; Проигрываем простую мелодию

         ldi F reqConst,Note_7

         ldi BeepDuration,1

         rcall Beep

         ldi FreqConst,Note_5

         ldi BeepDuration,1

         rcall Beep

         ldi FreqConst,Note_3

         ldi BeepDuration,1

         rcall Beep

         ldi FreqConst,Note_5

         ldi BeepDuration,1

         rcall Beep

EndRing:

         clt; Сбрасываем флаг нажатия клавиши

NoRing:

         ret

;===================

Beep_Del:; Короткая пауза перед нотой и сама нота

         ldi BeepVar,50

Del2: clr DelayVar

Del1: dec DelayVar

         brne Del1

         dec BeepVar

         brne Del2

         cli

         rjmp Beep

;===================

; Сканирование клавиатуры: установка на выходных линиях заданного кода и прием

; ответа вызывается из функции GetKey

GetKeyAnswer:

        mov Key,r31

        andi Key,$0F

        out PORTB,Key

        clr DelayVar

Delay1: dec DelayVar

        brne Delay1

        in Key,PINB

        com Key

        andi Key,$70;Если что-то было найдено, флаг Z не нулевой

        ret

;===================

; Запись события EventType в текущую ячейку EEPR0M памяти и обнуление времени

WrireEEPROM:

        ; Поиск последней записи

        clr tmp

        ldi EEadr,2

FincNextAdr:

        out TCNTO,ZerReg; Пока не сработал таймер, читающий из EEPROM (через 300 мс). все операции должны быть завершены

        subi EEadr, — 2

        cpi EEadr,62

        brne EERead

        ldi EEadr,4; Если дошли до 64-ro адреса, начинаем с начала

EERead

        sbic EECR,EEWE; Ждем обнуления бита EEWE

        rjmp EERead

        out EEAR,EEadr; Подготавливаем адрес

        sbi EECR,EERE; Устанавливаем бит для синхронизации

        sbi EECR,EERE; Дважды

        in r31,EEDR; Читаем данные

        dec tirp; Если было 256 неудачных попыток найти бит

       breq NoZav; признак последней записи, значит, его нет вообще, значит, пишем по любому адресу

        sbrs r31,0

        rjmp FindNextAdr

NoZav: andi r31,$FE

EEWrite0:; Запись дня сброса флага, указывающего на последнюю запись

        sbic EECR,EEWE

        rjmp EEWrite0

        out EEAR,EEadr

        out EEDR,r31

        sbi EECR,EEWE

        inc EEadr

EEWrite1:; Запись старшего байта времени

        sbic EECR,EEWE

        rjmp EEWrite1

        out EEAR,EEadr

        out EEDR,Time2

        sbi EECR,EEWE

        inc EEadr

EEWrite2:; Запись времени, типа события и флага последней записи

        sbic EECR,EEWE

        rjmp EEWrite2

        out EEAR,EEadr

        mov r31,Time1

        andi r31,SF8

        or r31,EventType

        out EEDR,r31

        sbi EECR,EEWE

        clr Time1; Счетчик считает время между записями в EEPROM,

        clr Time2; поэтому сбрасываем его

        ret

.EXIT

; Таблица использования линий микроконтроллера

; Порт В используется для подключения клавиатуры и динамика

; PORTB,7 — вывод на динамик

; PORTB,0…3 — выходы на сканирование клавиатуры

; PORTB,4…6 — входы от 12-клавишной клавиатуры, подключены к +5 В через резисторы

; Порт D используется для управления замком, выдачи информации и проверки двери

; PORTD.0 используется для вывода информации из ЕЕРАОН, на нем с частотой

; 3815 Гц (@ 1МГц) побитно выводится все ее содержимое

; PORTD.1 Подключен на электромагнит или двигатель, единица разрешает открытие

; PORTD.2 Подключен на концевику, срабатывающему (=0) при открытии

Перейти на страницу:

Все книги серии Библиотека инженера

Похожие книги

Электроника для начинающих (2-е издание)
Электроника для начинающих (2-е издание)

В ходе практических экспериментов рассмотрены основы электроники и показано, как проектировать, отлаживать и изготавливать электронные устройства в домашних условиях. Материал излагается последовательно от простого к сложному, начиная с простых опытов с электрическим током и заканчивая созданием сложных устройств с использованием транзисторов и микроконтроллеров. Описаны основные законы электроники, а также принципы функционирования различных электронных компонентов. Показано, как изготовить охранную сигнализацию, елочные огни, электронные украшения, устройство преобразования звука, кодовый замок и др. Приведены пошаговые инструкции и более 500 наглядных рисунков и фотографий. Во втором издании существенно переработан текст книги, в экспериментах используются более доступные электронные компоненты, добавлены новые проекты, в том числе с контроллером Arduino.

Чарльз Платт

Радиоэлектроника / Технические науки
Электроника для начинающих
Электроника для начинающих

В ходе практических экспериментов рассмотрены основы электроники и показано, как проектировать, отлаживать и изготавливать электронные устройства в домашних условиях. Материал излагается последовательно от простого к сложному, начиная с простых опытов с электрическим током и заканчивая созданием сложных устройств с использованием транзисторов и микроконтроллеров. Описаны основные законы электроники, а также принципы функционирования различных электронных компонентов. Показано, как изготовить охранную сигнализацию для защиты от проникновения в дом, елочные огни, электронные украшения для одежды, устройство преобразования звука, кодовый замок, автономную роботизированную тележку и др. Приведены пошаговые инструкции и более 500 наглядных рисунков и фотографий.Для начинающих радиолюбителей

Паоло Аливерти , Чарльз Платт

Радиоэлектроника / Технические науки
Искусство схемотехники. Том 3 (Изд.4-е)
Искусство схемотехники. Том 3 (Изд.4-е)

Широко известная читателю по предыдущим изданиям монография известных американских специалистов посвящена быстро развивающимся областям электроники. В ней приведены наиболее интересные технические решения, а также анализируются ошибки разработчиков аппаратуры: внимание читателя сосредотачивается на тонких аспектах проектирования и применения электронных схем. На русском языке издается в трех томах. Том 3 содержит сведения о микропроцессорах, радиотехнических схемах, методах измерения и обработки сигналов, принципах конструирования аппаратуры и проектирования маломощных устройств, а также обширные приложения. Для специалистов в области электроники, автоматики, вычислительной техники, а также студентов соответствующих специальностей вузов и техникумов.

Пауль Хоровиц , Уинфилд Хилл

Техника / Радиоэлектроника