Разработка программы для управления домофоном, на микроконтроллере LM3S316

Описание работы элементов программы в виде блок-схем. Анализ структурной схемы модели домофона. Блок-схема работы открытия двери ключом. Моделирование в Proteus: принцип динамического опроса и индикации, внешний вид жидкокристаллического дисплея.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 12.04.2019
Размер файла 1,4 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

Содержание

  • 1. Техническое задание
  • 1.1 Цель курсового проекта
  • 1.2 Требования к модели
  • 2. Анализ технического задания
  • 3. Описание устройства
  • 3.1 Описание работы элементов программы в виде блок-схем
  • 4. Моделирование в Proteus
  • 4.1 Принцип динамического опроса и индикации
  • 4.2 ЖК-дисплей
  • Заключение
  • Список использованных источников
  • Приложение А
  • Приложение Б
  • 1. Техническое задание
  • 1.1 Цель курсового проекта
  • блок схема домофон proteus
  • Цель данного курсового проекта: разработка программы для управления домофоном, на микроконтроллере LM3S316.
  • 1.2 Требования к модели
  • Разрабатываемое устройство должно иметь:

1. Связь с клавиатурой в реальном времени;

2. Индикацию номеров квартир на дисплее;

3. Иметь обратную связь для открывания двери.

2. Анализ технического задания

1. На основании анализа технического задания и возможностей протеуса было принято решение, что необходима клавиатура, состоящая из 11 кнопок: девять для цифр, одна для открытия двери ключом, другая для сброса. Чтобы реализовать опрос матричной клавиатуры необходимо:

а) Выдавать высокий энергетический уровень поочередно на каждый из столбцов. Для этой цели необходимо использовать таймер;

б) Постоянно принимать значения микроконтроллером;

в) Сравнивать переданные значения с полученными, чтобы понять какая нажата кнопка.

2. Для отображения номеров квартир использовать ЖК-дисплей. Также добоваить индикация запрошенной квартиры.

3. Для реализации обратной, связи использовать кнопку, при замыкании которой сигнал пойдёт в микроконтроллер.

3. Описание устройства

После анализа технического задания была принята структурная схема модели. Модель состоит из микроконтроллера (МК), блока квартиры (КВ), ЖК-дисплея для индикации (ЖК), уличной двери (ДВ) и клавиатуры (Клав).

Рисунок 1 - Структурная схема модели домофона

3.1 Описание работы элементов программы в виде блок-схем

Для начала рассмотрим работу Таймера0 для опроса матричной клавиатуры. Блок схема представлена на Рисунке 5.

Рисунок 2 - Блок-схема работы Таймера0 для поочередной отправки 1 на столбики матричной клавиатуры (реализация бегающей 1).

Принцип работы заключается в слудующем:

1. Произвести инициализацию Таймера0;

2. Задать начальное значение Таймера0 для порта GPIOA равное 1;

3. Таймер, в бесконечном цикле будет отправлять 1 на порты PA0, PA1, PA2, тоесть на строки клавиатуры.

Далее рассмотрим считывание состояний порта D, индикацию и открытие или закрытие входной двери. Блок-схема работы представлена на Рисунке 6. Так как работа считывания для всех кнопок однотипная, на схеме приведено условие для 1 строки и 1 столбца.

Рисунок 3 - Блок -схема считывания данных

Так же в проекте имеется возможность открытие двери напрямую - ключом, блок -схема работы представлена на Рисунке 7. Для открытия двери необходимо нажать на клавиатуре кнопку «Ключ».

Рисунок 4 - Блок-схема работы открытия двери ключом

4. Моделирование в Proteus

На рисунке 4 представлена схема проекта в Proteus.

Рисунок 5 -Схема в Протеусе

1. ЖК-дисплей - LM020L. Его назначение - выводить номер квартиры. Отображение номера;

2. Клавиатура - собрана на кнопках, замыкание которых отправляет высокий энергетический уровень на порты GPIO микроконтроллера;

3. Поле индикация - представляет собой палетку с 9 светодиодами, катоды которых замкнуты на землю. Диодная панель подключена через подтягивающие резисторы;

4. Поле квартира - это кнопка, разрешающая открытие двери;

5. Уличная дверь - светодиод, на который поступает сигнал высокого уровня с микроконтроллера для открывания. Диод в открытом состоянии - дверь открыта, диод закрыт - дверь заперта;

6. Декодер U2 - необходим для того, чтобы управлять с помощью четырёх ног микроконтроллера девятью квартирами. Установлен с целью экономии ног микроконтроллера;

7. Элемент «ИЛИ» - выполняет функцию сложения, если на одну из квартир поступил запрос на открытие двери, на выходе элемента будет еденица;

8. Элемент «ИЛИ»(U5) добавлен из-за того, что не было элемента «ИЛИ»(U3) с 9 входами;

4.1 Принцип динамического опроса и индикации

Рассмотрим принцип динамического опроса клавиатуры. ноги микроконтроллера с PA0 по PA2 подключены к трем столбцам клавиатуры, эти ноги настраиваем на передачу. Четыре строчки клавиатуры подключены к выводам с PD0 по PD3, эти ноги микроконтроллера настраиваем на прием.

Бегающая единичка по столбцам реализована с помощью Таймера0, который выдает единицу на столбик с определенной задержкой.

Когда активен только первый столбик, то однозначно известно, что нажаты могут быть только квартиры с 1 по 3 и кнопка «Сброс».

Далее, происходит переход на на второй столбик, где сканируются кнопки с 4 по 6 и кнопка «Ключ», с третьим столбиком происходят аналогичные операции.

Для каждого из столбиков созданы отдельные прерывания, аналогичным образом выполнено для каждой из кнопок. Например если нажата цифра 2, контроллер заходит сначала в прерывание для 1 столбика, потом в прерывание для цифры 2, параллельно осуществляется высвечивание номера квартиры на ЖК - дисплее и загорается светодиод, соответствующий второй квартире.

