Прерывания

Простейшие вопросы в области инженерной разработки

Прерывания

Postby danya on 27 Oct 2015, 09:03

Здравствуйте! Вопрос у меня возник следующего характера. У меня есть плата стороннего производителя, не NI, есть библиотека на labview для работы с ней. Как мне отлавливать прерывания с этой платы? Имеется ВПП, который возвращает массив данных очередного прерывания.
danya
junior
junior
 
Posts: 52
Joined: 23 Mar 2015, 18:29
LabVIEW Version: 2010
Karma: 0

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

Postby dadreamer on 27 Oct 2015, 09:44

Не зная производителя и марку платы, можно только сказать в общих чертах. Очевидно, что "ловить" прерывания нужно в цикле и с помощью API этой платы. Вот похожая тема: http://www.labviewportal.ru/viewtopic.php?f=81&t=3119
User avatar
dadreamer
doctor
doctor
 
Posts: 2867
Joined: 17 Feb 2013, 16:33
Medals: 4
Activity (1) Professionalism (1) Автор (2)
LabVIEW Version: 2.5 — 2017
Karma: 705
I/O VIP vision internet

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

Postby danya on 27 Oct 2015, 09:46

Плата фирмы Элкус, tc1/pci4. Благодарю, почитаю эту тему.
danya
junior
junior
 
Posts: 52
Joined: 23 Mar 2015, 18:29
LabVIEW Version: 2010
Karma: 0

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

Postby dadreamer on 27 Oct 2015, 10:19

Что-то не могу найти такую плату в каталоге: http://www.elcus.ru/index.php?ID=price
User avatar
dadreamer
doctor
doctor
 
Posts: 2867
Joined: 17 Feb 2013, 16:33
Medals: 4
Activity (1) Professionalism (1) Автор (2)
LabVIEW Version: 2.5 — 2017
Karma: 705
I/O VIP vision internet

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

Postby danya on 27 Oct 2015, 10:45

Извините, я ошиблась, опечаталась - TA1-PCI4. http://www.elcus.ru/boards.php?ID=ta1-pci4
В API есть ВПП, как я уже писала, возвращающая массив прерывания, полученного от устройства. Я немного не могу понять как именно со стороны labview, поймать его. Использовать событие или цикл, каким образом.
danya
junior
junior
 
Posts: 52
Joined: 23 Mar 2015, 18:29
LabVIEW Version: 2010
Karma: 0

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

Postby dadreamer on 27 Oct 2015, 11:26

У вас в примере представлен вариант получения прерываний в цикле While:
2015-10-27_13-24-16.jpg

Описание выходных данных есть в контекстной справке :vi: и в DOC'овских файлах, идущих в комплекте с примерами.
User avatar
dadreamer
doctor
doctor
 
Posts: 2867
Joined: 17 Feb 2013, 16:33
Medals: 4
Activity (1) Professionalism (1) Автор (2)
LabVIEW Version: 2.5 — 2017
Karma: 705
I/O VIP vision internet

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

Postby danya on 27 Oct 2015, 12:28

Да, и правда. То есть существует только вариант проверять tmkgtevd каждую 1 мс как на этой блок-диаграмме. Я думала, что возможно есть еще какой-то более удобный вариант, чтобы программа реагировала на появление очередного прерывания. Вам спасибо! :thank:
danya
junior
junior
 
Posts: 52
Joined: 23 Mar 2015, 18:29
LabVIEW Version: 2010
Karma: 0

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

Postby dadreamer on 27 Oct 2015, 14:37

Ну, видимо, разработчик не удосужился реализовать эвенты или это оказалось сложновыполнимо. Но вы должны руководствоваться своим ТЗ. Если допускается более низкая частота опроса прибора, то можно задержку увеличить.
User avatar
dadreamer
doctor
doctor
 
Posts: 2867
Joined: 17 Feb 2013, 16:33
Medals: 4
Activity (1) Professionalism (1) Автор (2)
LabVIEW Version: 2.5 — 2017
Karma: 705
I/O VIP vision internet

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

Postby danya on 11 Nov 2015, 17:50

А в случае, если нужна более высокая частота опроса, 2 кГц например, возможно ли такое реализовать?
danya
junior
junior
 
Posts: 52
Joined: 23 Mar 2015, 18:29
LabVIEW Version: 2010
Karma: 0

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

Postby dadreamer on 11 Nov 2015, 19:12

