скачать рефераты

скачать рефераты

 
 
скачать рефераты скачать рефераты

Меню

Микропроцессорная система управления, предназначенная для использования на лесопильном заводе скачать рефераты

p align="left">Адрес первого обработчика составляется из полного слова ICW2 (старший байт) и битов 7,6,5 слова ICW1 (старшие три бита младшего байта адреса).

В нашем случае старший байт равен 00Н, младший байт равен 0010 0000 = 20Н. Обработчики имеют начальные адреса: 0020H, 0024H, 0028H, 002CH, 0030H, 0034H (6 обработчиков).

Процедура INI_PIC инициализирует контроллер.

Листинг 6: инициализация программируемого контроллера прерываний

; - - - переслать 38H в порт 0CH и 0 в порт 0DH

INI_PIC LD A, #38 ;

OUT (#0C), A ;

XOR A ;

OUT (#0D), A ;

Инициализация переменных системы

В системе за некоторыми ячейками памяти закреплена функция хранения переменных. Например, подсчитанный суммарный объем древесины V в двоичном формате хранится в отдельных двух байтах памяти с адресами V_SUM, V_SUM+1.

Требуют инициализации только две переменные (инициализируются нулем):

V (2 байта) - начальный адрес V_SUM;

Время (4 байта) - начальный адрес TIME.

Ясно, что эти имена (V_SUM и TIME) лишь условные обозначения (также, как, например, имена меток в листингах программ). При переводе в машинный код эти имена транслируются в двухбайтный адрес.

Листинг 7: инициализация ячеек суммарного объема и времени

; - - - начальное обнуление объема и времени

INI_VAR XOR A ;

LD (V_SUM), A ;

LD (V_SUM+1), A ;

LD (V_SUM+2), A ;

LD (TIME), A ;

LD (TIME+1), A ;

LD (TIME+2), A ;

LD (TIME+3), A ;

… ; следует продолжение переходит к основному циклу работы (описание см. в п.4.4).

Арифметические подпрограммы

Микропроцессорной системе необходимо “уметь” выполнять арифметические операции: сложение, вычитание, умножение, деление и косинус. В этом же разделе приведем и неарифметические процедуры для осуществления индикации: преобразования данных в двоично-десятичный код и в семисегментный.

Основным форматом чисел в МП системе является двухбайтный формат с фиксированной точкой вида 1байт , 1байт . Формат беззнаковый, предполагается, что числа положительны. Одно число умещается в одной регистровой паре. Минимальное представимое число - 0,01H=1/256=3,910-3, максимальное - FF,FFН=256,996.

Общие правила для всех вычислительных процедур:

программист вызывающей программы сам следит, чтобы операнды и результат не выходили за пределы представления и чтобы при вычитании не образовалось отрицательных величин;

операнды при сложении, вычитании, умножении, делении хранятся в регистровых парах HL и DE, результат в HL. Процедура косинуса получает операнд и выводит результат в паре HL.

Сложение

В микропроцессоре Z80 есть команда сложения регистровых пар ADD HL, DE. Однако, чтобы сохранить единообразие, оформим ее все же как подпрограмму.

Листинг 8: подпрограмма PLUS

; - - - подпрограмма сложения

; HL+DEHL

; сохраняет A, BC, DE

PLUS ADD HL, DE ;

RET ;

Вычитание

В Z80 есть команда вычитания регистровых пар с учетом переноса SBC HL, DE. Используем ее в подпрограмме вычитания, обнулив прежде флаг CY.

Листинг 9: подпрограмма MINUS

; - - - подпрограмма сложения

; HL-DEHL

; сохраняет A, BC, DE

MINUS OR A ; A не меняется, но флаг CY=0

SBC HL, DE ;

RET ;

Умножение

При умножении первый множитель хранится в паре BC (скопируем его туда из HL в начале), второй множитель хранится в DE. Результат первоначально получается в четырехбайтном виде HL.DE, затем “обрезается” до H.L.

Результат произведения накапливается в HLDE. В течение 16 циклов сдвигов HLDE второй множитель DE постепенно выдвигаясь, уходит вправо и на его место приходит из HL готовые биты произведения. Они получаются при суммировании первого множителя (BC) и левой половины накопленной суммы HLDE (HL). Суммирование делается в случае, если перед этим при сдвиге HLDE вправо из DE был выдвинут единичный бит.

Листинг 10: подпрограмма MUL

; - - - подпрограмма умножения

; HLDEHL

; все регистры меняются

MUL LD B, H ; BC=1-й множитель

LD C, L ;

LD HL, 0 ; HL=0

LD A, 16 ; счетчик цикла

MUL2 SRL H ; сдвиг 0HLDECY

RR L ;

RR D ;

RR E ;

JR NC, MUL1 ; если выдвинут 0, то на конец цикла

ADD HL, BC ; если выдвинута 1, то сложить

MUL1 DEC A ;

JR NZ, MUL2 ;

LD H, L ; получено произведение HL.DE

LD L, D ; которое “обрезаем” до L.D и переносим в H.L

RET

Деление

При делении делимое хранится в HL, делитель в DE. Результат получается в виде трех байт [стек.L] (где “стек” - содержимое вершины стека), в конце программы младший байт стека переносится в H и окончательный результат имеет формат H.L. Регистровая пара BC в начале обнуляется.

Деление производится в течение 24-х циклов. В каждом цикле делается сдвиг BCHL0, т.е. делимое HL выдвигается влево в пару BC. Затем BC сравнивается с DE (путем вычитания BC-DE и проверки флага переноса). Если BC>DE, то младший разряд HL устанавливается единицей, в противном случае он остается нулем. Это один из разрядов частного.

После 16 сдвигов в делимое HL полностью сдвинется влево и на его место придет частное целочисленного деления, в BC будет остаток деления, DE сохранит делитель. На этом этапе целая часть частного в HL заносится в стек, а HL обнуляется. В оставшихся 8-ми сдвигах BCHL в BC будут сдвигаться только нули. После всех 24-х циклов в регистре L будет дробная часть частного, а в стеке целая часть.

Листинг 11: подпрограмма DIV

; - - - подпрограмма деления

; HL/DEHL

; сохраняет DE, использует стек (2 байта)

DIV LD BC, 0 ;

LD A, 24 ; А - счетчик циклов

DIV4 PUSH AF ; сохранить счетчик А в стеке

ADD HL, HL ; BCHL0

RL C ;

RL B ;

LD A, C ;

SUB E ;

LD C, A ;

LD A, B ;

SBC D ;

LD B, A ;

JR NC, DIV1 ; если BC>DE, то переход

LD A, C ;

ADD E ;

LD C, A ;

LD A, B ;

ADC D ;

LD B, A ;

JR DIV2 ;

DIV1 INC HL ; если BC>DE: установить последний бит

; частного в 1

DIV2 POP AF ; извлечь счетчик А из стека

CP #09 ; проверить, 16-й цикл идет или нет

JR NZ, DIV3 ;

PUSH HL ; если 16-й цикл, то в HL целая часть частного,

; сохранить ее в стеке, чтобы извлечь

; в конце программы

LD HL, 0 ;

DIV3 DEC A ;

JR NZ, DIV4 ; конец цикла

POP BC ; извлекаем из стека целую часть частного

LD H, C ; получаем частное в H.L

RET ;

Косинус

Чтобы вычислить косинус, используется ограниченный четырьмя членами ряд Тейлора:

, угол изменяется от 0 до /2. (6)

Эта формула дает косинус с максимальной погрешностью 8,910-4, это меньше, чем ошибка разрядности используемого формата [1].[1] дробных чисел.

(7)

Представление (7) формулы (6) гораздо удобнее для вычисления косинуса программно. Достаточно сделать процедуру для вычисления , где n - целое число, - дробное число. Перед обращением к этой процедуре (названной COS_A) операнды содержатся:

HL = 2;

DE = ;

BC = n в формате n.0 (B=n, C=0).

Результат - в HL

Эта подпрограмма использует предыдущие арифметические программы.

Листинг 12: подпрограмма COS_A

; - - - вспомогательная подпрограмма для косинуса

; операнды: HL, DE, BC

; изменяются все регистры

COS_A PUSH BC ; сохранить в стеке n перед вызовом MUL

CALL MUL ; HL=HLDE

POP DE ; DE=n

CALL DIV ; HL=HL/DE

LD D, 1 ; DE=1.0

LD E, 0 ;

EX HL, DE ;

CALL MINUS ; HL=HL-DE

RET ;

Подпрограмма косинуса вычисляет косинус угла в паре HL.

Листинг 13: подпрограмма COS

; - - -подпрограмма косинуса

; операнд и результат в HL

; изменяются все регистры

COS LD D, H ;

LD E, L ;

CALL MUL ; HL=2

PUSH HL ; 2 в стеке

LD D, 1 ; DE=1.0

LD E, 0 ;

LD B, #1E ; BC=1E.0H=30

LD C, 0 ;

CALL COS_A ; HL=1-2/30

EX HL, DE ;

POP HL ; HL=2

PUSH HL ; 2 в стеке

LD B, #0C ; BC=C.0H=12

LD C, 0 ;

CALL COS_A ; HL=1-2/12(1-2/30)

EX HL, DE ;

POP HL ; HL=2

LD B, #02 ; BC=2.0

LD C, 0 ;

CALL COS_A ; HL=1-2/2[1-2/12(1-2/30)]

RET ;

Преобразование двоичныйдвоично-десятичный код

В управляющей программе надо переводить двухбайтные числа формата [12].[34] в двоично-десятичный код вида [123.45] размером в пять тетрад для последующего перевода в семисегментный код и индикации.

Для этого нужны две отдельных подпрограммы: одна (по имени B2D) для перевода целой части числа [12] и вторая (имя B2D_F) для перевода дробной части числа [34].

Подпрограмма B2D переводит целое двоичное число в регистре C (0..FFH) в 2-10 код, расположенный в регистровой паре HL. Перевод производится в соответствии с формулой:

HL=(…((c7)2+c6)2+…+c1)2+c0,

в которой ci - разряды числа в регистре C, а удвоение и сложение с битами ci происходит по правилам десятичной арифметики (с командой DAA после операции).

Листинг 14: подпрограмма B2D

; - - - перевод байта (целого) в 2-10 код

; операнд C - переводимое число, результат в HL

; сохраняет DE

B2D LD B, 8 ;

B2D1 SLA C ; CYC (получаем последний бит операнда)

LD A, L ; удвоение HL с учетом переноса CY

ADC L ; по правилам десятичной арифметики

DAA ;

LD L, A ;

LD A, H ;

ADC H ;

DAA ;

LD H, A ;

DJNZ B2D1 ; конец цикла

RET ;

Подпрограмма B2D_F переводит дробное число в формате 0.L в 2-10 код из трех тетрад в формате 0.ABC (учитываются три цифры после запятой). Регистры A, B, C содержат в конце каждый по одной десятичной цифре. Перевод происходит так. Число 0.L умножается на 10, результат в паре H.L. Его целая часть (H) и будет первой цифрой A результата. Затем H обнуляется, полученная дробь 0.L снова умножается на 10 и т.д.

Для быстрого умножения на 10 сделана отдельная подпрограмма MUL10, умножающая пару HL (где H=0) и получающая результат в той же HL. Она использует равенство:

10HL=2HL+8HL, а умножения на 2 и на 8 делаются с помощью команды ADD HL, HL.

Листинг 15: подпрограммы B2D_F и MUL10

; - - - перевод байта (дробного) в 2-10 код

; операнд C - число с фиксированной перед старшим разрядом точкой, результат в ABC

; изменяются все регистры

B2D_F LD H, 0 ;

CALL MUL10 ; получить в H первую цифру

LD A, H ; скопировать ее в A

LD H, 0 ; и обнулить H

CALL MUL10 ;

LD B, H ; вторую цифру - в регистр B

LD H, 0 ;

CALL MUL10 ; третью - в C

LD C, H ;

RET

; - - - умножение на 10

; операнд в HL (имеет значение только L) и результат в HL

; сохраняет A, BC

MUL10 ADD HL, HL ; HL10=HL2+HL8

LD D, H ;

LD E, L ;

ADD HL, HL ;

ADD HL, HL ;

ADD HL, DE ;

RET ;

Преобразование двоичныйсемисегментный код

Это преобразование с помощью таблицы перекодировки уже встречалось в тестовой программе ОЗУ. Сейчас оформим ее как отдельную подпрограмму (в тесте ОЗУ нельзя вызывать подпрограммы, т.к. команда вызова CALL использует стек). Операнд подпрограммы - двоично-десятичная цифра в регистре A (0..9, старшая тетрада нулевая).

Листинг 16: подпрограмма D27

; - - - перевод байта в семисегментный код

; операнд (0..9) и результат в A

; сохраняет BC, DE

D27 LD H, #07 ;

LD L, A ;

LD A, (HL) ;

RET ;

Обработчики прерываний

Всего их шесть - по числу прерываний. Обработчик обязательно должен сохранить в стеке все изменяемые им регистры и в конце восстановить их. Выход из обработчика выполняется не стандартным RET, а командой RETI.

Обработчик IRQ0 (начало измерений)

Функция обработчика - обнулить таймеры T1 и T2, а также специальную ячейку памяти D_NUM (2 байта). Эта ячейка инкрементируется всякий раз после чтения напряжения Ud с датчика диаметра. По приходу запроса IRQ0, когда приходит новое бревно, она должна быть обнулена.

Листинг 17: обработчик запроса IRQ0

; - - - обнулить T1, T2, D_NUM

IR0_H PUSH BC ;

PUSH AF ;

LD BC, 0 ;

LD (T1), BC ; обнулить T1

LD (T2), BC ; обнулить T2

LD (D_NUM), BC ; обнулить D_NUM

POP AF ;

POP BC ;

RETI ;

Обработчик IRQ2 (информация с АЦП готова)

Функция обработчика - если бревно сейчас под пластиной датчика (можно судить, прочтя порт фотоэлементов с адресом 0B), считать два байта напряжения из портов 00 (младший) и 01 (старший). Записать их в массив напряжений, под который отведена область памяти начиная с адреса 0100Н до конца ОЗУ (всего 2К). Перед записью проверить, не заполнен ли этот массив. Инкрементировать ячейку D_NUM, содержащую число элементов этого массива.

Листинг 18: обработчик запроса IRQ2

; - - - считать и обработать байт с АЦП

IR2_H PUSH BC ;

PUSH HL ;

PUSH AF ;

IN A, (#0B) ;

AND #02 ; наложить маску 000000010

JR Z, IR2_H1 ; если второй бит нулевой, то выход

LD HL, #1000 ; рассчитать адрес очередного элемента массива

Страницы: 1, 2, 3, 4