Время дозвона в квартиру определяется Таймером1. Это реализовано следующим образом: в обработчике прерывания запускается счетчик (Таймер1), который отсчитывает определенное число раз, далее заходит в обработчик прерывания Таймера1 и сбрасывается, а так же отключает индикацию и очищает ЖК-дисплей, а так же закрывает дверь.

4.2 ЖК-дисплей

Для отображения номера квартиры был выбран дисплей LM020L. Значения отображается в одну строчку, питание дисплея - постоянное напряжение 5 В. Внешний вид ЖК-дисплея представлен на Рисунке 2

Рисунок 6- Внешний вид ЖК-дисплея

Назначение выводов:

VSS - на него подается питание +5 В;

VDD - земля;

VEE - регулирование яркости дисплея;

RS - вывод, с помощью которого дисплей определяет, что в него поступает, данные или команды;

RW - чтение с дисплея или запись на него;

E - ввод.

Выводы с D0 по D7 являются информационными, на них подается непосредственно код, соответствующий определенным символам. Таблица соответствий приведена в даташите на дисплей и на Рисунке 7.

На основании информации из даташита был выбран 8-разрядный режим отправки символов, то есть данные на информационыый вход пересылаются за один такт, для этого пришлось задействовать 8 выводов микроконтроллера.

Для отображения символов необходимо:

1. Проинициализировать дисплей. Когда дисплей проинициализирован на мониторе высвечивается прямоугольник:

GPIOB->DATA = 15; // Включение, посылаю на В 10101

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0xA0; // Посылаю 1 на порт E и RS

for (i=0;i<DELAY;i++){} // Задержка

GPIOC->DATA = 0; // 0 на C

GPIOB->DATA = 0; // 0 на В

for (i=0;i<DELAY;i++){} // Задержка

2. Правильно подключить выводы. Схема подключения представлена на Рисунке 4.

3. Подать на информационные входы определенную битовую последовательность. Кодирование символов взято из даташита на данный ЖК-дисплей.

Рисунок 7 - Битовое изображение вводимых символов

4. Для завершения ввода необходимо последовательно подать 1 на выводы E и RS:

GPIOB->DATA = 0x36; // #6

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

Результаты моделирования

По результатам моделирования в Протеусе можно сделать вывод, что разработанная модель отвечает всем требованиям технического задания: модель реагирует на нажатие кнопок на клавиатуре, параллельно осществляется индикация на ЖК-дисплее (на электрической принципиальной схеме он обозначен как LCD), дополнительно, в результате дешифрирования (дешифратор DC на схеме), с помощью четырех выводов микроконтроллера (PC0, PC1,PC2 и PC3) мы управляем девятью квартирами (светодиоды D5 - D13).

Связь с квартирой отображена на структурной схеме Рисунок 1. Эта связь обозначена как «Запрос квартиры» и «Разрешение».

Под запросом подразумевается звонок в определенную квартиру после нажатия номера этой квартиры на клавиатуре.

Сигнал запроса проходит следующий путь:

1. Клавиатура;

2. Микроконтроллер;

3. Квартира.

Сигнал разрешения открытия - это обратная связь от квартиры до двери (нажали кнопку в квартире, чтобы открыть дверь). Эта связь осуществляется через микроконтроллер, который коммутирует сигнал от квартиры (вывод PD7 на схеме) на вывод PE0.

Далее рассмотрим полный ход работы на примере нажатия одной кнопки:

1. Включили симуляцию. На портах PA0, PA1, PA2 появилась бегающая единичка. На ЖК-дисплей подается питание и на дисплее загорается символ «Прямоугольник». На ногах приема отсутсвует высокий энегетических уровень, так как кнопки еще не замкнулись.

Рисунок 8 -Схемы из Протеуса при включении симуляции

2. Нажимаем кнопку «1». Этим действием происходит замыкание контактов в кнопке и сигнал с порта PA0 попадает в PD0 через диод VD1. Появившийся сигнал на ногах D запускает обработчик прерываний, в котором есть команды вывода на дисплей цифры «1», и единицы на ноги С. Через дешифратор и элемент «ИЛИ», сигнал отправляется на панель диодов «Квартира», где загорается первый светодиод.

Рисунок 9 - Схема при нажатии кнопки 1

3. Когда пришел сигнал от нажатия кнопки уличной двери, мы имеем возможность ее открыть. Для этого нажимаем соответтвующую кнопку «Открыть дверь», которая замкнет цепь, и сигнал попадает в микроконтроллер по выводу PD7. В обработчике прерывания для портов D выполнится условие, согласно которому, единица установится на вывод PE0, тем самым открывая дверь.

Рисунок 10 - Часть схемы при разрешения открытия двери

4. Если нажать на кнопку «Ключ» - аналог приложения ключа к чипу, цепь замкнется через PA1 и PD3 микроконтроллера . В обработчике прерываний для портов D выполняится условие, согласно которому, единица подается на вывод PE0 и дверь открывается.

Рисунок 11 - Часть схемы при открывании ключом

Заключение

В результате выполнения курсового проекта была создана модель работы домофона на девять квартир на базе микроконтроллера LM3S316. Для создания модели была использована среда Proteus. При создании модели были задействованы: таймеры, порты ввода-вывода (GPIO).

Модель работает на девять квартир, отображая номер каждой на ЖК-дисплее. Связь от двери до квартиры и наоборот осуществляется через микроконтроллер. Введена возможность автоматического закрывания двери, если ответа от владельца квартиры не поступает, это происходит с помощью таймера, так же таймер прекращает индикацию квартиры, что дает следующему посетителю позвонить в домофон.

Была составлена структурная схема модели (Рисунок 1), где были показаны основные блоки системы.

Алгоритм работы модели представлен на рисунках 2-4.

Программный код на языке Си представлен в Приложении А.

Элементы, входящие в состав модели и представленные на электрической принципиальной схеме, перечислены в спецификации КП-11.05.01 ЭЗ.

Для проверки работоспособности модели проведенео моделирование в среде Proteus.

Список использованных источников

