Обработчик 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 ; рассчитать адрес очередного элемента массива
LD C, (D_NUM) ; считать D_NUM
LD B, (D_NUM+1) ;
SLA C ; умножить его на 2
RL B ;
ADD HL, BC ; теперь адрес в HL
LD A, H ;
CP #18 ;
JR NC, IR2_H1 ; если вышли за пределы массива, то выход
IN A, (#00) ; считать первый байт с АЦП
LD (HL), A ; и отправить его в память
INC HL ;
IN A, (#01) ; считать второй
LD (HL), A ; отправить
INC BC ; увеличить переменную D_NUM на единицу
LD (D_NUM), BC ;
IR2_H1 POP AF ;
POP HL ;
POP BC ;
RETI ;
Обработчик IRQ3 (от генератора 16 Гц)
Функция обработчика – произвести инкремент часов реального времени и условный инкремент таймеров. Часы реального времени – это 4 байта в памяти:
TIME 1/16 секунды (0..15);
TIME+1 секунды (0..59);
TIME+2 минуты (0..59);
TIME+3 часы (0..23);
Все величины хранятся в двоичном формате.
Таймерам T1 и T2 отведено по 2 байта с начальными адресами T1 и T2. Условия, при которых они инкрементируются, были приведены в п. 3.4.
Листинг 19: обработчик запроса IRQ3
; – – – инкремент часов реального времени и условный инкремент таймеров
IR3_H PUSH BC ;
|
|
PUSH HL ;
PUSH AF ;
; часы реального времени
LD HL, TIME ;
INC (HL) ; инкремент 1/16 секунд
LD A, (HL) ;
CP 16 ; проверить на достижение максимума JR C, IR3_H1 ; условный выход из подпрограммы
LD (HL), 0 ; иначе обнулить 1/16 секунды и продолжить
INC HL ;
LD B, 2 ; инкремент секунд и минут делается в цикле
IR3_H2 INC (HL) ;
LD A, (HL) ;
CP 60 ;
JR C, IR3_H1 ;
LD (HL), 0 ;
INC HL ;
DJNZ IR3_H2 ; конец цикла
INC (HL) ; инкремент часов
LD A, (HL) ;
CP 24 ;
JR C, IR3_H1 ;
XOR A ; если счетчик часов=24
LD (HL), A ; то обнулить все 4 байта часов реального времени
DEC HL ;
LD (HL), A ;
DEC HL ;
LD (HL), A ;
DEC HL ;
LD (HL), A ;
|
|
; таймеры
IR3_H1 IN A, (#0B) ; загрузить слово статуса фотоэлементов
AND 1 ;
JR Z, IR3_H3 ; если не установлен 1-й бит, то выход
LD HL, T2 ; иначе инкремент Т2
INC (HL) ;
JR NZ, IR3_H4 ; если инкремент не обнулил
; первый байт Т2, то идем дальше
INC HL ; иначе увеличить на 1 и второй байт
INC (HL) ;
IR3_H4 IN A, (#0B) ;
AND 2 ; проверить 2-й бит статуса ФЭЛ
JR Z, IR3_H3 ; если он не установлен, то выход
LD HL, T1 ; иначе инкремент Т1
INC (HL) ;
JR NZ, IR3_H3 ;
INC HL ;
INC (HL) ;
IR3_H3 POP AF ;
POP HL ;
POP BC ;
RETI ;
Обработчик IRQ4 (от кнопки “+Час”)
Функция обработчика – увеличить на единицу часы реального времени (ячейка TIME+3).
Листинг 20: обработчик запроса IRQ4
; – – – инкремент часов
|
|
IR4_H PUSH HL ;
PUSH AF ;
LD HL, TIME+3;
INC (HL) ; инкремент часов
LD A, (HL) ;
CP 24 ;
JR C, IR4_H1 ;
XOR A ; если счетчик часов=24
LD (HL), A ; то обнулить часы и минуты
DEC HL ;
LD (HL), A ;
IR4_H1 POP AF ;
POP HL ;
RETI
Обработчик IRQ5 (от кнопки “+Мин”)
Функция обработчика – увеличить на единицу минуты реального времени (ячейка TIME+2).
Листинг 21: обработчик запроса IRQ5
; – – – инкремент минут
IR5_H PUSH HL ;
PUSH AF ;
LD HL, TIME+2;
INC (HL) ; инкремент минут
LD A, (HL) ;
CP 60 ;
JR C, IR5_H1 ;
XOR A ; если счетчик минут=60
LD (HL), A ; то обнуление минут
INC HL ; и инкремент часов
INC (HL) ;
LD A, (HL) ; с проверкой часов на 24
CP 24 ;
JR C, IR5_H1 ;
XOR A ; если счетчик часов=24
LD (HL), A ; то обнулить и часы
IR4_H1 POP AF ;
POP HL ;
RETI
Обработчик IRQ1 (от фотоэлемента Фэл2)
Обработчик IRQ1 выполняет самую важную функцию. Его задача – вычислить объем бревна. Последовательность следующая: вычисляем диаметр бревна, длину, вычисляем объем Vi, находим объем V S.
Для вычисления диаметра все значения, прежде считанные в массив напряжений с АЦП, усредняются: суммируются и делятся на количество (D_NUM). При суммировании может произойти переполнение суммы (а она двухбайтная), чтобы этого не было, массив разбивается на группы по 16 измерений в каждой. Если осталась остаточная группа с числом меньше 16, то она отбрасывается. В каждой из них подсчитывается среднее, затем рассчитывается искомое как среднее средних.
Из среднего напряжения находится угол
a= .
Затем находим диаметр d=0,625 – 0,5cos a=00,A0H – 00,80Hcos a. Занести его в ячейку DIAM (2 байта в памяти). Сравнить диаметр с допустимыми пределами [0,2..0,5]=[0,33H..0,8H]. Если он выходит за эти пределы, то выдать на отбраковку (порт 02H) единицу.
Объем Vi находится как Vi=(p/4)d2×T1/T2=0,C9H×d2×T1/T2.
Листинг 22: обработчик запроса IRQ1
; – – – найти объем бревна и суммарный объем
; усреднение всех напряжений с датчика диаметра в массиве по адресу 1000H
IR1_H PUSH AF ;
PUSH BC ;
PUSH DE ;
PUSH HL ;
LD L, (D_NUM) ;
LD H, (D_NUM+1) ;
LD B, 4 ; делим D_NUM на 16
IR1_H1 SRL H ;
RR L ;
DJNZ IR1_H1 ;
LD C, L ; в результате C=число групп по 16
PUSH BC ; сохранить С в стеке
LD HL, #1000 ;
LD DE, 0 ; DE – начальная сумма групп
PUSH DE ; отправить ее в стек, C станет второй в стеке
PUSH DE ; DE – начальная сумма отдельной группы,
; отправить®в стек, сумма групп вторая в стеке
; C – третья в стеке
IR1_H4 LD B, 16 ;
IR1_H2 LD E, (HL) ; читаем в DE элемент массива
INC HL ;
LD D, (HL) ;
INC HL ;
EX (SP), HL ; текущую сумма в HL, текущий адрес в стеке
ADD HL, DE ;
EX (SP), HL ; новая сумма в стеке, текущий адрес в HL
DJNZ IR1_H2 ;
; в итоге сумма одной группы по 16 – в стеке
; начальный адрес следующей группы – в HL
POP DE ;
LD B, 4 ; находим среднее одной группы,
IR1_H3 SRL D ; деля сумму в DE на 16
RR E ;
DJNZ IR1_H3 ;
POP HL ; берем из стека сумму групп
ADD HL, DE ;
PUSH HL ; снова отправляем в стек: сначала сумму групп
PUSH DE ; затем сумму одной группы
DEC C ; С – счетчик групп
JR NZ, IR1_H4 ; следующая группа…
POP HL ;
POP HL ; извлечь найденную сумму групп
POP BC ; извлечь счетчик групп C
LD D, C ; DE=C.0
LD E, 0 ;
CALL DIV ; делим сумму групп на число групп
; теперь HL=Ud=среднее всего массива напряжений датчика
; следующий шаг – нахождение угла a, cos a, d
LD D, 4 ; DE=491H
LD E, #91 ;
LD B, H ; сохранить Ud в BC
LD C, L ;
EX DE, HL ;
CALL MINUS ; HL=491H-Ud
EX HL, DE ;
LD H, B ;
LD L, C ;
CALL DIV ; HL= Ud/(491H-Ud)
LD D, 0 ;
LD E, #4F ;
CALL MUL ; HL=a
CALL COS ; HL=cos a
LD D, 0 ;
LD E, #80 ;
CALL MUL ; HL=0,5cos a
LD D, 0 ;
LD E, #A0 ;
EX HL, DE ;
CALL MINUS ; HL=0,625-0,5cos a=d
LD (DIAM), HL ; занести диаметр в память
; формируем сигнал отбраковки
LD A, L ;
CP #33 ;
JR NC, IR1_H5 ; если d>20, то идем дальше
LD A, 1 ; иначе в порт отбраковки записать 1
OUT (#02), A ;
JR IR1_OUT ; и выход, не считая объем
IR1_H5 LD A, L ;
CP #80 ;
JR C, IR1_H6 ; если d<50, то идем дальше
LD A, 1 ; иначе в порт отбраковки записать 1
OUT (#02), A ;
; дальше находим Vi, VS
IR1_H6 LD L, (T1) ;
LD H, (T1+1) ;
LD E, (T2) ;
LD D, (T2+1) ;
CALL DIV ; HL=T1/T2
LD E, (DIAM) ;
LD D, (DIAM+1) ;
PUSH DE ;
CALL MUL ; HL=T1×d/T2
POP DE ;
CALL MUL ; HL=T1×d2/T2
LD D, 0 ;
LD E, #C9 ;
CALL MUL ; HL=(p/4)T1×d2/T2=Vi
EX HL, DE ;
LD L, (V_SUM) ;
LD H, (V_SUM+1) ;
CALL PLUS ; HL=VS
LD (V_SUM), HL ; занести суммарный объем в память
IR1_OUT POP HL ;
POP DE ;
POP BC ;
POP AF ;
RETI ;
Основная исполняемая часть программы
Эту часть, которая, собственно, и является управляющей программой, микропроцессор выполняет большую часть своего времени, изредка отвлекаясь от нее на обработку прерываний.
Ее функции:
прочесть V S из ячейки V_SUM, перевести его в 2-10 код (подпрограммы B2D, B2D_F), перевести каждую цифру в семисегментный код (подпрограмма D27) и вывести в порт индикаторов (03-0A), присоединив десятичную запятую в индикаторе 06Н;
прочесть время из ячейки TIME (TIME+1–секунды, TIME+2–минуты, TIME+3–часы), перевести его в 2-10 код, перевести каждую цифру в семисегментный код и вывести в порт индикаторов (13-1A), присоединив десятичную запятую в индикаторах 13Н, 15Н, 17Н.
Рис. 7 Расположение объема и времени на индикаторах
Листинг 23: основная часть
; – – – вывести на индикаторы объем и время
; вывод объема
MAIN LD E, (V_SUM) ;
LD D, (V_SUM+1) ; D.E – суммарный объем
; выводим целую часть D
LD C, D ;
CALL B2D ; HL=2-10 код D
LD A, H ;
CALL D27 ; в семисегментный код
OUT (#08), A ; вывести в порт
LD A, H ;
AND #0F ;
CALL D27 ;
OR #80 ; примешать десятичную запятую
OUT (#06), A ; вывести в порт
LD A, H ;
RR A ; четырежды сдвигаем вправо
RR A ;
RR A ;
RR A ;
AND #0F ;
CALL D27 ;
OUT (#07), A ; вывести в порт
; выводим дробную часть E
LD L, E ;
CALL B2D_F ; ABC=три цифры 2-10 кода числа 0.L
CALL D27 ;
OUT (#05), A ; вывести в порт
LD A, B ;
CALL D27 ;
OUT (#04), A ; вывести в порт
LD A, C ;
CALL D27 ;
OUT (#03), A ; вывести в порт
; вывод текущего времени
LD HL, (TIME+1) ; HL=адрес секунд
LD B, #13 ; самый правый индикатор
MAIN1 PUSH HL ;
LD A, (HL) ;
LD C, A ;
CALL B2D ; HL=2-10 код секунд/минут/часов (причем Н=0)
LD A, L ;
AND #0F ;
CALL D27 ;
OR #80 ; примешать запятую
OUT (B), A ; вывести в порт
INC B ; следующий индикатор
LD A, L ;
RR A ; четырежды сдвигаем А вправо
RR A ;
RR A ;
RR A ;
AND #0F ;
CALL D27 ;
OUT (B), A ; вывести в порт
INC B ; следующий индикатор
POP HL ;
INC HL ; перейти к следующей ячейке (TIME+2, TIME+3)
LD A, B ;
CP #08 ; проверка конца цикла
JR NZ, MAIN1 ;
JP MAIN ; начинаем все сначала
Дата добавления: 2019-07-15; просмотров: 161; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!