|
Счетчик обратного отсчета
Счетчик обратного отсчета
Кафедра электронно-вычислительной аппаратуры Курсовая работа по дисциплине «Микропроцессорные системы» Тема “Счетчик обратного отсчета”Москва - 2007 ОглавлениеТехническое заданиеОписание работы программыТекст программыТехническое заданиеРазработать программу на языке Assembler, отсчитывающую время от заданного значения до 0. Значение может быть от 0001 до 9999.2 режима работы:1) режим установки значения2) режим отсчетаВвод необходимо осуществлять с помощью стандартной шестнадцатикнопочной терминальной клавиатуры. Переход в режим установки времени необходимо осуществлять нажатием клавиши 0. Выход из режима установки времени должен происходить автоматически по окончании ввода значений всех регистров.Описание работы программыЛогика построения программыИсходя из ТЗ сформируем следующую блок-схему работы основной программы:Устройства вводаДля ввода данных используется стандартная шестнадцатикнопочная клавиатура, подключаемая к параллельному порту (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: Текст программыORG 8000h;jmp lbMainORG 800Bh;jmp intTF0lbMain:; конфигурируем таймер T0:anl TMOD, #0F0h; обнуляем младшую тетрадуorl TMOD, #01h; младшую тетраду приводим к виду "0001"clr TR0; остановка таймера T0 (таймер - не считает); загружаем старший и младший байты регистра таймера T0 нулями:mov TH0, #0mov TL0, #0; настраиваем систему прерываний:mov IP, #0; все прерывания (пока) - с одинаковым низким уровнем приоритетаmov IE, #10000010b; IEN0: выставили биты EA(7),ES(4),ET0(1);mov 0E8h, #00001011b; IEN1: выставили биты 0,1,3mov P1, #00001111bmov 0EBh,#0FFh;;;;; ОПИСАНИЕ ПЕРЕМЕННЫХ: ;;;;;регистр R0 - единицы;регистр R1 - десятки;регистр R2 - сотни;регистр R3 - тысячи;регистры R4, R5, R6 - для разных промежуточных значений;регистр R7 - буфер для хранения значения нажатой клавиши [#0..#9] или; значения #FFh, если клавиша не нажатаCR equ 0Dh; "возврат каретки"LF equ 0Ah; "перевод строки"ESC equ 1Bh; "конец сообщения"Buf_R0 equ 20hBuf_R1 equ 21hBuf_R2 equ 22hBuf_R3 equ 23h;;;; ТЕЛО ПРОГРАММЫ: ;;;;;задаём начальное время:mov R0, #0;mov R1, #2;mov R2, #1;mov R3, #0;mov Buf_R0, R0mov Buf_R1, R1mov Buf_R2, R2mov Buf_R3, R3mov DPTR, #msgShowTime_Modecall prShowMessage; вывод сообщения msgShowTime_Modesetb TR0mov R4, #13lbMainLoop:nopclr Aadd A, R0add A, R1add A, R2add A, R3jz lbFinalcall prIs_SetTime_Mode;jmp lbMainLoop;call prDelay;;call prDisplay;;call prIs_SetTime_Mode;intTF0:clr TF0djnz R4, lbTF0_End;; реализация обратного отсчёта:dec R0cjne R0, #0FFh, lbTF0_Next1;mov R0, #9dec R1cjne R1, #0FFh, lbTF0_Next1;mov R1, #9dec R2cjne R2, #0FFh, lbTF0_Next1;mov R2, #9dec R3cjne R3, #0FFh, lbTF0_Next1;lbTF0_Next1: mov R4, #13lbTF0_End: call prDisplayretilbFinal:clr TR0mov DPTR, #msgFinalcall prShowMessage;call prIs_SetTime_Mode;jmp $;;;; ОПИСАНИЕ ПРОЦЕДУР: ;;;;;; процедура prDelay:; lb5: mov R5, #1;;; lb3: djnz R6, lb3; djnz R4, lb3; djnz R5, lb3;; ret;; prDelay:; mov R6, #0; mov R4, #0; mov R5, #6; call lb3;; mov R4, #244; (!!!); call lb5;; mov R4, #1; mov R6, #118; (!!!) Это следует менять для подстройки задержки!!!; call lb5;; ret;; процедура prSmartDelay:;; небольшая задержка, за время которой на клавиатуре успевает;; завершиться "переходный процесс"prSmartDelay:mov R6, #0mov R5, #0lbSmartDelay_Loop:djnz R5, $djnz R6, lbSmartDelay_Loopret;; процедура prDisplay:;; [2 на вызов]+[2 на возврат]+[7]+[1]+[1432]=[1444];; переводим значения R0, R1, R2 в кодировку ACSII:lbDrawElement:add A, #30hcall prWaitFor_TImov SBUF, AretprDisplay:call prWaitFor_TImov SBUF, #CR; переводим курсор в начало строки:mov A, R3call lbDrawElementmov A, R2call lbDrawElementmov A, R1call lbDrawElementmov A, R0call lbDrawElementcall prWaitFor_TI; для выравнивания подождём передачи последнего символаsetb TI; [1] иначе - программа "зависнет"ret; [2];; процедура prWaitFor_TI:;; ожидание "готовности передачи" по последовательному портуprWaitFor_TI:jnb TI, $; зациклить, пока TI=0clr TI ; устанавливаем "неготовность пердачи"ret;; процедура prIs_SetTime_Mode:;; [2 на вызов]+[2+1+2+2]=[9];; проверяет, нажата ли клавиша входа в режим установки времени;;; такой клавишей явл. '0'prIs_SetTime_Mode:mov P1, #00BFhmov A, P1cjne A, #00BEh, lbNot_SetTime_Modecall prSetTime; переход в режим установки таймераlbNot_SetTime_Mode:cjne A, #00B7h, lbNotAnyModemov R0, Buf_R0mov R1, Buf_R1mov R2, Buf_R2mov R3, Buf_R3lbNotAnyMode: ret;; процедура prExam_NumKeys:;; опрос цифровых клавишprExam_NumKeys:mov R7, #0FFh; допустим, что ничего не будет нажато;опрос первого столбца клавиш:lbKey_1:mov P1, #00DFhmov A, P1cjne A, #00DDh, lbKey_2mov R7, #1retlbKey_2:cjne A, #00DEh, lbKey_3mov R7, #2retlbKey_3:cjne A, #00D7h, lbKey_4mov R7, #3ret;опрос второго столбца клавиш:lbKey_4:mov P1, #00EFhmov A, P1cjne A, #00EDh, lbKey_5mov R7, #4retlbKey_5:cjne A, #00EEh, lbKey_6mov R7, #5retlbKey_6:cjne A, #00E7h, lbKey_7mov R7, #6ret;опрос третьего столбца клавиш:lbKey_7:mov P1, #007Fhmov A, P1cjne A, #007Dh, lbKey_8mov R7, #7retlbKey_8:cjne A, #007Eh, lbKey_9mov R7, #8retlbKey_9:cjne A, #0077h, lbKey_0mov R7, #9ret;опрос четвёртого столбца клавиш:lbKey_0:mov P1, #00BFhmov A, P1cjne A, #00BDh, lbEnd_Exam_NumKeysmov R7, #0lbEnd_Exam_NumKeys: ret;; процедура prWaitFor_NextKey_Pressed:;; ждёт СЛЕДУЮЩЕГО НАЖАТИЯ, чтобы долгое нажатие не "флудило"prWaitFor_NextKey_Pressed:lbPrevKey_Pressed: call prSmartDelay; чтоб избежать "дребезга" клавиатурыcall prExam_NumKeys;cjne R7, #0FFh, lbPrevKey_Pressed;call prSmartDelay; чтоб избежать "дребезга" клавиатурыlbNo_NextKey_Pressed: call prExam_NumKeyscjne R7, #0FFh, lbNextKey_Pressedjmp lbNo_NextKey_PressedlbNextKey_Pressed: ret;; процедура prSetTime:;; режим установки таймера:prSetTime:clr EAmov DPTR, #msgSetTime_Modecall prShowMessage; вывод сообщения msgSetTime_Modecall prDisplay;регистр R3:call prWaitFor_NextKey_Pressed;mov R3, 07call prDisplay;регистр R2:call prWaitFor_NextKey_Pressedmov R2, 07call prDisplay;регистр R1:call prWaitFor_NextKey_Pressedmov R1, 07call prDisplay;регистр R0:call prWaitFor_NextKey_Pressedmov R0, 07call prDisplaymov Buf_R0, R0mov Buf_R1, R1mov Buf_R2, R2mov Buf_R3, R3mov DPTR, #msgShowTime_Modecall prShowMessage; вывод сообщения msgShowTime_Modesetb EAret;; процедуры prIs_R0_more_59, prIs_R1_more_59, prIs_R2_more_23:;; проверяют соответствующие регистры на корректность значений в них;;; большие значения уменьшаются до ближайших верныхprCorrect_R0:cjne R0, #59, lbR0_not_59retlbR0_not_59: jnc lbR0_more_59retlbR0_more_59: mov R0, #59retprCorrect_R1:cjne R1, #59, lbR1_not_59retlbR1_not_59: jnc lbR1_more_59retlbR1_more_59: mov R1, #59retprCorrect_R2:cjne R2, #23, lbR2_not_23retlbR2_not_23: jnc lbR2_more_23retlbR2_more_23: mov R2, #23ret;; процедура prShowMessage:;; выводит на экран текстовое сообщение; символ ESC - признак конца сообщенияprShowMessage:clr Amovc A, @A + DPTRlbNextSymbol: call prWaitFor_TImov SBUF, Ainc DPTRclr Amovc A, @A + DPTRcjne A, #ESC, lbNextSymbolret;;;; ОПИСАНИЕ ТЕКСТОВЫХ СООБЩЕНИЙ: ;;;;msgSetTime_Mode: db LF,CR, '[Regim ustanovki taymera:]', CR, LF, ESCmsgShowTime_Mode: db LF,CR, 'OBRATNYI OTSCHET...', CR, LF, ESCmsgFinal: db CR, '!!!OBRATNYI OTSCHET ZAKONCHEN!!!:', CR, LF, ESCEND;;;; КОНЕЦ ПРОГРАММЫ
|
|