1. Джозеф Ю. “Ядро CORTEX-M3 Компании ARM”-Москва: ДМК Пресс, Додэка-XXI, 2015 - 535 с.

2. Data Sheet. Stellaris LM3S316 Microcontroller, 2007-2014 Texas Instruments Incorporated All rights reserved. Stellaris and StellarisWare 588 с.

3. Data Sheet. Hitachi LM020L - LMO20XBML, 37 c.

4. www.keil.com Assembler User Guide: LTORG

Приложение А

#include <lm3s_cmsis.h>

#define DELAY 21000 // Оптимальная задержка для LCD

#define DOOR_OPENING 120000 // Оптимальная задержка для разблокировки двери

int i = 0;

void Timer0A_IRQHandler (void) // Прерывание для Таймер0 - побегухи на А (опрос)

{

GPIOA->DATA = GPIOA->DATA << 1;

if(GPIOA->DATA == 8) GPIOA->DATA = 1;

}

void Timer1A_IRQHandler (void) // Падаем в прерывание Таймер1, чтобы отключить таймер

{

TIMER1 -> CTL&= ~1; // Выключаем таймер, ставим 0 в регистр TAEN из даташита

GPIOC->DATA = 0; // Выключаем лампочки

// Стирание числа после ожидания

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

}

void GPIOPortD_IRQHandler(void)

{

unsigned char portD_Data = GPIOD->DATA;

unsigned char portA_Data = GPIOA->DATA;

//----------------------------------------------------------------------------------------------------------------

if(portA_Data == 1) // Строка 1

{

////////////////////////////////// Столбик 4 - "С"

if(portD_Data == 8)

{

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOC->DATA = 0xA0; // E

GPIOE->DATA = 0;

}

////////////////////////////////// Столбик 3 - "7"

if(portD_Data == 4)

{

// Сброс LCD

GPIOC->DATA = 0xA0; // E = Enable

GPIOB->DATA = 1; // На младший один для очистки дисплея

GPIOC->DATA &= 0x1F; //4 единицы младщие + еще одна

// Индикация LCD

GPIOB->DATA = 0x37; // #7

GPIOC->DATA = 0xA0; // E = Enable = Enter (ввод) и на RS

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // НА RS единицу

// Звоним какое-то время, если не возьмёт, автосброс

TIMER1->CTL |= 1; // запускаем таймер

// Звоним в квартиру 7

GPIOC->DATA = 7;

}

////////////////////////////////// Столбик 2 - "4"

if(portD_Data == 2)

{

GPIOC->DATA = 0xA0; // E и RS

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x34; // #4

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |= 1; // Таймер1 запускается по прерыванию

GPIOC->DATA = 4;

}

////////////////////////////////// Столбик 1 - "1"

if(portD_Data == 1)

{

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x31; // #1

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |= 1; // Таймер1 запускается по прерыванию

GPIOC->DATA = 1;

}

}

//----------------------------------------------------------------------------------------------------------------

if(portA_Data == 2) // Строка 2

{

////////////////////////////////// Столбик 4 - "К"

if(portD_Data == 8)

{

GPIOE -> DATA = 0x1; // открыли дверь

for(i = 0; i < DOOR_OPENING; i++){} // подождали

GPIOE -> DATA = 0x0; // закрыли

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

}

////////////////////////////////// Столбик 3 - "8"

if(portD_Data == 4)

{

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x38; // #8

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |= 1; // Таймер1 запускается по прерыванию

GPIOC->DATA = 8;

}

////////////////////////////////// Столбик 2 - "5"

if(portD_Data == 2)

{

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x35; // #5

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |= 1; // Таймер1 запускается по прерыванию

// Прозапас GPIOC->DATA = 0;

GPIOC->DATA = 5;

}

////////////////////////////////// Столбик 1 - "2"

if(portD_Data == 1)

{

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x32; // #2

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |= 1; // Таймер1 запускается по прерыванию

GPIOC->DATA = 2;

}

}

//----------------------------------------------------------------------------------------------------------------

if(portA_Data == 4) // Строка 3

{

////////////////////////////////// Столбик 3 - "9"

if(portD_Data == 4)

{

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x39; // #9

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |= 1; // Таймер1 запускается по прерыванию

GPIOC->DATA = 9;

}

////////////////////////////////// Столбик 2 - "6"

if(portD_Data == 2)

{

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x36; // #6

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |=1; // Таймер1 запускается по прерыванию

GPIOC->DATA = 6;

}

////////////////////////////////// Столбик 1 - "3"

if(portD_Data == 1)

{

GPIOC->DATA = 0xA0; // E и RS

GPIOB->DATA = 1; //Clear 1 на DB0

GPIOC->DATA &= 0x1F; // Clear

GPIOB->DATA = 0x33; // #3

GPIOC->DATA = 0xA0; // E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0x80; // RS -> 1

TIMER1->CTL |= 1;

GPIOC->DATA = 3;

}

}

}

//----------------------------------------------------------------------------------------------------------------

int main (void)

