Кафедра ИКТ
КУРСОВАЯ РАБОТА
по дисциплине «Микропроцессорные системы»
на тему
«Двоичный калькулятор»
Руководитель темы _____________
подпись, дата
Исполнители ,
Группа С-85
Аннотация
В курсовой работе разрабатывается двоичный калькулятор на базе микроконтроллера 51 семейства. Используются прерывания от последовательного порта и таймера. Работа выполняется на прототипе.
Оглавление
Аннотация. 2
Техническое задание. 4
Анализ технического задания. 5
Алгоритм основной программы.. 6
Алгоритмы обработчиков прерываний. 7
Алгоритм обработчика COM порта. 7
Алгоритм обработчика прерываний от таймера T2. 8
Алгоритм подсчета результата. 9
Алгоритм вывода результата. 10
Исходный код. 11
Заключение. 17
Список использованной литературы.. 18
Техническое задание
Написать программу для тестового стенда, построенного на базе микропроцессора Intel 8051, позволяющую выполнять следующие функции:
1. Обрабатывать ввод чисел и операторов с матричной клавиатуре, подключенной к контроллеру.
2. Обрабатывать ввод чисел и операторов с клавиатуры компьютера, в этом случае символы передаются через последовательный порт.
3. Вывод вводимых чисел и результатов математических операций между ними на экран компьютера.
Максимальная длина чисел, над которыми производятся операции 8 бит. Используются только положительные, целые числа. Поддерживаются следующие операции: «*», «/»,»+»,»-»,»=».
Анализ технического задания
В соответствии с техническим заданием устройство должно выполнять арифметические операции над введенными числами. Поэтому выделим в памяти ячейки или регистры:
- для хранения идентификатора операции для хранения первого числа для хранения второго числа для показателя операнда, который вводится
Основная программа инициализирует прерывания с последовательного порта и таймера, после чего переходит в режим «холостого хода», ожидая следующие события:
- Ввод символов с порта, к которому подключена цифровая клавиатура Ввод символов с последовательного порта через терминал
Прием символа от матричной клавиатуры реализуется с помощью прерываний от таймера и определения нажатой клавиши в обработчике данных прерываний.
Ввод символа от компьютерной клавиатуры реализуется с помощью прерываний от COM порта.
Вывод символа реализуется с помощью прерываний от COM порта.
Алгоритм основной программы


Алгоритмы обработчиков прерываний
Алгоритм обработчика COM порта


Алгоритм обработчика прерываний от таймера


В нашем конкретном случае для хранения данных используются следующие регистры:
R0 – для хранения идентификатора операции
R1 – для хранения первого операнда
R2 – для хранения второго операнда
R3 – для хранения того который операнд вводится
Алгоритм опроса клавиатуры
Для ввода данных используется стандартная шестнадцатикнопочная клавиатура, подключаемая к параллельному порту (P1). Она имеет следующий вид:

Чтобы определить, нажата или нет какая-либо клавиша-ключ, сначала нужно выставить на линии регистра-защёлки P1, которые соединяет клавиша, разные логические значения. Затем необходимо считать из регистра значения этих линий: если оба бита стали равными «0», то значит, проверяемая клавиша была нажата.
Для сокращения процедуры опроса клавиатуры будем делать опрос по «строкам». Чтобы просто зафиксировать факт нажатия любой из цифровых клавиш, достаточно выставить в регистр P1 слово #b и ожидать на P1 значение #0000x1xxb, где xÎ{0;1}.
Особенностью данной клавиатуры, которую надо учитывать при программировании, является наличие переходного процесса (дребезга) с длительностью
в несколько раз большей, чем время машинного цикла микроконтроллера.
Алгоритм подсчета результата


Алгоритм вывода результата


