Главная Учебники - Разные Лекции (разные) - часть 33
|
Кафедра электронно-вычислительной аппаратуры
по дисциплине «Микропроцессорные системы» Москва – 2007 Техническое задание Описание работы программы Текстпрограммы Разработать программу на языке Assembler, отсчитывающую время от заданного значения до 0. Значение может быть от 0001 до 9999. 2 режима работы: 1) режим установки значения 2) режим отсчета Ввод необходимо осуществлять с помощью стандартной шестнадцатикнопочной терминальной клавиатуры. Переход в режим установки времени необходимо осуществлять нажатием клавиши 0. Выход из режима установки времени должен происходить автоматически по окончании ввода значений всех регистров. Исходя из ТЗ сформируем следующую блок-схему работы основной программы: Для ввода данных используется стандартная шестнадцатикнопочная клавиатура, подключаемая к параллельному порту (P1). Она имеет следующий вид: Чтобы определить, нажата или нет какая-либо клавиша-ключ, сначала нужно выставить на линии регистра-защёлки P1, которые соединяет клавиша, разные логические значения. Затем необходимо считать из регистра значения этих линий: если оба бита стали равными «0», то значит, проверяемая клавиша была нажата. Для сокращения процедуры опроса клавиатуры будем делать опрос по «строкам»: Чтобы просто зафиксировать факт нажатия любой из цифровых клавиш, достаточно выставить в регистр P1 слово #00001111b и ожидать на P1 значение #0000x
1xx
b, где xÎ{0;1}. Особенностью данной клавиатуры, которую надо учитывать при программировании, является наличие переходного процесса (дребезга) с длительностью ORG 8000h; jmplbMain ORG 800Bh; jmp intTF0 lbMain: ; конфигурируем таймер T0: anl TMOD, #0F0h; обнуляем младшую тетраду orlTMOD, #01h; младшую тетраду приводим к виду "0001" clrTR0; остановка таймера T0 (таймер - не считает) ; загружаем старший и младший байты регистра таймера T0 нулями: movTH0, #0 movTL0, #0 ; настраиваем систему прерываний: movIP, #0; все прерывания (пока) - с одинаковым низким уровнем приоритета movIE, #10000010b; IEN0: выставили биты EA(7),ES(4),ET0(1) ;mov 0E8h, #00001011b; IEN1: выставили биты 0,1,3 mov P1, #00001111b mov 0EBh,#0FFh; ;;;; ОПИСАНИЕ ПЕРЕМЕННЫХ: ;;;; ;регистр R0 - единицы ;регистр R1 - десятки ;регистр R2 - сотни ;регистр R3 - тысячи ;регистры R4, R5, R6 - для разных промежуточных значений ;регистр R7 - буфер для хранения значения нажатой клавиши [#0..#9] или ; значения #FFh, если клавиша не нажата CRequ 0Dh; "возврат каретки" LFequ 0Ah; "перевод строки" ESCequ 1Bh; "конец сообщения" Buf_R0 equ 20h Buf_R1 equ 21h Buf_R2 equ 22h Buf_R3 equ 23h ;;;; ТЕЛО ПРОГРАММЫ: ;;;; ;задаём начальное время: mov R0, #0; mov R1, #2; mov R2, #1; mov R3, #0; mov Buf_R0, R0 mov Buf_R1, R1 mov Buf_R2, R2 mov Buf_R3, R3 mov DPTR, #msgShowTime_Mode call prShowMessage; вывод сообщения msgShowTime_Mode setb TR0 mov R4, #13 lbMainLoop: nop clr A add A, R0 add A, R1 add A, R2 add A, R3 jz lbFinal call prIs_SetTime_Mode; jmp lbMainLoop ;call prDelay; ;call prDisplay; ;call prIs_SetTime_Mode; intTF0: clr TF0 djnz R4, lbTF0_End; ; реализация обратного отсчёта: decR0 cjneR0, #0FFh, lbTF0_Next1; mov R0, #9 dec R1 cjne R1, #0FFh, lbTF0_Next1; mov R1, #9 dec R2 cjne R2, #0FFh, lbTF0_Next1; mov R2, #9 dec R3 cjne R3, #0FFh, lbTF0_Next1; lbTF0_Next1: mov R4, #13 lbTF0_End: call prDisplay reti lbFinal: clr TR0 mov DPTR, #msgFinal call prShowMessage ;call prIs_SetTime_Mode; jmp $ ;;;; ОПИСАНИЕ ПРОЦЕДУР: ;;;; ;; процедура prDelay: ; lb5: movR5, #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: movR6, #0 mov R5, #0 lbSmartDelay_Loop: djnz R5, $ djnz R6, lbSmartDelay_Loop ret ;; процедура prDisplay: ;; [2 на вызов]+[2 на возврат]+[7]+[1]+[1432]=[1444] ;; переводим значения R0, R1, R2 в кодировку ACSII: lbDrawElement: add A, #30h call prWaitFor_TI mov SBUF, A ret prDisplay: callprWaitFor_TI movSBUF, #CR; переводим курсор в начало строки: mov A, R3 call lbDrawElement mov A, R2 call lbDrawElement mov A, R1 call lbDrawElement mov A, R0 call lbDrawElement callprWaitFor_TI; для выравнивания подождём передачи последнего символа setbTI; [1] иначе - программа "зависнет" ret; [2] ;; процедура prWaitFor_TI: ;; ожидание "готовности передачи" по последовательному порту prWaitFor_TI: jnbTI, $; зациклить, пока TI=0 clrTI; устанавливаем "неготовность пердачи" ret ;; процедура prIs_SetTime_Mode: ;; [2 на вызов]+[2+1+2+2]=[9] ;; проверяет, нажата ли клавиша входа в режим установки времени; ;; такой клавишей явл. '0' prIs_SetTime_Mode: mov P1, #00BFh mov A, P1 cjne A, #00BEh, lbNot_SetTime_Mode callprSetTime; переход в режим установки таймера lbNot_SetTime_Mode: cjne A, #00B7h, lbNotAnyMode mov R0, Buf_R0 mov R1, Buf_R1 mov R2, Buf_R2 mov R3, Buf_R3 lbNotAnyMode: ret ;; процедура prExam_NumKeys: ;; опрос цифровых клавиш prExam_NumKeys: movR7, #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 movR7, #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 movR7, #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 movR7, #9 ret ;опрос четвёртого столбца клавиш: lbKey_0: mov P1, #00BFh mov A, P1 cjne A, #00BDh, lbEnd_Exam_NumKeys mov R7, #0 lbEnd_Exam_NumKeys: ret ;; процедура prWaitFor_NextKey_Pressed: ;; ждёт СЛЕДУЮЩЕГО НАЖАТИЯ, чтобы долгое нажатие не "флудило" prWaitFor_NextKey_Pressed: lbPrevKey_Pressed: callprSmartDelay; чтоб избежать "дребезга" клавиатуры call prExam_NumKeys; cjne R7, #0FFh, lbPrevKey_Pressed; call prSmartDelay; чтоб избежать "дребезга" клавиатуры lbNo_NextKey_Pressed: call prExam_NumKeys cjne R7, #0FFh, lbNextKey_Pressed jmp lbNo_NextKey_Pressed lbNextKey_Pressed: ret ;; процедура prSetTime: ;; режимустановкитаймера: prSetTime: clrEA mov DPTR, #msgSetTime_Mode call prShowMessage; вывод сообщения msgSetTime_Mode call prDisplay ;регистр R3: call prWaitFor_NextKey_Pressed; mov R3, 07 call prDisplay ;регистр R2: call prWaitFor_NextKey_Pressed mov R2, 07 call prDisplay ;регистр R1: call prWaitFor_NextKey_Pressed mov R1, 07 call prDisplay ;регистр R0: call prWaitFor_NextKey_Pressed mov R0, 07 call prDisplay mov Buf_R0, R0 mov Buf_R1, R1 mov Buf_R2, R2 mov Buf_R3, R3 mov DPTR, #msgShowTime_Mode call prShowMessage; вывод сообщения msgShowTime_Mode setb EA ret ;; процедуры prIs_R0_more_59, prIs_R1_more_59, prIs_R2_more_23: ;; проверяют соответствующие регистры на корректность значений в них; ;; большие значения уменьшаются до ближайших верных prCorrect_R0: cjne R0, #59, lbR0_not_59 ret lbR0_not_59: jnc lbR0_more_59 ret lbR0_more_59: mov R0, #59 ret prCorrect_R1: cjne R1, #59, lbR1_not_59 ret lbR1_not_59: jnc lbR1_more_59 ret lbR1_more_59: mov R1, #59 ret prCorrect_R2: cjne R2, #23, lbR2_not_23 ret lbR2_not_23: jnc lbR2_more_23 ret lbR2_more_23: mov R2, #23 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 cjneA, #ESC, lbNextSymbol ret ;;;; ОПИСАНИЕ ТЕКСТОВЫХ СООБЩЕНИЙ: ;;;; msgSetTime_Mode: db LF,CR, '[Regim ustanovki taymera:]', CR, LF, ESC msgShowTime_Mode: db LF,CR, 'OBRATNYI OTSCHET...', CR, LF, ESC msgFinal: db CR, '!!!OBRATNYI OTSCHET ZAKONCHEN!!!:', CR, LF, ESC
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||