{

// Ставим тактовую

SYSCTL->RCGC2 = 0xFF; // Подаём таковую на ДЖИПИО

SYSCTL->RCGC1 |= 0x30001; // Подаём тактовую на Таймер0 и Таймер1

// Инициализируем таймер0 (для опроса)

NVIC_EnableIRQ(Timer0A_IRQn); // Разрешение прерываний для котроллера

TIMER0->CTL &= ~1;

TIMER0->CFG = 0;

TIMER0->TAMR = 0x2;

TIMER0->TAILR = 100000;

TIMER0->IMR =1;

TIMER0->CTL |=1; // Включение таймера

// Инициализируем таймер1 (для задержки индикации и не только)

NVIC_EnableIRQ(Timer1A_IRQn);

TIMER1->CTL &= ~1; // Применяем "И" для не 1, ставим 0 только для регистра TAEN

TIMER1->CFG = 0;

TIMER1->TAMR = 0x2;

TIMER1->TAILR = 6250000; //

TIMER1->IMR =1;

// Инициалищируем GPIO

NVIC_EnableIRQ(GPIOPortA_IRQn);

GPIOA->DEN = 0x7;

GPIOA->DIR = 0xFF;

GPIOA->AFSEL = 0;

GPIOA->DATA = 1;

GPIOB->DEN = 0xFF;

GPIOB->DIR = 0xFF;

GPIOB->AFSEL = 0;

NVIC_EnableIRQ(GPIOPortC_IRQn);

GPIOC->DEN = 0xFF;

GPIOC->DIR = 0xFF;

GPIOC->AFSEL = 0;

NVIC_EnableIRQ(GPIOPortD_IRQn);

GPIOD->DEN = 0xFF; // Это шестандцатеричное число показывает какие ноги нам нужны

GPIOD->AFSEL = 0;

GPIOD->DIR = 0x00;

GPIOD->IM = 0x0F;

GPIOD->IS = 0x00;

GPIOD->IEV = 0x0F;

GPIOE->DEN = 0x1;

GPIOE->AFSEL = 0;

GPIOE->DIR = 0x1; // ЗАДАЁМ КОНКРЕТНЫЕ НОГИ НА ПЕРЕДАЧУ!

//Инициализация LCD

GPIOB->DATA = 15; // Включение, посылаю на В 10101

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0xA0; // Посылаю 1 на порт E

for (i=0;i<DELAY;i++){}

GPIOC->DATA = 0; // 0 на C

GPIOB->DATA = 0; // 0 на В

for (i=0;i<DELAY;i++){}

while (1)

{

unsigned char PD7 = GPIOD->DATA; // Обозначаем переменную PD7, чтобы смотреть что там у нас на D

//----------------------- Открытие года

if(PD7 == 128) // Если нажали кнопку "открыть дверь", то

{

GPIOC -> DATA = 0; // Индикация (Вызов) off

GPIOE -> DATA = 1; // Лампочка горит (Открываем дверь)

for (i=0;i<DOOR_OPENING;i++){} // Но совсем не надолго

GPIOE -> DATA = 0; // Дверь off

GPIOC->DATA = 0xA0; // E

GPIOB->DATA = 1; //Clear

GPIOC->DATA &= 0x1F; // Clear

}

if(PD7 == 64) // Нажали на "Сброс"

{

GPIOC -> DATA = 0;

GPIOE -> DATA = 0;

}

}

return 0;

}

Приложение Б

STACK_TOP EQU 0x20000100 ; верщина стека (таким образом число объявляем)

; Есть контакт?

PRESERVE8 ; 8 бит в стеке

THUMB ; 32-х битная инструция

AREA RESET, CODE, READONLY ; Кодовый сегмент. Ресет - это начало всего(Сначало надо ресетнуться). code - кодовый сегмент

DCD STACK_TOP ; Указываем имя вершины. Создаём переменную "вершина стека"

DCD Start ; Вектор сброса. Создаём переменную "Старт".

space 68 ; 14 обязательных векторов (хотя их там больше) + GPIO(A,B,C)

DCD GPIOPortD_IRQHandler

space 60 ; Резервируем 60 байта под обработчик прерываний для Таймера_0А.

DCD Timer0A_IRQHandler ; Вводим переменную "Обработчик прерываний Таймера_0А"

space 4; 4 байта сохарнили, не прописывая вектор Timer0B_IRQHandler

DCD Timer1A_IRQHandler

ENTRY ; Конец таблицы векторов "Вступление"

Start PROC ; Метка - Начало программы

; -------- И-НИ-ЦИ-А-ЛИ-ЗА-ЦИ-Я -------------

;Так как временные отрезки подобраны для программы Proteus (настоящее время идёт не так быстро, как в программе), то нужно задвать перед установкой домофона

; В регистры R10 -> Время открытия двери, R12 -> Время автосброса вызова

; При установке Домофона нужно выбирать следующие значения:

; R10 -> 25e6 Гц * 4 секунды = 100e6 -> 0x5F5E100

; R11 -> 25e6 Гц * 30 секунд = 750e6 -> 0x2CB41780

LDR R10, =0x7A120 ; Оптимальная задержка, чтобы открыть физическую дверь (относительно времени в программе Proteus)

LDR R12, = 0x1C9C380 ; Оптимальное время автосбрасывания вызова (относительно времени в программе Proteus)

; -------- ТАКТОВАЯ --------

;(!) Чтобы Таймер_0A заработал нужно подать на него тактовую частоту. В регситре RCGC1 ставим бит, соответствующий Таймеру_А0 - это 16 бит. -> 0x10000

;стр. 197 - Карта регистра RCGC1 (Run Mode Clock Gating Control Register 1)

LDR R0, =0x400FE000 ; в r0 положиле адрес регистра RCGC1

MOVT R1, #0x3 ; выбираю бит, который соответствует Timer 1 и Timer 0-> 0x30000 (старший бит загрузил)

