Прерывания
-
- junior
- Сообщения: 52
- Зарегистрирован: 23 мар 2015, 18:29
- Версия LabVIEW: 2010
- Контактная информация:
Прерывания
Здравствуйте! Вопрос у меня возник следующего характера. У меня есть плата стороннего производителя, не NI, есть библиотека на labview для работы с ней. Как мне отлавливать прерывания с этой платы? Имеется ВПП, который возвращает массив данных очередного прерывания.
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Прерывания
Не зная производителя и марку платы, можно только сказать в общих чертах. Очевидно, что "ловить" прерывания нужно в цикле и с помощью API этой платы. Вот похожая тема: http://www.labviewportal.org/viewtopic.php?f=81&t=3119
-
- junior
- Сообщения: 52
- Зарегистрирован: 23 мар 2015, 18:29
- Версия LabVIEW: 2010
- Контактная информация:
Re: Прерывания
Извините, я ошиблась, опечаталась - TA1-PCI4. http://www.elcus.ru/boards.php?ID=ta1-pci4
В API есть ВПП, как я уже писала, возвращающая массив прерывания, полученного от устройства. Я немного не могу понять как именно со стороны labview, поймать его. Использовать событие или цикл, каким образом.
В API есть ВПП, как я уже писала, возвращающая массив прерывания, полученного от устройства. Я немного не могу понять как именно со стороны labview, поймать его. Использовать событие или цикл, каким образом.
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Прерывания
У вас в примере представлен вариант получения прерываний в цикле While:
Описание выходных данных есть в контекстной справке и в DOC'овских файлах, идущих в комплекте с примерами.-
- junior
- Сообщения: 52
- Зарегистрирован: 23 мар 2015, 18:29
- Версия LabVIEW: 2010
- Контактная информация:
Re: Прерывания
Да, и правда. То есть существует только вариант проверять tmkgtevd каждую 1 мс как на этой блок-диаграмме. Я думала, что возможно есть еще какой-то более удобный вариант, чтобы программа реагировала на появление очередного прерывания. Вам спасибо!
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Прерывания
Ну, видимо, разработчик не удосужился реализовать эвенты или это оказалось сложновыполнимо. Но вы должны руководствоваться своим ТЗ. Если допускается более низкая частота опроса прибора, то можно задержку увеличить.
-
- junior
- Сообщения: 52
- Зарегистрирован: 23 мар 2015, 18:29
- Версия LabVIEW: 2010
- Контактная информация:
Re: Прерывания
А в случае, если нужна более высокая частота опроса, 2 кГц например, возможно ли такое реализовать?
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Прерывания
Боюсь, что на обычной винде никак, потому что максимум, на который способен таймер - это 1 кГц. Для бóльших частот придётся использовать RT контроллер с RT OS. Однако придётся тогда и плату другую использовать.
-
- VIP
- Сообщения: 1339
- Зарегистрирован: 03 фев 2010, 00:42
- Награды: 6
- Версия LabVIEW: 6.1 - 2024
- Откуда: Германия
- Благодарил (а): 1 раз
- Поблагодарили: 44 раза
- Контактная информация:
Re: Прерывания
Ну не всё так уж плохо - процессор-то у нас не на 1 кГц тактируется, так что получить в LabVIEW более-менее детерминированную задержку меньше миллисекунды вполне себе можно. Единственное - с чем придётся смириться - в цикле ожидания нам придётся крутить "холостой" цикл, который будет требовать ресурсов процессора, но нынче процессоры многоядерные, так что на общей производительности это не очень скажется.dadreamer писал(а):Боюсь, что на обычной винде никак, потому что максимум, на который способен таймер - это 1 кГц. Для бóльших частот придётся использовать RT контроллер с RT OS. Однако придётся тогда и плату другую использовать.
В последних версиях у нас есть таймер высокого разрешения, можно реализовать задержку на его основе. В старых версиях можно воспользоваться библиотекой:
http://www.ni.com/example/28582/en/
Только там таймер надо чуть доработать напильником - вызов DLL осуществлять не в UI потоке (пометить это дело как "потокобезопасный" вызов, ну и отключить отладку и поднять приоритет до time critical. Ну и вычесть накладные расходы на вызов таймера - у меня это примерно 40 микросекунд. Так что цикл с задержкой 0,46 мс крутится примерно на два килогерца.
Но надо понимать, что задержка там организована примерно вот так:
while ((current-start)< delay) Time_Get(¤t);
так что одноядреный процессор чуть более чем полностью будет занят ожиданием.
Более правильно работать с прерываниями через библиотеку-обёртку. Грубо говоря в библиотеке, поставляемой с драйвером должна быть функция, в которую надо передать адрес своей функции-обработчика прерывания из обёртки. Соответственно при наступлении прерывания будет вызвана наша функция, а там уже можно передать данные в LabVIEW, скажем уведомив LabVIEW через occurence. Плюс такого подхода в том, что "вхолостую" крутящихся циклов у нас вообще не будет и загрузка процессора в режиме ожидания будет стремиться к нулю. Кроме того, прерывания должны быть буферизованы (если наступило следующее прерывание, а мы ещё не освободили обработчик, то данные складываются в буфер, содержимое которого будет нам передано при следующем вызове обработчика). Буфер в плате вроде есть - на 256 слов, а как организовать обработчик - это уже документацию надо смотреть.
В принципе надо понимать, что Windows - не есть система жёсткого реального времени, так что всегда есть опасность потери сообщений в том случае, когда буфер уже заполнен, но не прочитан и при этом наступило следующее прерывание. Чем больше буфер и ниже частота прерываний, тем меньше вероятность потери данных.
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Прерывания
А ведь верно, что-то у меня из головы вылетел вообще этот таймер. Видимо, торопился, когда писал. В 2010-м уже есть High Resolution Relative Seconds.vi, так что проблем с этим быть не должно.AndreyDmitriev писал(а):В последних версиях у нас есть таймер высокого разрешения, можно реализовать задержку на его основе.
Вот что нашёл в документации на драйвер:AndreyDmitriev писал(а):как организовать обработчик - это уже документацию надо смотреть.
Во враппере для (lvtmk.dll) функция tmkdefevent есть. Только вот в примере почему-то никакой event не создаётся: Видимо, нужно создать эвент и передать его хэндл в функцию, а потом ожидать события через WaitForSingleObject, например. Сам это проверить не могу, ибо железки такой нет.В драйверах Windows работа с прерываниями осуществляется через механизм событий Win32. Прежде всего, процесс должен сообщить драйверу идентификатор (handle) используемого события для текущего выбранного ТМК через вызов функции tmkdefevent, которой передается в качестве первого параметра идентификатор события Win32, полученный из Win32 вызова CreateEvent:
void tmkdefevent(HANDLE hEvent, BOOL fEventSet);
Нулевое значение hEvent отменяет использование события. Значение параметра fEventSet равное TRUE указывает на необходимость установки события драйвером через вызовы SetEvent, а значение FALSE - через вызовы PulseEvent. Внимание! В текущей версии драйвера значение переменной fEventSet игнорируется (принимается равным TRUE). Кроме того, рекомендуется вызывать функцию ResetEvent непосредственно перед вызовом tmkdefevent.
-
- junior
- Сообщения: 52
- Зарегистрирован: 23 мар 2015, 18:29
- Версия LabVIEW: 2010
- Контактная информация:
Re: Прерывания
Как бы в теории мне вроде бы понятно о чем вы говорите. А как сделать все равно не ясно.
Из библиотеки на плату есть только функция tmkgetevd, которая выдает данные о прерывании, ее видимо и нужно постоянно опрашивать... Я пыталась создать пользовательское событие на получение данных о прерывании, но как в данном случае контролировать время не знаю. Поэтому что-то не выходит толком, скорее всего не так делаю, не знаю те ли я вообще средства labview использую. В целом передо мной стоит задача снятия данных с устройства, а прерывание как раз таки возникает при приеме данных, т.е. в моем понимание я должна получить прерывание - считать данные, обработать и т.д. и все это еще в определенных временных рамках.
Из библиотеки на плату есть только функция tmkgetevd, которая выдает данные о прерывании, ее видимо и нужно постоянно опрашивать... Я пыталась создать пользовательское событие на получение данных о прерывании, но как в данном случае контролировать время не знаю. Поэтому что-то не выходит толком, скорее всего не так делаю, не знаю те ли я вообще средства labview использую. В целом передо мной стоит задача снятия данных с устройства, а прерывание как раз таки возникает при приеме данных, т.е. в моем понимание я должна получить прерывание - считать данные, обработать и т.д. и все это еще в определенных временных рамках.
-
dadreamer
- professor
- Сообщения: 3926
- Зарегистрирован: 17 фев 2013, 16:33
- Награды: 4
- Версия LabVIEW: 2.5 — 2022
- Благодарил (а): 11 раз
- Поблагодарили: 127 раз
- Контактная информация:
Re: Прерывания
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 поток .
Сделал вам вот такой пример. Не знаю, как будет работать в реальности, но надеюсь, что всё будет ок. Заодно улучшил некоторые от производителя для более удачного построения dataflow на БД (включены в исходную llb с пометкой _new). Если есть желание, можете переделать и другие по такому же принципу.
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 поток .
Сделал вам вот такой пример. Не знаю, как будет работать в реальности, но надеюсь, что всё будет ок. Заодно улучшил некоторые от производителя для более удачного построения dataflow на БД (включены в исходную llb с пометкой _new). Если есть желание, можете переделать и другие по такому же принципу.
- Вложения
-
- LVTMK_Win32_Events.vi
- lv2010
- (17.78 КБ) 152 скачивания
-
- Lvtmk.llb
- (1.41 МБ) 151 скачивание
-
- interested
- Сообщения: 7
- Зарегистрирован: 10 окт 2011, 08:18
- Версия LabVIEW: 9.0
- Контактная информация:
Re: Прерывания TA1-104-2
Подскажите, пожалуйста.
Плата тоже Элкус 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 может никогда не выдавать "прерывания" при получении сообщений?
Плата тоже Элкус 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 может никогда не выдавать "прерывания" при получении сообщений?