Боюсь, что на обычной винде никак, потому что максимум, на который способен таймер - это 1 кГц. Для бóльших частот придётся использовать RT контроллер с RT OS. Однако придётся тогда и плату другую использовать.
User avatar
dadreamer
doctor
doctor
 
Posts: 2867
Joined: 17 Feb 2013, 16:33
Medals: 4
Activity (1) Professionalism (1) Автор (2)
LabVIEW Version: 2.5 — 2017
Karma: 705
I/O VIP vision internet

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

Postby AndreyDmitriev on 11 Nov 2015, 21:38

dadreamer wrote:Боюсь, что на обычной винде никак, потому что максимум, на который способен таймер - это 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 - не есть система жёсткого реального времени, так что всегда есть опасность потери сообщений в том случае, когда буфер уже заполнен, но не прочитан и при этом наступило следующее прерывание. Чем больше буфер и ниже частота прерываний, тем меньше вероятность потери данных.
User avatar
AndreyDmitriev
VIP
VIP
 
Posts: 1225
Joined: 03 Feb 2010, 00:42
Location: Германия
Medals: 6
Activity (1) Professionalism (1) Tutorials (1) Gold (1) Black (2)
LabVIEW Version: 6.1 - 2016
Karma: 433

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

Postby dadreamer on 11 Nov 2015, 22:17

AndreyDmitriev wrote:В последних версиях у нас есть таймер высокого разрешения, можно реализовать задержку на его основе.

А ведь верно, что-то у меня из головы вылетел вообще этот таймер. :D Видимо, торопился, когда писал. В 2010-м :labview: уже есть High Resolution Relative Seconds.vi, так что проблем с этим быть не должно.
AndreyDmitriev wrote:как организовать обработчик - это уже документацию надо смотреть.

Вот что нашёл в документации на драйвер:
В драйверах 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 KiB) Viewed 3327 times

Видимо, нужно создать эвент и передать его хэндл в функцию, а потом ожидать события через WaitForSingleObject, например. Сам это проверить не могу, ибо железки такой нет. :dntknw:
User avatar
dadreamer
doctor
doctor
 
Posts: 2867
Joined: 17 Feb 2013, 16:33
Medals: 4
Activity (1) Professionalism (1) Автор (2)
LabVIEW Version: 2.5 — 2017
Karma: 705
I/O VIP vision internet

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

Postby danya on 12 Nov 2015, 12:43

Как бы в теории мне вроде бы понятно о чем вы говорите. А как сделать все равно не ясно.
Из библиотеки на плату есть только функция tmkgetevd, которая выдает данные о прерывании, ее видимо и нужно постоянно опрашивать... Я пыталась создать пользовательское событие на получение данных о прерывании, но как в данном случае контролировать время не знаю. Поэтому что-то не выходит толком, скорее всего не так делаю, не знаю те ли я вообще средства labview использую. В целом передо мной стоит задача снятия данных с устройства, а прерывание как раз таки возникает при приеме данных, т.е. в моем понимание я должна получить прерывание - считать данные, обработать и т.д. и все это еще в определенных временных рамках.
Attachments
Снимок.JPG
Вот как то так пробовала, но со временем здесь вообще никак
danya
junior
junior
 
Posts: 52
Joined: 23 Mar 2015, 18:29
LabVIEW Version: 2010
Karma: 0

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

Postby dadreamer on 12 Nov 2015, 14:03

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: по такому же принципу.
Attachments
LVTMK_Win32_Events.vi
lv2010
(17.78 KiB) Downloaded 65 times
Lvtmk.llb
(1.41 MiB) Downloaded 57 times
User avatar
dadreamer
doctor
doctor
 
Posts: 2867
Joined: 17 Feb 2013, 16:33
Medals: 4
Activity (1) Professionalism (1) Автор (2)
LabVIEW Version: 2.5 — 2017
Karma: 705
I/O VIP vision internet

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

Postby m1ndst0rm on 27 Jul 2016, 11:56

Подскажите, пожалуйста.
Плата тоже Элкус 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 может никогда не выдавать "прерывания" при получении сообщений?
m1ndst0rm
interested
interested
 
Posts: 7
Joined: 10 Oct 2011, 08:18
LabVIEW Version: 9.0
Karma: 0

Next

Return to Для чайников

Who is online

Users browsing this forum: Google, Yandex and 12 guests

cron