STR R1, [R0, #0x104] ; загружаю свой бит в память по адресу r0 с нужным смещением

MOVW R0, #19 ; 19 вектор в таблице векторов - Timer0A_IRQHandler

BL EnableIRQ ; Переходим к вектору прерываний. BL - переход с сылкой

MOVW R0, #21 ; 21 вектор в таблице векторов - Timer1A_IRQHandler

BL EnableIRQ

;(!) Чтобы порты ввода-ввода вывода GPIO заработали, подаём тактовую. Регистр RCGC2

LDR R0, =0x400FE000 ; адрес RCGC2

MOVW R1, #0x1F ; 0x1F - биты поставили на все порты (A - E)

STR R1, [R0,#0x108] ; Записываем в r2 значение r0 со смещением для RCGC2

MOVW R0, #3 ; 3 вектор в таблице векторов - GPIOPortD_IRQHandler

BL EnableIRQ

; -------- ТАЙМЕР_0А (Скорость "побегух") --------

;1 Убедиться, что в регистре CTL бит TAEN (TimerA Enable) очищен - выключаем таймер

LDR R0, =0x40030000 ; r0 -> адрес Таймер_0А

MOV R1, #0x0 ; обнуляю r1

STR R1, [R0, #0x00C] ; чтобы попасть именно в регистр CTL я смещаю адрес на число 0xC

;2 Записать в регистр CFG - configuration 0x0

STR R1, [R0,#0x000] ; в r0 - адрес, r1 - уже 0. Смещение нулевое

;3 Записать в регистр TAMR (TimerA Mode) бит 0x1, если я выбираю One-Shot mode, 0x2 - Periodic mode

MOV R1, #0x2 ; Periodic Mode - нужно периодичное повторение

STR R1, [R0, #0x004] ; чтобы попасть в регистр TAMR смещаюсь на 0x4

;4 В регситре TAILR (TimerA Load Registr) указатать кол-во импульсов, которые он будет считать. Счет -> время (полезного ожидания)

LTORG

LDR R1, =0x3D090 ; 250k - это 100 часть от частоты генератора -> в секунду я получу 100 срабатываний Таймера.

STR R1, [r0,#0x028] ; 100 ms пусть работает Таймер_А0

;5 Если нам нужно прерывание, то в регистр IMR (Interrupt Mask Registr) записываю единичку

MOV R1, #0x1 ; нам - нужно

STR R1, [R0, #0x018] ; загружаю значение единички в IMR

;6 Включаем таймер -> TAEN = 1

STR R1, [R0, #0x00C] ; Включаем таймер.

; -------- ТАЙМЕР_1А (Время, сколько будет звонить в квартире трубка) -------

; 1. CTL

LDR R0, =0x40031000 ; r0 -> адрес Таймер_1А

MOV R1, #0x0

STR R1, [R0, #0x00C]

; 2. CFG

MOVW R1, #0x0

STR R1, [R0,#0x000]

; 3. TAMR

MOV R1, #0x2

STR R1, [R0, #0x004]

; 4. TAILR ; (Load the start value into the GPTM TimerA Interval Load)

STR R12, [R0,#0x028]

; 5. IMR

MOV R1, #0x1 ; нам - нужно

STR R1, [R0, #0x018] ; загружаю значение единички в IMR

; -------- GPIO --------

; -GPIOA-

;1 Регистр DEN (Digital Enable) - Разрешение работы портов

LDR R0, =0x40004000 ; в r0 запишу адрес порта A (он мне еще пригодится)

MOVW R1, #0x7 ; последние 3 бита уставнавливаю единичными. Активриую только нужные ноги А

STR R1, [R0,#0x51C] ; загружаю в память со смещением для DEN

;2 Регистр AFSEL (Alternate Function Select)- Регистр выбора альтернативной функции контактов

;Альтернативная цифровая функция активируется установкой соответствующего бита в регистрах GPIO Alternate Function Select

MOVW R1, #0x0 ; альтернативные ф-и мне не нужны

STR R1, [R0,#0x420]

;3 Регистр DIR (Direction) - Настраиваем каждый отдельный контакт в качестве входа или выхода

; 1 - выход

; 0 - вход

MOVW R1, #0x7 ; 3 ноги А на передачу

STR R1, [R0,#0x400] ; в память со смещением для DIR

; -GPIOB-

; 1. DEN

LDR R0, =0x40005000 ; B

MOVW R1, #0xFF ; 8 ног

STR R1, [R0,#0x51C]

; 2. AFSEL

MOVW R1, #0x0 ; альтернативные ф-и мне не нужны

STR R1, [R0,#0x420]

; 3. DIR

MOVW R1, #0xFF ; 8 ног B на передачу

STR R1, [R0,#0x400]

; -GPIOC-

; 1. DEN

LDR R0, =0x40006000 ; C

MOVW R1, #0xEF ; только рабочие ноги активирую

STR R1, [R0,#0x51C]

; 2. AFSEL

MOVW R1, #0x0 ; альтернативные ф-и мне не нужны

STR R1, [R0,#0x420]

; 3. DIR

MOVW R1, #0xFF ; 8 ног B на передачу

STR R1, [R0,#0x400]

; -GPIOD-

; 1. DEN

LDR R0, =0x40007000 ; D

MOVW R1, #0xCF ; только рабочие ноги активирую

STR R1, [R0,#0x51C]

; 2. AFSEL

MOVW R1, #0x0 ; альтернативные ф-и мне не нужны

STR R1, [R0,#0x420]

; 3. DIR

MOVW R1, #0x0 ; 8 ног B на передачу

STR R1, [R0,#0x400]

; 4. IM (Interrupt Mask) - разрешение прерываний

MOVW R1, #0xCF ; Прерывание только на нужные ноги

STR R1, [R0,#0x410]

; 5. IS (Interrupt Sense) - Регистр настройки прерываний по уровню сигнала

;0 - регистрация прерываний по фронту

;1 - регистация прерываний по уровню

MOVW R1, #0x0 ; По фронту

STR R1, [R0,#0x404]

; 5. IEV (Interrupt Event) - Регистр настройки срабатыванию по фронту

;0 - работа по спадающему фронту

;1 - работа по нарастающему фронту

MOVW R1, #0xCF ; На все ноги по нарастающему

STR R1, [R0,#0x40C]

; -GPIOE-

; 1. DEN

LDR R0, =0x40024000 ; E

MOVW R1, #0x1 ; только рабочие ноги активирую

STR R1, [R0,#0x51C]

; 2. AFSEL

MOVW R1, #0x0 ; альтернативные ф-и мне не нужны

STR R1, [R0,#0x420]

; 3. DIR

MOVW R1, #0x1 ; 8 ног B на передачу

STR R1, [R0,#0x400]

; -------- LCD --------

LDR R0, =0x40005000 ; Адресс B

MOVW R1, #0xF ; Включение, посылаю на В 1010

STR R1, [R0,#0x3FC] ; загружаю в память со смещением для DEN

MOV R0, #0x0; <- Delay for (i=0;i<DELAY;i++){}

DELAY1

ADD R0, #0x1

LDR R1, =0x5208 ; Оптимальная задержка для инициализации и работы таймера

CMP R0, R1;

BNE DELAY1

;-----------

LDR R0, =0x40006000 ; Адресс C

MOVW R1, #0xA0 ; Посылаю 1 на порт E и 1 на RS

STR R1, [R0,#0x3FC] ; загружаю в память со смещением для DEN

MOV R0, #0x0; <- Delay for (i=0;i<DELAY;i++){}

DELAY2

ADD R0, #0x1

LDR R1, =0x5208

CMP R0, R1

BNE DELAY2 ;BNE - переход, когда условие не выполняется -> снова возвращаемся к DELAY

;Много DELAY, т.к. при невыполнении неравнства, мы должны попасть ниже. Ссылаться на DELAY1 -> переходить не туда

;-----------

LDR R0, =0x40006000 ; Адресс C

MOVW R1, #0x0 ; Обнуляю С

STR R1, [R0,#0x3FC] ; загружаю в память со смещением для DEN

LDR R0, =0x40005000 ; Адресс B

MOVW R1, #0x0 ; Обнуляю B

STR R1, [R0,#0x3FC] ; загружаю в память со смещением для DEN

MOV R0, #0x0; <- Delay for (i=0;i<DELAY;i++){}

DELAY3

ADD R0, #0x1

LDR R1, =0x5208 ; 0x5208 = 21000

CMP R0, R1

BNE DELAY3

LTORG

;-----------------------

LOOP ; метка - бесконечный цикл

B LOOP ; переход к метке бесконечного цикла

ENDP ; Конец программы

;---------------- Нажали кнопку -> Попали в нужную квартиру -----------------

GPIOPortD_IRQHandler ; Метка для обработчика прерываний GPIOD

push{LR} ; Загружаем в стек линк-регистр

; R6 -> portD_Data

LDR R0, =0x40007000 ; в r0 загрузили адрес GPIOD

LDR R6, [R0, #0x3FC] ; РОН 6 записывает в себя значения, которые на r4

; R5 -> portA_Data

LDR R0, =0x40004000; A

LDR R5, [R0, #0x3FC] ; РОН 5 записываетзначения, которые на r0 - порт А

; +суфикс EQ, потому что флаг Z установлен. Он устанавливается при сравнении 2х одинаковых значений

MOV R0, #0x80 ; Если на 7 (считаем с нуля) ногу пришел сигнал, то переходим к метке. Т.к. кнопка важная, для сравнения используем отдельный регситр R0

CMP R6, R0

BEQ FROG_JUMP_CKOPO_CKOPO_CKOPO_CKOPO_CKOPO ; Метка, которая нас приведет в код открытия двери

CMP R5, #1

BEQ FROG_JUMP_CKOPO_PA0 ; Прыгаем к 1 столбику (который рядом со своими кнопками)

CMP R5, #2

BEQ FROG_JUMP_CKOPO_CKOPO_PA1

CMP R5, #4

BEQ FROG_JUMP_PA2

pop {PC}

;=====================PA2(Начало)============================

KEY_IS_3

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 3

MOVW R1, #0x33 ; #3

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY003

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY003

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #3 ; 3 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

KEY_IS_6 ;-------------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 6

MOVW R1, #0x36 ; #6

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY006

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY006

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #6 ; 6 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

;~~~~~~~~KVA~~~~~~~~

FROG_JUMP_CKOPO_PA0

CMP R5, #1

BEQ FROG_JUMP_PA0

FROG_JUMP_CKOPO_CKOPO_PA1

CMP R5, #2

BEQ FROG_JUMP_CKOPO_PA1

FROG_JUMP_PA2

CMP R5, #4

BEQ Signal_PA2

FROG_JUMP_CKOPO_CKOPO_CKOPO_CKOPO_CKOPO

MOV R0, #0x80

CMP R6, R0

BEQ FROG_JUMP_CKOPO_CKOPO_CKOPO_CKOPO

;~~~~~~~~~~~~~~~~~~

KEY_IS_9 ;-------------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 9

MOVW R1, #0x39 ; #9

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY009

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY009

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #9 ; 9 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

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

Signal_PA2

CMP R6, #1 ; принимает порт PD0 (Нажали "3")

BEQ KEY_IS_3

CMP R6, #2 ; принимает порт PD1 (Нажали "6")

BEQ KEY_IS_6

CMP R6, #4 ; принимает порт PD2 (Нажали "9")

BEQ KEY_IS_9

pop {PC}

;=====================PA2(Конец)============================

;~~~~~~~~~~~KVA~~~~~~~~~

FROG_JUMP_PA0

CMPR5, #1

BEQ Signal_PA0

FROG_JUMP_CKOPO_PA1

CMP R5, #2

BEQ FROG_JUMP_PA1

;~~~~~~~~~~~~~~~~~~~~~~~~~~~

;=====================PA0(Начало)============================

Signal_PA0

CMP R6, #1 ; принимает порт PD0 (Нажали "1")

BEQ KEY_IS_1

CMP R6, #2 ; принимает порт PD1 (Нажали "4")

BEQ KEY_IS_4

CMP R6, #4 ; принимает порт PD2 (Нажали "7")

BEQ KEY_IS_7

pop {PC}

LTORG

;~~~~~~~~~~~~~~~KVA~~~~~~~~~~~~~~~~~~

FROG_JUMP_CKOPO_CKOPO_CKOPO_CKOPO

MOV R0, #0x80

CMP R6, R0

BEQ FROG_JUMP_CKOPO_CKOPO_CKOPO

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

KEY_IS_1 ;------------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 1

MOVW R1, #0x31 ; #1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY001

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY001

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #1 ; 1 квартира

STR R1, [R0, #0x3FC]

pop {PC}

KEY_IS_4 ;-------------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 4

MOVW R1, #0x34 ; #4

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY004

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY004

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #4 ; 4 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

;~~~~~~~~~~~~~~~~KVA~~~~~~~~~~~~~~~~~~~~~

FROG_JUMP_CKOPO_CKOPO_CKOPO

MOV R0, #0x80

CMP R6, R0

BEQ FROG_JUMP_CKOPO_CKOPO

;На 665-558=107 строк можно прыгать

FROG_JUMP_PA1

CMP R5, #2

BEQ Signal_PA1

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

KEY_IS_7 ;-------------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 7

MOVW R1, #0x37 ; #7

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY007

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY007

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #7 ; 7 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

;=====================PA0(Конец)============================

;=====================PA1(Начало)============================

KEY_IS_K

LDR R0, =0x40006000; -> Enable LCD

MOVW R1, #0xA0

STR R1, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

MOV R1, #0x0 ; Мы в регистр R1 записали то, что на порту C

STR R1, [R0,#0x3FC]

LDR R0, =0x40024000 ; E

MOVW R1, #1 ; Открываем дверь

STR R1, [R0, #0x3FC]

MOV R0, #0x0;

DELAY00K

ADD R0, #1

CMP R0, R10

BNE DELAY00K

LDR R0, =0x40024000; E

MOVW R1, #0

STR R1, [R0,#0x3FC] ;Выключаем лампочку

pop {PC}

;~~~~~~~~~~~~~~KVA~~~~~~~~~~~~~~

FROG_JUMP_CKOPO_CKOPO

MOV R0, #0x80

CMP R6, R0

BEQ FROG_JUMP_CKOPO

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

KEY_IS_SBROS ;-----------------------------

LDR R0, =0x40006000; -> Enable LCD

MOVW R1, #0xA0

STR R1, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

MOV R1, #0x0 ;

STR R1, [R0,#0x3FC]

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #0 ; Сброс

STR R1, [R0, #0x3FC]

LDR R0, =0x40024000 ; E

MOVW R1, #0 ; Сбрасываем дверь

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

Signal_PA1 ;-----------------------------------

CMP R6, #1 ; принимает порт PD0 (Нажали "2")

BEQ KEY_IS_2

CMP R6, #2 ; принимает порт PD1 (Нажали "5")

BEQ KEY_IS_5

CMP R6, #4 ; принимает порт PD2 (Нажали "8")

BEQ KEY_IS_8

CMP R6, #8 ; принимает порт PD3 (Нажали "K")

BEQ KEY_IS_K

CMP R6, #64 ; принимает порт PD3 (Нажали "СБРОС")

BEQ KEY_IS_SBROS

KEY_IS_2 ;---------------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 2

MOVW R1, #0x32 ; #2

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY002

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY002

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #2 ; 2 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

;~~~~~~~~~~~~~KVA~~~~~~~~~~~~~~~~~~

FROG_JUMP_CKOPO

MOV R0, #0x80

CMP R6, R0

BEQ OPEN_THE_DOOR

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

KEY_IS_5 ;----------------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 5

MOVW R1, #0x35 ; #5

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY005

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY005

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #5 ; 5 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

KEY_IS_8 ;-----------------------------------

LDR R0, =0x40006000 ; -> Enable LCD

LDR R2, [R0, #0x3FC] ; Загружаю в R2 то, что у меня на C

ORR R2, #0xA0 ; Делаю ПОБИТОВОЕ ЛОГ. ИЛИ с 0xA0, чтобы не зацепить младшие биты порта С

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

AND R2, #0xF ; Чтобы не обнулить младшие биты GPIOC, делаю ЛОГ. И с выгруженным в R2 информационным значением порта С и 0x1F

STR R2, [R0,#0x3FC]

LDR R0, =0x40005000 ; B -> кв. 8

MOVW R1, #0x38 ; #8

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000; -> Enable LCD

ORR R2, #0xA0

STR R2, [R0,#0x3FC]

MOV R0, #0x0;

DELAY008

LDR R1, =0x3A98;

ADD R0, #1

CMP R0, R1

BNE DELAY008

LDR R0, =0x40006000 ; RS -> 1

AND R2, #0x8F ; На RS 1 и на младщие биты С -> 1, чтобы не затирать то, что на С

STR R2, [R0,#0x3FC]

LDR R0, =0x40031000;-> АКТИВАЦИЯ Timer_A1 (На случай игнорирования звонка в квартире)

MOVW R1, #1; ВКЛ Timer_A1

STR R1, [R0,#0x00C]; Смещение на CTL

LDR R0, =0x40006000; -> Звонок в нужную квартиру

MOVW R1, #8 ; 8 квартира

STR R1, [R0, #0x3FC]

pop {PC}

LTORG

;======================PA2(КОНЕЦ)==================================

OPEN_THE_DOOR ; Самое главное - разрешение на открытие уличной двери --------

LDR R0, =0x40006000; -> Enable LCD

MOVW R1, #0xA0

STR R1, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

MOV R1, #0x0 ;

STR R1, [R0,#0x3FC]

LDR R0, =0x40024000 ; E

MOVW R1, #1 ; Открываем дверь

STR R1, [R0, #0x3FC]

MOV R0, #0x0;

DELAY_OPEN

ADD R0, #1

CMP R0, R10 ; В R10 Оптимальная задржка для того, чтобы успеть открыть физическую дверь

BNE DELAY_OPEN

LDR R0, =0x40024000; E

MOVW R1, #0

STR R1, [R0,#0x3FC] ;Выключаем лампочку

pop{PC}

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

;----------------- Скорость "побегух" ---------------------------------------

Timer0A_IRQHandler ; Метка для обработчика прерываний Таймер_А0

PUSH{LR} ; LR - следующую

CMP R9, #8 ; Сравниваю значение r9 - смещение с "критическим смещением"

BEQ RESET_R9 ; Если наше число уже не на той ноге, на которой должно, то сбрасываем

CMP R9, #1 ; Если наше число 0b001, сдвигаем

BEQ CDVIGAEM_R9

CMP R9, #2 ; Если наше число 0b010, сдвигаем

BEQ CDVIGAEM_R9

CMP R9, #4 ; Если наше число 0b100, сдвигаем

BEQ CDVIGAEM_R9 ; Поменять имя метки. надо сдвинуть налево

MOVW R9, #1 ;Записываем в r9 нашу единичку. Предполагается, что изначально условия сравнения не выполнятся, и мы только уставновим 1 на PA1

CDVIGAEM_R9 ; Метка на сам сдвиг

LDR R8, =0x40004000 ; Адрес порта А. r8 - потому что он нигде ранее не использовался

STR R9, [R8,#0x3FC] ; Загружаю туда наше значение r9 (которое по 1 такту только стало единичным)

LSL R9, #1 ; Сдвигаем R9. Вот и всё

POP{PC}

RESET_R9 ; Метка, если уже перестарались сдвигать

MOVW R9, #1 ; Аналог if(GPIOA->DATA == 8) GPIOA->DATA = 1;

LDR R8, =0x40004000 ; Адрес А

STR R9, [R8,#0x3FC] ; В память

LSL R9, #1 ; Сразу сдвигаем, чтобы r9 имело значение 0b010

POP{PC} ; PC - текущая

;-------------- Автоматический сброс вызова -----------------

Timer1A_IRQHandler

push{LR} ; Загружаем в стек линк-регистр (LR - это регистр, в котором хранится номер исполняемой команды - слева цифры)

LDR R0, =0x40031000 ; Адрес Timer_A1

MOVW R1, #0 ; Выключаю Timer_A1

STR R1, [R0,#0x00C] ; Сдвинули на 0x00C, попали в регистр CTL

; После истечения работы таймера1 выключим ноги С, чтобы сбросить сигнал с индикатора

LDR R0, =0x40006000 ; Адрес порта С

MOVW R1, #0 ; Обнуляю регистр R1

STR R1, [R0,#0x3FC] ; Сбрасываю ноги С. Аналог кнопки СБРОС

; Сбрасываем LCD. В даташите на LCD (стр. 16) указано - для очистки LCD нужно подать на все ноги ноль, кроме ноги B0. Нам не хватило ног, поэтому старшие биты LCD - GPIOC; младшие биты (8 ног адресных) - GPIOB

LDR R0, =0x40006000; -> Enable LCD

MOVW R1, #0xA0

STR R1, [R0,#0x3FC]

LDR R0, =0x40005000; -> CLEAR SCREEN LCD (2 Этапа)

MOVW R1, #0x1

STR R1, [R0, #0x3FC]

LDR R0, =0x40006000 ;С

MOV R1, #0x0 ;

STR R1, [R0,#0x3FC]

pop{PC} ; Используем значение LR, находящееся в стеке, для возврата

EnableIRQ; Подпрограмма формирования вектора прерывания

push{r0-r2, LR}

and.wr1,r0,#0x1f

movr2,#1

lslr2,r2,r1

and.wr1,r0,#0xe0

lsrr1,r1,#3

ldrr0,=0xe000e100

strr2,[r0, r1]

pop{r0-r2, PC}

END ; Конец

Размещено на Allbest.ru


Подобные документы

  • Описание алгоритма работы и разработка структурной схемы МКС. Схема вывода аналогового управляющего сигнала, подключения ЖК-дисплея, клавиатуры и аварийного датчика. Разработка блок-схемы алгоритма главной программы работы МКС. Функция инициализации.

    курсовая работа [5,7 M], добавлен 26.06.2016

  • Разновидности конструктивных решений реализации весового оборудования. Разработка блок-схемы предустановок, блок-схемы измерения веса, блок-схемы вывода информации о весе в компьютер, блок-схемы устройства и программы работы микропроцессорного блока.

    курсовая работа [525,4 K], добавлен 13.02.2023

  • Создание имитационной модели для регистрации транспортных средств. Построение Q-схемы модели. Базовый алгоритм программы в виде блок-схемы. Проектирование программы на языке GPSS. Обработка результатов работы. Планирование модельных экспериментов.

    курсовая работа [490,5 K], добавлен 18.12.2013

  • Аналитический обзор существующих программ-редакторов схем (Microsoft Office Visio 2007, FCEditor, редактор блок-схем). Математическое описание программы и её интерпретатора. Описание системы и руководство пользователя, XML и текст редактора схем.

    дипломная работа [2,1 M], добавлен 07.07.2012

  • Преобразование матрицы по заданным правилам. Методика работы с массивами, основанная на классических алгоритмах. Разработка и описание блок-схемы алгоритма. Листинг программы, экраны работы и отладки программы. Инструкция для пользователей программы.

    контрольная работа [338,4 K], добавлен 29.01.2013

  • Виды терморегуляторов и их общее устройство. Разработка устройства для управления микроклиматом в теплице. Возможные варианты модернизации системы контроля температуры. Блок инициализации микроконтроллера. Разработка структурной схемы работы программы.

    курсовая работа [1,8 M], добавлен 27.05.2015

  • Программирование игр с использованием визуальных компонентов. Описание операторов, используемых при практической реализации разработанной программы. Работа над созданием программы "Морской бой", постановка задачи, алгоритм реализации работы, блок-схема.

    курсовая работа [175,9 K], добавлен 10.05.2010

  • Основные аналитические соотношения. Блок схемы и алгоритм решения задачи. Проверка работоспособности алгоритма вручную. Таблица идентификации переменных. Формы входной и выходной печати. Разработка и отладка программы. Инструкция для работы с программой.

    курсовая работа [69,8 K], добавлен 13.02.2012

  • Основные показатели, используемые для оценки тормозных свойств автомобиля. Расчет длины тормозного пути. Описание структуры и принципа работы программы для моделирования торможения автомобиля, реализованной на языке C#. Блок-схема и листинг программы.

    курсовая работа [535,5 K], добавлен 22.05.2013

  • Анализ и формализация задачи моделирования: построение концептуальной модели, ее формализация в виде Q-схемы. Построение имитационной модели: создание блок-схемы, представление базовой исходной имитационной модели. Исследование экономических процессов.

    контрольная работа [156,0 K], добавлен 21.11.2010

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.