Страница 1 из 2

Прерывания

Добавлено: 27 окт 2015, 09:03
danya
Здравствуйте! Вопрос у меня возник следующего характера. У меня есть плата стороннего производителя, не NI, есть библиотека на labview для работы с ней. Как мне отлавливать прерывания с этой платы? Имеется ВПП, который возвращает массив данных очередного прерывания.

Re: Прерывания

Добавлено: 27 окт 2015, 09:44
dadreamer
Не зная производителя и марку платы, можно только сказать в общих чертах. Очевидно, что "ловить" прерывания нужно в цикле и с помощью API этой платы. Вот похожая тема: http://www.labviewportal.org/viewtopic.php?f=81&t=3119

Re: Прерывания

Добавлено: 27 окт 2015, 09:46
danya
Плата фирмы Элкус, tc1/pci4. Благодарю, почитаю эту тему.

Re: Прерывания

Добавлено: 27 окт 2015, 10:19
dadreamer
Что-то не могу найти такую плату в каталоге: http://www.elcus.ru/index.php?ID=price

Re: Прерывания

Добавлено: 27 окт 2015, 10:45
danya
Извините, я ошиблась, опечаталась - TA1-PCI4. http://www.elcus.ru/boards.php?ID=ta1-pci4
В API есть ВПП, как я уже писала, возвращающая массив прерывания, полученного от устройства. Я немного не могу понять как именно со стороны labview, поймать его. Использовать событие или цикл, каким образом.

Re: Прерывания

Добавлено: 27 окт 2015, 11:26
dadreamer
У вас в примере представлен вариант получения прерываний в цикле While:
2015-10-27_13-24-16.jpg
Описание выходных данных есть в контекстной справке :vi: и в DOC'овских файлах, идущих в комплекте с примерами.

Re: Прерывания

Добавлено: 27 окт 2015, 12:28
danya
Да, и правда. То есть существует только вариант проверять tmkgtevd каждую 1 мс как на этой блок-диаграмме. Я думала, что возможно есть еще какой-то более удобный вариант, чтобы программа реагировала на появление очередного прерывания. Вам спасибо! :thank:

Re: Прерывания

Добавлено: 27 окт 2015, 14:37
dadreamer
Ну, видимо, разработчик не удосужился реализовать эвенты или это оказалось сложновыполнимо. Но вы должны руководствоваться своим ТЗ. Если допускается более низкая частота опроса прибора, то можно задержку увеличить.

Re: Прерывания

Добавлено: 11 ноя 2015, 17:50
danya
А в случае, если нужна более высокая частота опроса, 2 кГц например, возможно ли такое реализовать?

Re: Прерывания

Добавлено: 11 ноя 2015, 19:12
dadreamer
Боюсь, что на обычной винде никак, потому что максимум, на который способен таймер - это 1 кГц. Для бóльших частот придётся использовать RT контроллер с RT OS. Однако придётся тогда и плату другую использовать.

Re: Прерывания