Исходный код
ORG 8000h ; Старт программы
jmp main
ORG 8003h ; Вектор прерывания INT0
reti ; Действие не определено
ORG 800Bh ; Переполнение таймера 0
call small_kbd ; Опрашиваем маленькую клавиатуру
reti
ORG 801Bh ; Переполнение таймера 1
reti ; Действие не определено
ORG 8023h ; Прерывание по последовательному порту
call _read ; Считываем символ из параллельного порта
reti
ORG 8030h ; Основная логика и данные
small_kbd: mov P1, #0FDh
jnb P1.5, a1 ; 1
jnb P1.6, a0 ; 0
mov P1, #0FBh
jnb P1.5, a_plus ; +
jnb P1.4, a_minus ; -
jnb P1.7, a_multi ; *
jnb P1.6, a_division ; /
mov P1, #0F7h
jnb P1.6, a_equal ; =
;call _read
ret_kbd: ret
a0: call btn_0
jmp ret_kbd
btn_0: mov A, #'0'
call _out
cjne R4, #0, a0_num_2
mov A, R1
rl A
mov R1, A
;call wait
ret
a0_num_2: mov A, R2
rl A
mov R2, A
;call wait
ret
a1: call btn_1
jmp ret_kbd
btn_1: mov A, #'1'
call _out
cjne R4, #0, a1_num_2
mov A, R1
rl A
add A, #1
mov R1, A
;call wait
ret
a1_num_2: mov A, R2
rl A
add A, #1
mov R2, A
;call wait
ret
a_plus: call btn_plus
jmp ret_kbd
btn_plus: mov A, #'+'
call _out
; call wait
mov R0, #'+' ; запомним что нажат +
mov R4, #1 ; обрабатывает второй операнд
ret
a_minus: call btn_minus
jmp ret_kbd
btn_minus: mov A, #'-'
call _out
; call wait
mov R0, #'-' ; -
mov R4, #1 ; второй операнд
ret
a_multi: call btn_multi
jmp ret_kbd
btn_multi: mov A, #'*'
call _out
; call wait
mov R0, #'*' ; *
mov R4, #1 ; второй операнд
ret
a_division: call btn_division
ret
btn_division: mov A, #'/'
call _out
; call wait
mov R0, #'/' ; /
mov R4, #1 ; второй операнд
ret
a_equal: call do_expr
jmp ret_kbd
do_expr: mov A, #'='
call _out
;call wait
cjne R0, #'+', b1
mov A, R1
add A, R2
jmp _end_expr
b1: cjne R0, #'-', b2
mov A, R1
subb A, R2
jmp _end_expr
b2: cjne R0, #'*', b3
mov A, R1
mov B, R2
mul AB
jmp _end_expr
b3: cjne R0, #'/', b4
mov A, R1
mov B, R2
div AB
jmp _end_expr
b4: mov A, #0
_end_expr: ;call _out
jb ACC.7,bin1
call vivbin2
bin12: jb ACC.6,bin2
call vivbin2
bin23: jb ACC.5,bin3
call vivbin2
bin34: jb ACC.4,bin4
call vivbin2
bin45: jb ACC.3,bin5
call vivbin2
bin56: jb ACC.2,bin6
call vivbin2
bin67: jb ACC.1,bin7
call vivbin2
bin78: jb ACC.0,bin8
call vivbin2
call draw_enter
ret
;jmp input1 ; начать заново
bin1: call vivbin1
jmp bin12
bin2: call vivbin1
jmp bin23
bin3: call vivbin1
jmp bin34
bin4: call vivbin1
jmp bin45
bin5: call vivbin1
jmp bin56
bin6: call vivbin1
jmp bin67
bin7: call vivbin1
jmp bin78
bin8: call vivbin1
call draw_enter
ret
; jmp input1
vivbin1: jbc TI, mbin1 ; проверка битаTI наготовность к приему символа(перейти, если установлен и сбросить его)
jmp vivbin1 ; ожидание готовности
mbin1: mov SBUF, #31H ; запись на терминал Введенного числа
ret
vivbin2: jbc TI, mbin2 ; проверка битаTI наготовность к приему символа(перейти, если установлен и сбросить его)
jmp vivbin2 ; ожидание готовности
mbin2: mov SBUF, #30H ; запись на терминал Введенного числа
ret
; jmp input1 ;
; ret
_out: jnb TI, _out
clr TI
mov SBUF, A
call wait
ret
_read: jnb RI, _ret_r
clr RI
mov A, SBUF
cjne A, #'0', re1
call btn_0
jmp _ret_r
re1: cjne A, #'1', re2
call btn_1
jmp _ret_r
re2: cjne A, #'+', re3
call btn_plus
jmp _ret_r
re3: cjne A, #'-', re4
call btn_minus
jmp _ret_r
re4: cjne A, #'*', re5
call btn_multi
jmp _ret_r
re5: cjne A, #'/', re6
call btn_division
jmp _ret_r
re6: cjne A, #'=', _ret_r
call do_expr
jmp _ret_r
_ret_r: ret
draw_enter: mov A, #0Ah
call _out
mov A, #0Dh
call _out
mov R0, #0 ; Запись начальных данных для следующеей операции калькуляции
mov R1, #0
mov R2, #0
mov R4, #0
ret
wait: mov R5, #0
loop1: mov R6, #0
loop2: djnz R6, loop2
djnz R5, loop1
ret
main: mov R0, #0 ; Идентификатор операции
mov R1, #0 ; Число 1
mov R2, #0 ; Число 2
mov R4, #0 ; Показатель, какой операнд вводим левый, 1 -- правый )
mov IP, #0 ; Установка приоритета выполнения всех прерываний в 0 (низкий)
mov IE, #b ; Разрешение прерываний от счетчика 0 и последовательного порта
mov TMOD, #b ; Настройка таймера
mov TCON, #b ; Запустить таймер 0
loop: jmp loop
END
Заключение
Данный алгоритм программы может быть реализован на микроконтроллере серии 51
В курсовой работе запрограммирован микроконтроллер 51 серии на ввод символов от матричной и компьютерной клавиатуры. Также используется вывод символов через последовательный порт и терминал на ПК. Использованы прерывания от последовательного порта и таймера.



