Введение N отсчетов (1000≤N≤2000) с АЦП в ОЗУ в режиме прямого доступа к памяти, нахождение их среднего значения и вывод его на индикатор, страница 3

При окончании циклов ПДП формируется прерывание в процедуре обработчике которого процессор обрабатывает массив полученных данных -  находит среднее путем сначала сложения их всех - получается 16ти битное значение, а затем делится на их число. таким образом формируется среднее значение в двоичном коде. Для его преобразования в десятичный оттуда выделяются сотни десятки и единицы - получается двоично-десятичный код, который выдается на адрес индикатора и запоминается в регистрах и отображается на индикаторах до следующего обновления таким же образом.

Описание программы

Начальные установки

Карта адресов:

0xxxh                    ПЗУ

7xxxh                    ПЗУ

Fxxxh          ПЗУ

1xxxh                    КПДП

2xxxh                    Индикатор

3xxxh                    АЦП

4xxxh                    ОЗУ

CAR_BAR_0        equ    1000h;         канал 0

WCR_CWR_0      equ    1001h;

CAR_BAR_1        equ    1002h;         канал 1

WCR_CWR_1      equ    1003h;

CAR_BAR_2        equ    1004h;         канал 2

WCR_CWR_2      equ    1005h;

CAR_BAR_3        equ    1006h;         канал 3

WCR_CWR_3      equ    1007h;

KPDP_RU             equ    1008h;                   регистр управления

KPDP_RR             equ    1009h;                   регистр запросов

KPDP_MASK_ALL_SET        equ    100Ah;        установка всех разрядов маски

KPDP_МR            equ    100Bh;                   регистр режима

KPDP_L0wBYTE equ    100Ch;                   установка режима ввода младшего байта

KPDP_RD_TR     equ    100Dh;                  чтение регистра временного хранения

KPDP_CLR          equ    100Dh;                  общий сброс

KPDP_MASK_ALL_CLR       equ    100Eh;         сброс всех разрядов маски

KPDP_MASK_ONE_SET        equ    100Fh;         установка одного разряда маски

IND   equ    2000h;

ACP  equ    3000h;

N       const  1500;                                    число отсчетов N

Немаскируемое прерывание (окончание циклов ПДП)

ORG 00008h;        вектор входа в прерывание по входу NMI

push AX;    

mov KPDP_CLR, 0;       сброс КПДП (сброс запросов и флагов окончания) + автоинициализация

Теперь контроллер готов к следующему циклу - все начальные значения регистров восстановлены

clr AX;

clr BX;

clr CX;

cikl:

mov BL, DS:[AX];          Достаем из ОЗУ значение по адресу смещение + АХ

add CX, BX;                    суммируем с СХ

inc AX;                            увеличиваем адрес

cmp AX, N;           сравниваем не вышли ли за диапазон

jne cikl;                 если нет то повторяем до тех пор пока не просуммируем все значения

Теперь в СХ сумма N значений - надо поделить на N - получим среднее арифметическое. Надо поделить 16-ти битное на 16-ти битное, а процессор умеет 16 на 8. Сократим делитель и делимое на 8 - при Н до 2047 это дает уложиться в диапазон.

sar CX, 3;              арифметический сдвиг вправо на 3 разряда есть целочисленное деление на 8

mob BX, N;

sar BX, 3;              арифметический сдвиг вправо на 3 разряда есть целочисленное деление на 8

mov AX, CX;

div BL;                  поделили результат в AL, остаток в AH

Перевод 16-ричного в десятичное (сотни десятки единицы)

clr BX;                   очищаем, тут будет потом результат

ssub100:

sub AL, 100;         -100

add BX, 0100h;     прибавляем 1 в третью тетраду

jns ssub100;            если положительный то еще раз

sub BX, 0100h;     если стало отрицательным значит вычли лишнего - возвращаем: вычитаем 1 из сотен

add AL, 100;         прибавляем лишнюю вычтенную сотню

ssub10:

sub AL, 10; -10

add BX, 0010h;     прибавляем 1 в 2ю тетраду

jns ssub10;            если положительный то еще раз

sub BX, 0010h;     если стало отрицательным значит вычли лишнего - возвращаем: вычитаем 1 из десятков

add AL, 10;            прибавляем лишнюю вычтенную десятку

add BL, AL;          прибавляем оставшиеся единицы, в ВХ получаем потетрадно: 0 сотни десятки единицы

Выдаем на индикатор результат

mov IND, BX;       выдаем результат на индикатор - он "защелкнется" в регистрах и будет гореть на табло

pop AX;

iret;                        восстановление всего из стека

Начальная установка по сбросу                                                                                                                                                                

Reset:

Задаем смещения

mov CS, 0000h;    память программ ПЗУ

mov DS, 0400h;    ОЗУ

mov SS, 04F0h;    делаем стек в ОЗУ 256 байт - 64 уровня

Настройка контроллера ПДП

PDP_Init:

mov KPDP_CLR, 0;       сброс КПДП

Настраиваем каналы 0 и 1 (их адреса) для работы в режиме ПАМЯТЬ-ПАМЯТЬ. 2 и 3 произвольно

канал 0:

mov AX, 3000h;              адрес АЦП

mov CAR_BAR_0, AL; Младший байт

mov CAR_BAR_0, AH; Затем сразу старший

mov AX, N;           число циклов (считываемых значений)

mov WCR_CWR_0, AL;          млад байт

mov WCR_CWR_0, AH;         старший байт

канал :1

mov AX, 4000h;              Начальный адрес ОЗУ

mov CAR_BAR_1, AL; Младший байт

mov CAR_BAR_1, AH; Затем сразу старший

mov AX, N;           число циклов (считываемых значений)

mov WCR_CWR_1, AL;          млад байт

mov WCR_CWR_1, AH;         старший байт

канал 2:      

mov AX, 4000h;              Начальный адрес ОЗУ

mov CAR_BAR_2, AL; Младший байт