Добавлено: 11 ноя 2015, 21:38
AndreyDmitriev
dadreamer писал(а):Боюсь, что на обычной винде никак, потому что максимум, на который способен таймер - это 1 кГц. Для бóльших частот придётся использовать RT контроллер с RT OS. Однако придётся тогда и плату другую использовать.
Ну не всё так уж плохо - процессор-то у нас не на 1 кГц тактируется, так что получить в LabVIEW более-менее детерминированную задержку меньше миллисекунды вполне себе можно. Единственное - с чем придётся смириться - в цикле ожидания нам придётся крутить "холостой" цикл, который будет требовать ресурсов процессора, но нынче процессоры многоядерные, так что на общей производительности это не очень скажется.
В последних версиях у нас есть таймер высокого разрешения, можно реализовать задержку на его основе. В старых версиях можно воспользоваться библиотекой:
http://www.ni.com/example/28582/en/
Только там таймер надо чуть доработать напильником - вызов DLL осуществлять не в UI потоке (пометить это дело как "потокобезопасный" вызов, ну и отключить отладку и поднять приоритет до time critical. Ну и вычесть накладные расходы на вызов таймера - у меня это примерно 40 микросекунд. Так что цикл с задержкой 0,46 мс крутится примерно на два килогерца.
Но надо понимать, что задержка там организована примерно вот так:
while ((current-start)< delay) Time_Get(&current);
так что одноядреный процессор чуть более чем полностью будет занят ожиданием.

Более правильно работать с прерываниями через библиотеку-обёртку. Грубо говоря в библиотеке, поставляемой с драйвером должна быть функция, в которую надо передать адрес своей функции-обработчика прерывания из обёртки. Соответственно при наступлении прерывания будет вызвана наша функция, а там уже можно передать данные в LabVIEW, скажем уведомив LabVIEW через occurence. Плюс такого подхода в том, что "вхолостую" крутящихся циклов у нас вообще не будет и загрузка процессора в режиме ожидания будет стремиться к нулю. Кроме того, прерывания должны быть буферизованы (если наступило следующее прерывание, а мы ещё не освободили обработчик, то данные складываются в буфер, содержимое которого будет нам передано при следующем вызове обработчика). Буфер в плате вроде есть - на 256 слов, а как организовать обработчик - это уже документацию надо смотреть.
В принципе надо понимать, что Windows - не есть система жёсткого реального времени, так что всегда есть опасность потери сообщений в том случае, когда буфер уже заполнен, но не прочитан и при этом наступило следующее прерывание. Чем больше буфер и ниже частота прерываний, тем меньше вероятность потери данных.

Re: Прерывания

Добавлено: 11 ноя 2015, 22:17
dadreamer
AndreyDmitriev писал(а):В последних версиях у нас есть таймер высокого разрешения, можно реализовать задержку на его основе.
А ведь верно, что-то у меня из головы вылетел вообще этот таймер. :D Видимо, торопился, когда писал. В 2010-м :labview: уже есть High Resolution Relative Seconds.vi, так что проблем с этим быть не должно.
AndreyDmitriev писал(а):как организовать обработчик - это уже документацию надо смотреть.
Вот что нашёл в документации на драйвер:
В драйверах Windows работа с прерываниями осуществляется через механизм событий Win32. Прежде всего, процесс должен сообщить драйверу идентификатор (handle) используемого события для текущего выбранного ТМК через вызов функции tmkdefevent, которой передается в качестве первого параметра идентификатор события Win32, полученный из Win32 вызова CreateEvent:

void tmkdefevent(HANDLE hEvent, BOOL fEventSet);

Нулевое значение hEvent отменяет использование события. Значение параметра fEventSet равное TRUE указывает на необходимость установки события драйвером через вызовы SetEvent, а значение FALSE - через вызовы PulseEvent. Внимание! В текущей версии драйвера значение переменной fEventSet игнорируется (принимается равным TRUE). Кроме того, рекомендуется вызывать функцию ResetEvent непосредственно перед вызовом tmkdefevent.
Во враппере для :labview: (lvtmk.dll) функция tmkdefevent есть. Только вот в примере почему-то никакой event не создаётся:
2015-11-12_0-14-20.jpg
2015-11-12_0-14-20.jpg (21.93 КБ) 10480 просмотров
Видимо, нужно создать эвент и передать его хэндл в функцию, а потом ожидать события через WaitForSingleObject, например. Сам это проверить не могу, ибо железки такой нет. :dntknw:

Re: Прерывания

Добавлено: 12 ноя 2015, 12:43
danya
Как бы в теории мне вроде бы понятно о чем вы говорите. А как сделать все равно не ясно.
Из библиотеки на плату есть только функция tmkgetevd, которая выдает данные о прерывании, ее видимо и нужно постоянно опрашивать... Я пыталась создать пользовательское событие на получение данных о прерывании, но как в данном случае контролировать время не знаю. Поэтому что-то не выходит толком, скорее всего не так делаю, не знаю те ли я вообще средства labview использую. В целом передо мной стоит задача снятия данных с устройства, а прерывание как раз таки возникает при приеме данных, т.е. в моем понимание я должна получить прерывание - считать данные, обработать и т.д. и все это еще в определенных временных рамках.

Re: Прерывания

Добавлено: 12 ноя 2015, 14:03
dadreamer
User Events здесь вообще никаким местом не подходят. Вам нужно использовать узлы Call Library Function Node для работы с прерываниями по событиям. Этот метод лучше постоянного опроса устройства тем, что снижается нагрузка на процессор. При инициализации платы делаете так:
1. hEvent CreateEvent (NULL, TRUE, FALSE, NULL);
2. bReset ResetEvent (hEvent);
3. void tmkdefevent (hEvent, TRUE);

В процессе работы в отдельном цикле выполняете:
4. dWait WaitForSingleObject (hEvent, INFINITE=0xFFFFFFF);
Как только функция вернула WAIT_OBJECT_0=0, получаете массив прерываний стандартным образом.

При закрытии платы вызываете
5. bResult CloseHandle (hEvent);

Вроде бы это всё. Не забудьте сделать вызовы CLFN реентерантными (Run In Any Thread), а то ожидание эвента подвесит UI поток :labview: .

Сделал вам вот такой пример. Не знаю, как будет работать в реальности, но надеюсь, что всё будет ок. Заодно улучшил некоторые :vi: от производителя для более удачного построения dataflow на БД (включены в исходную llb с пометкой _new). Если есть желание, можете переделать и другие :vi: по такому же принципу.

Re: Прерывания TA1-104-2

Добавлено: 27 июл 2016, 11:56
m1ndst0rm
Подскажите, пожалуйста.
Плата тоже Элкус TA1-104-2 (два терминала независимых на одной плате формата pc/104).

Устройство генератор сигналов по МКПД отправляет посылки по 32 слова с максимальной скоростью, на которое способно.

Штатная программа-монитор от Элкус "ловит" около 1700 посылок в секунду.

Самая быстрая версия ОУ на LabVIEW (2009) нескомпилированная (возможно, это важно!) способна поймать порядка 400 посылок в секунду.

То есть монитор от Элкус (на С++, скорее всего)работает сильно быстрее LabVIEW.
В чем может быть проблема?


И второй вопрос, более важный:

Когда источник выдаёт посылки в режиме максимальной скорости (порядка 1700 в секунду по 32 слова) - прерывания с помощью tmkgetevd (TMK get event data) отлавливаются, с горем пополам (в 15-20 раз медленнее, чем приходят посылки).

Но если тот же источник отправляет посылки редко ( 1-10 а секунду) по тому же протоколу, той же линии итд - прерывания не приходят вообще.

Причём посылки достоверно отправляются - их видно монитором, в адрес того же ОУ1.

Как так может быть?
По какой причине ТМК в режиме ОУ может не генерировать прерывание в случае получения (??) посылки?

Я так понимаю, если посылка приходит, с любой скоростью (плотностью) передачи - по каждому сообщению генерируется прерывание, которое в цикле while можно ждать как 0 элемент массива данных функции tmkgetevd (если не 0 - значит пришли данные - оно же код результата обмена).
Почему tmkgetevd может никогда не выдавать "прерывания" при получении сообщений?