Применение однокристальной микро ЭВМ семейства МК51 для реализации алгоритма работы электронных часов
Работа добавлена на сайт samzan.net:
Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Предоплата всего
от 25%
Подписываем
договор
Пояснительная записка к курсовой работе
по дисциплине:
«Микропроцессорные системы»
тема_курсовой_работы:
«Применение однокристальной микроЭВМ
семейства МК51 для реализации
алгоритма работы электронных часов»
[ Выполнили: ]
студенты группы С-85
Ким В.
Пиленко Ю.
Седрединов А.
Шапцов В.
[ Проверил: ]
преподаватель кафедры
Гудков
Юрий Игоревич
Оглавление:
[1] Техническое задание
[2] Выполнение
[2.1] Логика построения программы
[2.2] Устройства ввода
[2.3] Исходный текст программы с комментариями
[3] Список использованных источников
|
Техническое задание
Разработать программу для микроконтроллера на базе МП Intel 8051, реализующую функциональность электронных часов и имеющую следующие особенности:
- поддержка двух режимов работы программы: а) режим счёта; б) режим установки времени;
- в режиме счёта на дисплей терминала выводится текущее время в формате hh:mm:ss, где , , ;
- в режиме установки времени выполняется последовательный ввод значений двузначных регистров, начиная с ss, причём в каждом регистре сначала задаётся значение десятков, а затем единиц. На этапе ввода значений регистров должна производиться проверка корректности задаваемых чисел и, в случае их выхода за пределы допустимого для регистра диапазона значений, коррекция до верных значений.
Ввод необходимо осуществлять с помощью стандартной шестнадцатикнопочной терминальной клавиатуры.
Переход в режим установки времени необходимо осуществлять нажатием клавиши 9. Выход из режима установки времени должен происходить автоматически по окончании ввода значений всех регистров, т.е. сразу после задания числа единиц регистра hh.
Выполнение
- Логика построения программы
Исходя из ТЗ сформируем следующую блок-схему работы основной программы:
- Устройства ввода
Для ввода данных используется стандартная шестнадцатикнопочная клавиатура, подключаемая к параллельному порту (P1). Она имеет следующий вид:
Чтобы определить, нажата или нет какая-либо клавиша-ключ, сначала нужно выставить на линии регистра-защёлки P1, которые соединяет клавиша, разные логические значения. Затем необходимо считать из регистра значения этих линий: если оба бита стали равными «0», то значит, проверяемая клавиша была нажата.
Для сокращения процедуры опроса клавиатуры будем делать опрос по «строкам»:
Клавиша
Слово, выставленное на P1
Ожидаемое на P1 слово
7
6
5
4
3
2
1
0
7
6
5
4
3
2
1
0
1
1
1
0
1
1
1
1
1
1
1
0
1
1
1
0
1
2
1
1
0
1
1
1
1
1
1
1
0
1
1
1
1
0
3
1
1
0
1
1
1
1
1
1
1
0
1
0
1
1
1
4
1
1
1
0
1
1
1
1
1
1
1
0
1
1
0
1
5
1
1
1
0
1
1
1
1
1
1
1
0
1
1
1
0
6
1
1
1
0
1
1
1
1
1
1
1
0
0
1
1
1
7
0
1
1
1
1
1
1
1
0
1
1
1
1
1
0
1
8
0
1
1
1
1
1
1
1
0
1
1
1
1
1
1
0
9
0
1
1
1
1
1
1
1
0
1
1
1
0
1
1
1
0
1
0
1
1
1
1
1
1
1
0
1
1
1
1
0
1
|
Чтобы просто зафиксировать факт нажатия любой из цифровых клавиш, достаточно выставить в регистр P1 слово #00001111b и ожидать на P1 значение #0000x1xxb, где x{0;1}.
Особенностью данной клавиатуры, которую надо учитывать при программировании, является наличие переходного процесса (дребезга) с длительностью в несколько раз большей, чем время машинного цикла ОМЭВМ МК8051:
- Исходный текст программы с комментариями
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; Лабораторная работа по курсу "Микропроцессорные системы".
- ;; (С) Ким В., Пиленко Ю., Седрединов А., Шапцов В.
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;;;; ОПИСАНИЕ ПЕРЕМЕННЫХ: ;;;;
-
- ;R0 - итерация для режима установки времени; для удобства
- ;R1 - адрес для косвенно-регистровой адресации, указывающий на регистры R2-R4
-
- ;регистры R2 - секунды (ss) in [0..3Bh]
- ;регистры R3 - минуты (mm) in [0..3Bh]
- ;регистры R4 - часы (hh) in [0..17h]
-
- ;регистры R5,R6 - для разных промежуточных значений
- ;регистр R7 - буфер для хранения значения нажатой клавиши [#0..#9] или
- ; значения #FFh, если клавиша не нажата
-
- CR equ 0Dh; "возврат каретки"
- LF equ 0Ah; "перевод строки"
- ESC equ 1Bh; "конец сообщения"
- TimerRepeat equ 30h; число полных циклов таймера, через которое нужно
- ; обрабатывать прерывание по переполнению
-
- fMode equ 20h.0; текущий режим:
- ; "0" - режим счёта
- ; "1" - режим установки времени
-
- ; *****************************************************************************
- ; *****************************************************************************
- ; ОПИСАНИЕ ТОЧЕК ВХОДА ОСНОВНОЙ ПРОГРАММЫ и ПОДПРОГРАММ ПРЕРЫВАНИЙ
- ; !Внимание! В i8051 точки прерываний предопределены (фиксированы)
- ; для того или иного прерывания! Т.е. не могут назначаться произвольно!
-
- ORG 8000h; - точка входа в основную программу
- jmp lbMain
-
- ORG 800Bh; - прерывание по переполнению таймера (по биту TF0)
- jmp intTF0
-
- ;;Далее по каждому биту назначаем одно прерывание и по фронту, и по срезу:
- ORG 8033h; - прерывание по биту P1.0 (по любому фронту)
- jmp intP1
-
- ORG 803Bh; - прерывание по биту P1.1 (по любому фронту)
- jmp intP1
-
- ORG 804Bh; - прерывание по биту P1.3 (по любому фронту)
- jmp intP1
-
-
- ; *****************************************************************************
- ; *****************************************************************************
- ; ОСНОВНАЯ ПРОГРАММА
-
- lbMain:
- ; конфигурируем таймер T0:
- anl TMOD, #0F0h; обнуляем младшую тетраду
- orl TMOD, #01h; младшую тетраду приводим к виду "0001"
- ;mov TMOD, #00100001b; - то же самое
- clr TR0; остановка таймера T0 (таймер - не считает)
-
- ; настраиваем систему прерываний:
- mov IP, #00000010b; (IP0) все прерывания (пока) - с одинаковым низким уровнем
- ; приоритета
- mov 0F8h, #00000000b; (IP1)
- mov IE, #10000010b; IEN0: выставили биты EA(7),ES(4),ET0(1)
- mov 0E8h, #00001011b; IEN1: выставили биты 0,1,3
- mov P1, #00001111b
- mov 0EBh,#11111111b; (CTCON) разрешаем прерывания по битам P1 по фронту и срезу
- ; CTCON - см. стр. 22 в "publab2.pdf"
- ;задаём начальное время:
- mov R2, #55; секунды
- mov R3, #59; минуты
- mov R4, #11; часы
-
- clr fMode; изначально - в режим счёта
-
- ;I. РЕЖИМ СЧЁТА:
- lbCountMode:
- clr IE.7
-
- mov DPTR, #msgShowTimeMode
- call prShowMessage; вывод сообщения msgShowTimeMode
-
- ; настраиваем таймер T0:
- mov TH0, #0
- mov TL0, #0
- mov TimerRepeat, #13
-
- mov P1, #00001111b
- setb IE.7
-
- setb TR0; запускаем таймер (таймер - считает). Пошло инкрементирование T0
-
- lbCountMode_Loop:
- ; проверяем бит режима, и выполняем соответствующий переход:
- jb fMode, lbSetTimeMode
- jmp lbCountMode_Loop
-
- ;II. РЕЖИМ УСТАНОВКИ ВРЕМЕНИ:
- lbSetTimeMode:
- clr IE.7
- clr TR0; остановка таймера T0 (таймер - не считает)
-
- mov DPTR, #msgSetTimeMode
- call prShowMessage; вывод сообщения msgSetTimeMode
-
- mov R0, #04h; задаём начальное значение; всего будет семь итераций
-
- mov P1, #00001111b
- setb IE.7
-
- lbSetTimeMode_Loop:
- ;проверяем бит режима, и выполняем соответствующий переход:
- jnb fMode, lbCountMode
- jmp lbSetTimeMode_Loop
-
- ; *****************************************************************************
- ; *****************************************************************************
- ; ПОДПРОГРАММЫ_ОСНОВНЫЕ
-
- ; |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- ;; процедура intTF0:
-
- intTF0:
- clr TF0; сбрасываем бит переполнения ВРУЧНУЮ!
- djnz TimerRepeat, lbTF0_End;
-
- ; реализация собственно "хода" часов:
- inc R2
- cjne R2, #60, lbTF0_Next1
- mov R2, #0
- inc R3
- cjne R3, #60, lbTF0_Next1
- mov R3, #0
- inc R4
- cjne R4, #24, lbTF0_Next1
- mov R4, #0
-
- lbTF0_Next1: mov TimerRepeat, #13
- lbTF0_End: call prDisplay
- reti
-
- ; |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- ;; процедура prDisplay:
-
- lbDrawSeparator:
- call prWaitFor_TI
- mov SBUF, #3Ah
-
- ;; переводим значение из A в кодировку ACSII и выводим на экран:
- lbDrawElement:
- mov B, #10
- div AB
- add A, #30h
- call prWaitFor_TI
- mov SBUF, A
- mov A, B
- add A, #30h
- call prWaitFor_TI
- mov SBUF, A
- ret
-
- prDisplay:
- ;[начало вывода 9 символов]
-
- call prWaitFor_TI
- mov SBUF, #CR; переводим курсор в начало строки:
-
- mov A, R4
- call lbDrawElement
-
- mov A, R3
- call lbDrawSeparator
-
- mov A, R2
- call lbDrawSeparator
-
- call prWaitFor_TI; для выравнивания подождём передачи последнего символа
- setb TI; иначе - программа "зависнет"
-
- ;[конец вывода 9 символов]
- ret
-
- ; |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- ;; обработчик прерывания intP1:
- ;; проверяет, нажата ли клавиша входа в режим установки времени.
- ;; Такой клавишей явл. '0' на маленькой клавиатуре
-
- intP1:
- ; Запрещаем прерывания на время выполнения:
- clr 0C8h.0
- clr 0C8h.1
- clr 0C8h.2
- clr 0C8h.3
-
- jnb fMode, lbP1_CountMode
- ;;I. ПРЕРЫВАНИЕ ИЗ РЕЖИМА УСТАНОВКИ ВРЕМЕНИ:
- call prSmartDelay
- call prCheckNumKeys
-
- cjne R7, #0FFh, lbP1_CountMode_KeyPressed
- jmp lbP1_SetTimeMode_Finalize
-
- lbP1_CountMode_KeyPressed:
- call prSetTimeMode_Iteration
-
- lbP1_SetTimeMode_Finalize:
- jmp lbP1_End
-
- ;;II. ПРЕРЫВАНИЕ ИЗ РЕЖИМА СЧЁТА:
- lbP1_CountMode:
- call prSmartDelay
- call prCheckNumKeys
- cjne R7, #9, lbP1_End
- setb fMode
-
- lbP1_End:
- call prSmartDelay
- mov P1, #00001111b
- reti
-
-
- prSetTimeMode_Iteration:
- mov A, R0
- mov B, #2
- div AB; в А - целая часть, в В - остаток
- mov R1, A
- mov A, B
-
- cjne A, #0, lbSetTimeMode_Iteration_LO
- ;;Загружаем десятки в регистр:
- mov A, R7
- mov B, #10
- mul AB
- mov @R1, A
- jmp lbSetTimeMode_Iteration_Finalize
-
- lbSetTimeMode_Iteration_LO: ;;Загружаем единицы в этот же регистр:
- mov A, @R1
- add A, R7
- mov @R1, A
-
- call prCorrect_SS; корректируем секунды (R2)
- call prCorrect_MM; корректируем минуты (R3)
- call prCorrect_HH; корректируем часы (R4)
-
- lbSetTimeMode_Iteration_Finalize:
-
- call prDisplay; выводим вводимое время на экран
-
- inc R0; увеличили указатель на регистры
- cjne R0, #10, lbSetTimeMode_Iteration_End
- clr fMode; - устанавливаем режим счёта
-
- lbSetTimeMode_Iteration_End: ret
-
- ; |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- ;; процедура prShowMessage:
- ;; выводит на экран текстовое сообщение; символ ESC - признак конца сообщения
-
- prShowMessage:
- clr A
- movc A, @A + DPTR
-
- lbNextSymbol:
- call prWaitFor_TI
- mov SBUF, A
- inc DPTR
- clr A
- movc A, @A + DPTR
- cjne A, #ESC, lbNextSymbol
- ret
-
- ; *****************************************************************************
- ; *****************************************************************************
- ; ПОДПРОГРАММЫ_ВСПОМОГАТЕЛЬНЫЕ
-
- ; ///////////////////////////////////////////////////////////////////////////
- ;; процедуры prCorrect_SS, prCorrect_MM, prCorrect_HH:
- ;; проверяют соответствующие регистры на корректность значений в них;
- ;; большие значения уменьшаются до ближайших верных
-
- prCorrect_SS:
- cjne R2, #59, lbR2_not_59
- ret
- lbR2_not_59:
- jnc lbR2_more_59
- ret
- lbR2_more_59:
- mov R2, #59
- ret
-
- prCorrect_MM:
- cjne R3, #59, lbR3_not_59
- ret
- lbR3_not_59:
- jnc lbR3_more_59
- ret
- lbR3_more_59:
- mov R3, #59
- ret
-
- prCorrect_HH:
- cjne R4, #23, lbR4_not_23
- ret
- lbR4_not_23:
- jnc lbR4_more_23
- ret
- lbR4_more_23:
- mov R4, #23
- ret
-
- ; ///////////////////////////////////////////////////////////////////////////
- ;; процедура prSmartDelay:
- ;; небольшая задержка, за время которой на клавиатуре успевает
- ;; завершиться "переходной процесс"
-
- prSmartDelay:
- mov B, #0
- mov A, #0
- lbSmartDelay_Loop:
- djnz ACC, $
- djnz B, lbSmartDelay_Loop
- ret
-
- ; ///////////////////////////////////////////////////////////////////////////
- ;; процедура prWaitFor_TI:
- ;; ожидание "готовности передачи" по последовательному порту
-
- prWaitFor_TI:
- jnb TI, $; зациклить, пока TI=0
- clr TI ; устанавливаем "неготовность передачи"
- ret
-
- ; ///////////////////////////////////////////////////////////////////////////
- ;; процедура prCheckNumKeys:
- ;; опрос цифровых клавиш.
- ;; Процедура помещает в регистр R7 номер нажатой клавиши '0'..'9' или
- ;; #0ffh, если ничего не нажато
-
- prCheckNumKeys:
-
- mov R7, #0FFh; допустим, что ничего не будет нажато
-
- ;опрос первого столбца клавиш:
- lbKey_1:
- mov P1, #00DFh
- mov A, P1
-
- cjne A, #00DDh, lbKey_2
- mov R7, #1
- ret
-
- lbKey_2:
- cjne A, #00DEh, lbKey_3
- mov R7, #2
- ret
-
- lbKey_3:
- cjne A, #00D7h, lbKey_4
- mov R7, #3
- ret
-
- ;опрос второго столбца клавиш:
- lbKey_4:
- mov P1, #00EFh
- mov A, P1
-
- cjne A, #00EDh, lbKey_5
- mov R7, #4
- ret
-
- lbKey_5:
- cjne A, #00EEh, lbKey_6
- mov R7, #5
- ret
-
- lbKey_6:
- cjne A, #00E7h, lbKey_7
- mov R7, #6
- ret
-
- ;опрос третьего столбца клавиш:
- lbKey_7:
- mov P1, #007Fh
- mov A, P1
-
- cjne A, #007Dh, lbKey_8
- mov R7, #7
- ret
-
- lbKey_8:
- cjne A, #007Eh, lbKey_9
- mov R7, #8
- ret
-
- lbKey_9:
- cjne A, #0077h, lbKey_0
- mov R7, #9
- ret
-
- ;опрос четвёртого столбца клавиш:
- lbKey_0:
- mov P1, #00BFh
- mov A, P1
-
- cjne A, #00BDh, lbEnd_Exam_NumKeys
- mov R7, #0
- lbEnd_Exam_NumKeys: ret
-
- ; *****************************************************************************
- ; *****************************************************************************
- ; ОПИСАНИЕ ТЕКСТОВЫХ СООБЩЕНИЙ:
-
- msgSetTimeMode: db LF,LF,CR, '-= Time Set Mode: =-', CR, LF, ESC
- msgShowTimeMode: db LF,LF,CR, '-= Current Time: =-', CR, LF, ESC
-
- END;;;; КОНЕЦ ПРОГРАММЫ
Список использованных источников
- Курс лекций по дисциплине «Микропроцессорные системы».
- [ http://donntu.edu.ua/library_web/resurs/mikro ] Однокристалльные МикроЭВМ. Справочник. Под ред. Боборыкина, Липовецкого и др.
- Ю.Н. Евланов, В.А. Новиков, А.А. Шатохин. ОДНОКРИСТАЛЬНЫЙ МИКРОКОНТРОЛЛЕР 80C552. Методическое пособие по курсу «Схемотехника и программное обеспечение электронных средств измерений» для студентов, обучающихся по направлению «Информатика и вычислительная техника». М.: Издательство МЭИ, 2001.
- Микроконтроллеры семейства MCS51 и др. материалы и пособия кафедры.