Гл5_07 (Раздаточный материал к курсовому проекту), страница 14
Описание файла
Файл "Гл5_07" внутри архива находится в следующих папках: Раздаточный материал к курсовому проекту, Доп_материалы. PDF-файл из архива "Раздаточный материал к курсовому проекту", который расположен в категории "". Всё это находится в предмете "системы автоматического управления (сау) (мт-11)" из 11 семестр (3 семестр магистратуры), которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "остальное", в предмете "системы автоматического управления (сау) (мт-11)" в общих файлах.
Просмотр PDF-файла онлайн
Текст 14 страницы из PDF
5.38).Для индивидуального выбора аппаратной инициализации ДК по любому каналу наFPGA сформировано два шестнадцатиразрядных регистра маски Masc1 и Masc2. Эти регистры доступны для чтения и записи по адресу BA+7 и BA+9 при любом значении регистра банков BNK. Запись единицы в бит регистра маски разрешает аппаратную инициализацию по соответствующему входу канала дискретного контроля, запись нуля - запрещает.Биты регистров маски и регистров событий поступают на входы блоков формирования запроса прерываний AND0…AND3. Каждый блок представляет из себя восемь ячеек«И», к входам которых подключены соответствующие биты регистров масок и регистровсобытий.
Запрос на прерывание формируется параллельно всеми блоками, если на выходехотя бы одной ячейки внутри блока появляется единица.Это происходит, если по какому либо из каналов фиксируется событие (появлениеединицы в соответствующем бите EVrg) и аппаратные прерывания по этому каналу разрешены (в бите с тем же номером регистра маски записана единица).Для выявления причины прерывания в подпрограмме его обслуживания следует читать содержимое регистров событий EVrg1 и EVrg2.
Снимается запрос на прерывание обнулением регистра событий, если этого не сделать, при выходе из подпрограммы обслуживания снова возникнет прерывание. Регистры событий аппаратно обнуляются при любойзаписи в них. Именно такой способ их обнуления приведен в последующих примерах программирования. Внутри подпрограммы обслуживания повторный запрос не возникнет, поскольку запросы равного и низшего приоритетов блокируются.Номер линии прерывания определяется содержимым трех младших битов регистраномера прерывания NIRQ. Этот регистр доступен по адресу ВА+13 и программно в негоможет быть записано число от 3 до 7.
Здесь, как и при выборе базового адреса платы,Рябов Владимир Тимофеевич. Кафедра «Электронные технологии в машиностроении»МГТУ им. Н. Э. Баумана, V_Ryabov@mail.ru43важно не допустить конфликта ресурсов и не использовать уже задействованные линии.Регистры ВА+14 и ВА+15 идентифицируют плату. В регистре с адресом ВА+14просто записан код символа «D», а с адресом ВА+15 – номер прошивки логической матрицы FPGA.Плата DI32 с прошивкой «D02»функционально похожа на плату МВД контроллераОРИОН, который мы рассматривали в разделе 5.1.Б. С той лишь разницей, что здесь любойиз тридцати двух каналов контроля может иметь аппаратную инициализацию, а у МВД –только шестнадцать. Кроме того, здесь можно по группам по восемь каналов выбирать видсобытия инициализации (записывать в пары бит регистра ВА+6: 0 - нет инициализации, 1 фронт сигнала, 2 - спад сигнала, 3 - фронт или спад сигнала). В модуле МВД событие«фронт или спад» было определено аппаратно.
Понять, что же наблюдалось, фронт илиспад, можно было, лишь прочитав входной регистр. Подавление дребезга контактов у платыМВД также не было.Использование механизма прерываний требует аккуратности, использовать аппаратную инициализацию контроля следует только по необходимости. Следует группировать входы, инициирующие аппаратные прерывания по виду событий (фронт и т.п.). Чтобы уложиться в одну группу, следует аппаратно сигналы сформировать так, чтобы инициирующие события были одинаковыми.Рассмотрим пример.
Допустим, нам нужно считать импульсы с двух расходомеров Q1 и Q2, чтобы знать количество поступающей среды и отводимой среды, например,какого либо реагента. Кроме того, мы должны следить за двумя конечными выключателями SA1 и SA2, чтобы реверсировать сканирующий привод, следить за реле давления, чтобы выключать подачу реагента, если уровень в баке выше нормы P_H или отключатьслив, если ниже P_L.Таким образов, есть шесть сигналов, для которых аппаратная инициализация рациональна.
Для примера программного дискретного контроля будем следить за двумя клапанами KL1_on (клапан 1 открыт?) и KL2_off (клапан 2 закрыт?).Импульсы с расходомера корректно считать по спаду. Чтобы инициирующим событием по всем шести каналам аппаратной инициализации сделать спад сигнала, можноиспользовать нормально замкнутый контакт конечных выключателей SA1 и SA2. Допустим, выходной сигнал реле давления также представляет из себя пару нормально открытых и нормально закрытых «сухих» контактов.
Тогда мы используем нормально закрытыеконтакты, чтобы инициирующим событием был спад сигнала.Об открытии первого клапана нам сообщает замыкание контактов конечного выключателя. Для разнообразия, пусть о закрытии второго нам сообщает пропадание постоянного напряжения +12 В.В таблице 5.3.1. приведен перечень рассматриваемых нами сигналов.Таблица 5.3.1.Наименование сигналаИмпульс с расходомераОбозн.Q1Импульс с расходомераQ2Левое положение приводаПравое положение приводаУровень выше нормыУровень ниже нормыКлапан 1 открытКлапан 2 закрытSA1SA2Р_НР_LKL1_onKL2_offУровень20мА, 30В,10 мс20мА, 30В,10 мс«сухой»контакт СКСКСКСКСК+12ВКонтакты+Di0,-Di0+Di1,-Di1+Di2,-Di2+Di3,-Di3+Di4,-Di4+Di5,-Di5+Di6,-Di6+Di7,-Di7ПримечаниеОткрытый коллектор, открытый эмиттер оптопарыОткрытый коллектор, открытый эмиттер оптопарыПравильнее было бы сигналы KL1_on и KL2_off не включать в группу (7..0) и собрать в этой группе только сигналы, требующие аппаратной инициализации. ОстальныеРябов Владимир Тимофеевич.
Кафедра «Электронные технологии в машиностроении»МГТУ им. Н. Э. Баумана, V_Ryabov@mail.ru44распределить в других группах с учетом времени антидребезга. Мы сами усложним себежизнь, чтобы рассмотреть, как в рамках одной группы можно обрабатывать сигналы спрограммной и аппаратной инициализацией.Здесь нам придется использовать механизм обработки прерываний, поэтому длянаписания программы используем язык С++, предоставляющий большие возможности впрограммировании прерываний, чем Pascal, используемый нами ранее.Нужно написать собственно процедуру обработки прерывания Read_Event, котораявыполнить соответствующие действия. Кроме того, нужна процедура, которая сформирует вектор прерывания, т.е.
по адресу вектора прерывания IRQ5 (такой номер линии изпредлагаемого диапазона линий 3..7 мы для конкретности выберем) запишет стартовыйадрес процедуры Read_Event.Сформировать вектор прерывания нам позволит стандартная функция С++ из библиотеки <dos.h>: void setvect(int INTERRUPT_NO, void interrupt NAME_HANDLER).Она процедуру обработки прерывания с именем NAME_HANDLER прикрепляет к вектору с заданным вектором прерывания INTERRUPT_NO. Следует отметить, что прерываниеIRQ5 использует вектор 13 десятичное или D шестнадцатеричное. В текстах для обозначения шестнадцатеричной системы записи после числа добавляют символ h или Н (Dh,DH), в языке С используют обычно префикс 0x (символ «ноль» символ «х»). 0xD – это иесть вектор прерывания IRQ5.
Ниже в таблице 5.3.2. приведены номера линий прерыванияи соответствующие им вектора прерывания и их источники.Таблица 5.3.2.Линия IRQ Адрес вектора INT Источник прерывания в ОС008hПрограммируемый таймер109hКонтроллер клавиатуры20AhКаскадирование второго контроллера8 70hЧасы реального времени9 71hПрограммно переадресовано на IRQ210 72hРезерв11 73hРезерв12 74hРезерв13 75hМатематический сопроцессор14 76hКонтроллер жесткого диска15 77hРезерв30BhПоследовательный порт COM240ChПоследовательный порт COM150DhПараллельный порт LPT260EhКонтроллер гибкого диска70FhПараллельный порт LPT2Из таблицы Вы видите, что адреса векторов прерываний плотно уложены в памяти истановится не очень понятным, как по адресу вектора пятого прерывания 0Dh, который мысобираемся использовать, записать адрес входа в процедуру обработки прерывания.
Ведьадрес записывается двумя шестнадцатиразрядными словами, сегментом и смещением внутри него. То есть, чтобы его записать необходимо окно в памяти, как минимум, в четыребайта, а у нас за вектором 0Dh сразу занят 0Eh. Дело в том, что в таблице приведены толькоадреса смещений внутри различных сегментов памяти. Стандартная процедура С setvect()помнит все сегменты и для ее использования достаточно записать значение INT.Когда мы работаем с одним каналом, использующим аппаратную инициализацию,мы знаем и адрес входа в процедуру, которую нужно запустить, она одна. Но когда каналов несколько, нужно из нескольких процедур выбрать и запустить одну, соответствующую каналу, в котором зафиксировано событие.
Хотелось бы иметь универсальную процедуру Read_Event, которая смогла бы запускать процедуры, имени которых, поэтому иРябов Владимир Тимофеевич. Кафедра «Электронные технологии в машиностроении»МГТУ им. Н. Э. Баумана, V_Ryabov@mail.ru45стартовых адресов, она не знает. Пойди туда, не знаю куда, принеси то, не знаю что. Здесьзадача попроще, куда пойти (адрес вектора прерываний) мы знаем.В С и Паскале есть аппарат ссылочных переменных, который нам поможет выполнить задуманное. Если, например, есть некоторая переменная указатель на целое ptr, то вней может храниться адрес некоторой целочисленной переменной.
И мы можем присвоить ей адрес переменной «а», «&a», тогда она будет зеркальной копией этой переменной«а». К ней можно обращаться просто через идентификатор «a», либо *ptr (то, на что указывает ptr). Точно также можно создать ссылки на процедуры, присвоить этим ссылкамадреса процедур и обращаться к ним через ссылки.Следующий пример демонстрирует это обращение, поочередно вызывая процедурычерез массив указателей на них.// ------------------ Заголовочные файлы и библиотеки, необходимые для трансляции---------------#include <bios.h>#include <conio.h>#include <dos.h>#include <stdlib.h>#include <stdio.h>//-----------------------Определение типа handler, как ссылки на процедуру-----------------------------typedef void ( *handler)(void);handler ev_channel[3]; //Определение массива ссылок на процедуру//--------------------------------------Описание трех процедур---------------------------------------------------void handchan1(void) { gotoxy(2,5); printf("сработал канал 0");}void handchan2(void) { gotoxy(2,6); printf("сработал канал 1");}void handchan3(void) { gotoxy(2,7); printf("сработал канал 2");}//------------------------------------------Основная программа---------------------------------------------------void main(void){unsigned int i;// Беззнаковое целое iint* ptr;// Ссылка (указатель) на целое (содержит адрес)int a=100;// Целое, исходно равное 100//---------------------------Присвоение ссылкам адресов входа в процедуры -----------------------------ev_channel[1]=&handchan1;ev_channel[2]=&handchan2;ev_channel[3]=&handchan3;clrscr(); gotoxy(1,1);//Очистить экран, курсор в первую позицию на первой строкеprintf("&a=%xh, a=%d, &ptr=%xh, ptr=%xh, *ptr=%d", &a ,a, &ptr, ptr, *ptr);/* -------------Будет напечатано: « &a=fff2h, a=100, &ptr=fff4h, ptr=8fb2h, *ptr=3855 »-----------Значение адресов зависят от транслятора, приведены те цифры, которые у меня получились */ptr=&a;/*-----Значение адреса «&a» присвоить указателю, при операторе *ptr=a – значение «a»--------присвоить той величине, на которую исходно ссылался ptr, будет записано 100 по адресу 8fb2h */gotoxy(1,2);printf("&a=%xh, a=%d, &ptr=%xh, ptr=%xh, *ptr=%d", &a ,a, &ptr, ptr, *ptr);//---------------- Будет напечатано: « &a=fff2h, a=100, &ptr=fff4h, ptr=fff2h, *ptr=100»--------------------gotoxy(1,9);printf("привет, для выхода нажмите ESC...");//----------- Поочередное выполнение процедур handchan1, handchan2 и handchan3----------------for (i=1;i<4;i++) (*ev_channel[i])();//------------------Далее идет цикл с выходом по нажатию клавиши ESC, код 11Вh ---------------------for (;;){ if ( kbhit()) { i=bioskey(0); if (i== 0x11B) return;} };}//=======================Конец программы===============================Текст программы, которая проводит дискретный контроль с аппаратной и программной инициализацией приведен ниже.