Разработка программы для управления домофоном, на микроконтроллере 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