manually merged with ARM version
This commit is contained in:
2489
x502api-1.1.34/doc/Doxyfile.in
Normal file
2489
x502api-1.1.34/doc/Doxyfile.in
Normal file
File diff suppressed because it is too large
Load Diff
12
x502api-1.1.34/doc/about.md
Normal file
12
x502api-1.1.34/doc/about.md
Normal file
@ -0,0 +1,12 @@
|
||||
О чем этот документ {#sect_about}
|
||||
==============================================================
|
||||
|
||||
Данный документ предназначен в первую очередь для программистов, которые собираются писать свои программы для работы с модулями @lcard_modules с использованием предоставляемой фирмой "Л Кард" библиотеки.
|
||||
|
||||
В данном документе рассматривается вопрос подключения библиотеки к проекту пользователя, дается подробное описание интерфейсных функций, предоставляемых библиотекой, а также дается описание основных подходов к использованию этих интерфейсных функций.
|
||||
|
||||
Сама библиотека написана на языке @langname{C} и все объявления функций и типов, а также примеры в данном документе приводятся на языке @langname{C}, однако все привязки к другим языкам программирования являются лишь обертками над библиотекой @langname{C} и все функции, типы и параметры сохраняют свое значения и для других языков программирования. Поэтому этот документ необходимо прочитать и пользователям, пишущим на других языках программирования. Кроме того в документе дается описание отличий и общих принципов использования библиотек на поддерживаемых других языках программирования. Примеры для других языков можно установить вместе @lpcie_sdk.
|
||||
|
||||
В настоящем документе не рассматриваются какие-либо вопросы, касающиеся подключения сигналов и характеристик модуля, а также лишь в общем затрагиваются принципы работы самого модуля. Эти вопросы рассматриваются в [\"Руководстве пользователя L-502\"](http://www.lcard.ru/download/l-502_users_guide.pdf) и [\"Руководстве пользователя E-502\"](http://www.lcard.ru/download/e-502_users_guide.pdf), с которыми рекомендуется ознакомится перед прочтением данного документа.
|
||||
|
||||
Также в данном документе не рассматривается задача написания своей прошивки для сигнального процессора модуля и работа с модулем без использования предоставляемой "Л Кард" библиотеки. Эти вопросы рассматриваются в [\"Низкоуровневом описании программиста\"](http://www.lcard.ru/download/x502_low_level.pdf).
|
||||
25
x502api-1.1.34/doc/config.xml.in
Normal file
25
x502api-1.1.34/doc/config.xml.in
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<doxyXmlToLatexConfig>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/constants.tex" sect_lvl="1" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__const__list.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/types.tex" sect_lvl="1" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__type__list.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/struct_x502_cbr_coef.tex" sect_lvl="2" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/structt__x502__cbr__coef.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/struct_x502_cbr.tex" sect_lvl="2" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/structt__x502__cbr.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/struct_x502_info.tex" sect_lvl="2" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/structt__x502__info.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_open.tex" sect_lvl="2" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__open.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_hnd.tex" sect_lvl="2" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__hnd.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_config.tex" sect_lvl="2" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__config.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_async.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__async.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_streams.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__streams.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_dsp.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__dsp.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_flash.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__flash.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_misc.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__misc.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_devrec.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__devrec.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_eth_config.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__eth__config.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_eth_svc_browse.tex" sect_lvl="2" type="xml" > @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__eth__svc__browse.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/funcs_tstp.tex" sect_lvl="1" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__func__tstp.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/tstptypes.tex" sect_lvl="1" type="xml"> @CMAKE_CURRENT_BINARY_DIR@/doc/xml/group__tstptype__list.xml </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/sect_gen_descr.tex" type="tex"> @CMAKE_CURRENT_BINARY_DIR@/doc/latex/sect_gen_descr.tex </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/sect_tstp_descr.tex" type="tex"> @CMAKE_CURRENT_BINARY_DIR@/doc/latex/sect_tstp_descr.tex </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/sect_setup.tex" type="tex"> @CMAKE_CURRENT_BINARY_DIR@/doc/latex/sect_setup.tex </file>
|
||||
<file output="@CMAKE_CURRENT_BINARY_DIR@/doc/pdf/sect_about.tex" type="tex"> @CMAKE_CURRENT_BINARY_DIR@/doc/latex/sect_about.tex </file>
|
||||
</doxyXmlToLatexConfig>
|
||||
646
x502api-1.1.34/doc/gen_descr.md
Normal file
646
x502api-1.1.34/doc/gen_descr.md
Normal file
@ -0,0 +1,646 @@
|
||||
Общий подход к использованию интерфейсных функций {#sect_gen_descr}
|
||||
==============================================================
|
||||
Отличия при работе с модулям @lcard_modules {#sect_modules_diff}
|
||||
==============================================================
|
||||
Отличие возможностей модулей {#sect_modules_diff_features}
|
||||
-------------------------------------------
|
||||
Функциональные возможности модулей @lcard_modules очень схожи, однако есть существенные отличая.
|
||||
1. Основное отличие заключается в использованных интерфейсах --- PCI-Express для L-502 и USB или Ethernet для E-502 и E16. В связи с этим несколько отличается процедура установки связи с устройством. Кроме того, работа по интерфейсу Ethernet требует настройки дополнительных параметров.
|
||||
2. В E-502 используется дополнительно контроллер ARM Cortex-M4 для реализации логики интерфейсов (USB/Ethernet). У данного контроллера есть своя прошивка, которую можно обновлять и в которой могут быть реализованы дополнительные возможности (в первую очередь при работе через Ethernet). Рекомендуется всегда использовать последнюю версию прошивки, которую можно скачать по адресу https://lcard.ru/e502-m4.bin и обновить с помощью программы [X502Studio](https://gitlab.com/l-card/acq/devices/x502/x502studio). Кроме того, теоретически возможно создание пользователем своей прошивки для данного контроллера, так как "Л Кард" предоставляет исходные коды данной прошивки (git-репозиторий с исходниками прошивки можно найти по адресу https://gitlab.com/l-card/acq/devices/x502/e502/firmware/e502_m4), однако какого-либо руководства по данной прошивке "Л Кард" для этого не предоставляет. Также возможно рассмотрение предложений по заказу на доработку прошивки ARM Cortex-M4 под нужные пользователю задачи.
|
||||
3. Существует ограничение скорости передачи данных для E-502. Если L-502 позволяет одновременно осуществить ввод и вывод всех данных с аналоговых каналов и цифровых линий на максимальной скорости, то в модуле E-502 есть ограничения, которые зависят от используемого интерфейса:
|
||||
- при работе по USB суммарная максимальная скорость передачи составляет порядка 5 млн. отсчетов в секунду. Т.е. допустимо использовать например ввод с АЦП и цифровых линий на 2 МГц и при этом вывод только на один канал ЦАП/DOUT на 1 МГц, или на два на 500 КГц. Если идет ввод только с АЦП на 2 МГц, то возможно использовать все три канала вывода на 1 МГц и т.д.
|
||||
При этом это ограничение обусловлено ограничением скорости интерфейса между контроллером ARM Cortex-M4 и ПЛИС, а не самим интерфейсом USB.
|
||||
- при работе по Ethernet (TCP/IP) максимальная скорость уже ограничена скоростью передачи по сети по протоколу TCP. При работе модуля только на ввод скорость ограничена 2.5 млн. отсчетов в секунду. Скорость на вывод и влияние ее на скорость ввода будет уточнена в дальнейшем. Для вывода рекомендуется по возможности использовать циклический режим вывода. Следует также учитывать загрузку самой сети при передаче данных по Ethernet, так как она может сильно влиять на максимальную скорость передачи.
|
||||
4. В связи с ограничением скорости передачи в E-502 поддерживается возможность задать общий делитель для частоты вывода , который можно задать с помощью X502_SetOutFreqDivider() или X502_SetOutFreq(). В L-502 также была введена данная возможность в версии прошивки ПЛИС 0.5, таким образом для ее использования может быть необходимо обновить прошивку.
|
||||
5. При циклическом выводе в L-502 буфер находится в драйвере на ПК, а в E-502 хранение циклического буфера реализовано внутри памяти контроллера ARM Cortex-M4 модуля, что позволяет избежать загрузки интерфейса и ПК во время работы, однако приводит к ограничению размера буфера. Т.е. при работе по сети циклический вывод не влияет на ограничение интерфейса, однако ограничение в суммарную скорость в 5 млн. отсчетов в секунду для модуля сохраняется. Для версии прошивки ARM ниже 1.0.3 буфер вывода в 3 млн. отсчетов (суммарно на все каналы) делился на 2 равные части (одна используется для вывода сигнала, другая для загрузки следующего, чтобы можно было сменить сигнал без останова предыдущего), поэтому один сигнал ограничен в 1.5 млн. отсчетов. Начиная с 1.0.3 буфер может делится произвольно (в зависимости от размера загружаемого сигнала), поэтому размер сигнала ограничен значением --- 3 млн. отсчетов минус размер выдаваемого сейчас сигнала (0 --- если при загрузке не идет генерация предыдущего). Таким образом, если не используется возможность смены сигнала на лету (т.е. всегда после X502_OutCycleSetup() идет X502_OutCycleStop() или X502_StreamsStop() до следующей загрузки сигнала), то можно для одного сигнала использовать все 3 млн. отсчетов. Также следует учитывать, что передача сигнала в ARM контроллер занимает время и при необходимости выдачи сигнала одновременно с запуском сбора необходимо дождаться загрузки сигнала, что можно сделать например с помощью флага #X502_OUT_CYCLE_FLAGS_WAIT_DONE в X502_OutCycleSetup().
|
||||
6. При работе по интерфейсу Ethernet не реализована функция X502_GetSendReadyCount(), а функция X502_GetRecvReadyCount() гарантировано работает только под ОС Windows.
|
||||
7. При чтении значений цифровых входов для E-502 старшие линии DI14, DI15, DI16 объединены с линиями синхронизации DI_SYN2, CONV_IN и START_IN соответственно. При этом, так как в обоих модулях линии 17 и 18 объединены с DI_SYN1 и DI_SYN2, то значение 18-ой и 14-ой линии для E-502 всегда одинаковы.
|
||||
8. Настройки подтяжек для цифровых входов в E-502 отличаются от L-502 (см. описание типа #t_x502_pullups)
|
||||
9. В E-502 используется другая микросхема ЦАП, которая также планируется к использованию в последующих ревизиях модуля L-502.
|
||||
10. E16 по цоколевке сигнальных разъемов и диапазонам измерений входного сигнала это продолжение линейки модулей [E14](https://www.lcard.ru/products/external/e-440). API верхнего уровня сделано совместимым с e502api. Для задания частоты работы ЦАП и АЦП используется опорная частота 48 Мгц. Есть режим совместимости с модулем E14-440 и работы с [E14-440 API](https://www.lcard.ru/products/external/e-440?qt-ltab=6). В качестве интерфейсного процессора используется контроллер WCH32V307. Cигнальные разъемы по цоколевке несовместимы с E502!
|
||||
11. В E16 как и в Е14 реализован старт сбора по уровню аналогового сигнала - выше/ниже уровня, при пересечении границы уровня снизу-вверх/сверху-вниз.
|
||||
12. Идентификатор USB устройства для E16 (VID_2A52&PID_0E16) отличается от E502 и E14, поэтому в некоторых случаях придется установить новые драйвера.
|
||||
13. В E16 для циклического вывода (вывода из внутреннего буфера без внешней подкачки), доступен один буфер размером 11264 слов (в новых прошивках кол-во может измениться).
|
||||
14. В отличие от E502, в E16 нет выделенных выходов синхронизации START_OUT и CONV_OUT, но их роль могут исполнять выходы TRIG или INT, которые можно переключать на вход или на выход, при конфигурации "на вход" эти контакты можно использовать как START_IN или CONV_IN.
|
||||
15. Контакты 17 и 18 цифрового разъёма сделаны унифицированными, по умолчанию на них выведены +3,3В и GND как в Е14-440, при подаче команды включения реле (см. #t_x502_pullups) на эти выводы выводится +15 и -15В как в Е14-140.
|
||||
|
||||
|
||||
Общие и специализированные функции для работы с модулем {#sect_modules_diff_functions}
|
||||
----------------------------------------------------------------
|
||||
В связи с тем, что большая часть функциональности модулей @lcard_modules совпадают, то большинство функций реализовано общими для обоих модулей. Все общие функции реализованы в библиотеке \filename{x502api}. При этом названия функций и констант начинаются с X502_, а типов с t_x502_. Соответственно, для работы с обоими модулями используется один и тот же тип описателя модуля #t_x502_hnd.
|
||||
|
||||
Основное отличие при работе, зависящее от интерфейса связи с модулем, заключается в процедуре установки самой связи. Эти функции реализованы в отдельных библиотеках \filename{l502api} и \filename{e502api} для модуля @lcard_modules соответственно. При установки связи, вся необходимая информация о том, как работать с модулем по нужному интерфейсу, сохраняется внутри непрозрачного описателя модуля, а пользователь после открытия связи может работать с модулем одинаково с использованием одних и тех же общих функций из \filename{x502api} независимо от типа модуля и используемого интерфейса.
|
||||
|
||||
Также в отдельную группу специализированных функций выделены функции по настройке интерфейса Ethernet, которые реализованы только в \filename{e502api} и описаны в разделе @ref func_eth_config.
|
||||
|
||||
Совместимость проектов, разработанных до введения библиотеки x502api {#sect_l502_comapt}
|
||||
----------------------------------------------------------------
|
||||
Для реализации полной совместимости с проектами, работающими только с модулем L-502 и разработанными до введения поддержки работы с модулем E-502 (которая введена с версии 1.1.0) и создания общей библиотеки, в \filename{l502api} реализованы функции из данной библиотеки предыдущих версий (1.0.x). При этом эти объявления этих функций и соответсвующих типов вынесены в отдельный файл "l502api_compat.h", который включается из "l502api.h" для сохранения совместимости. Эти типы определены через общие типы из "x502api.h", а функции реально только вызывают аналогичные общие функции из \filename{x502api}. Соответственно, проекты, разработанные для предыдущей версии без учета общих функций, должны корректно собираться и при новой версии библиотек. Главное отличие, которое следует учитывать, что если эти проекты распространяются с новой версией \filename{l502api}, то необходимо распространять и библиотеку \filename{x502api}, так как ее функции используются функциями новой версии \filename{l502api}.
|
||||
|
||||
Так как данные функции и типы полностью повторяют большинство обобщенных функций (за исключением префиксов в названиях), то они не приводятся в данном документе.
|
||||
|
||||
|
||||
Общий алгоритм для работы с модулем {#sect_gen_alg}
|
||||
==============================================================
|
||||
Данный раздел описывает типичную последовательность вызова функций для работы с модулями @lcard_modules. Более подробно каждый шаг будет описан в последующих разделах.
|
||||
|
||||
Типичная последовательность вызовов имеет следующий вид:
|
||||
1. При работе с модулями по интерфейсам PCI-Express или USB получить список серийных номеров с помощью функций L502_GetSerialList() и E502_UsbGetSerialList(), соответственно, или получить список записей о модулях с помощью L502_GetDevRecordsList() и E502_UsbGetDevRecordsList(). При работе по Ethernet можно использовать функции обнаружения устройств в локальной сети, описанные в главе @ref sect_eth_browsing, или, если известен IP-адрес устройства, перейти сразу к пункту 2.
|
||||
2. Если в системе присутствует нужный модуль, создать описатель модуля с помощью X502_Create().
|
||||
3. Установить соединение с модулем. При использовании записей о устройстве открытие всегда выполняется с помощью X502_OpenByDevRecord(). При использовании серийного номера используются L502_Open() или E502_OpenUsb() для L-502 и E-502, подключенного по USB, соответственно. Чтобы установить связь с модулем по Ethernet с использованием IP-адреса, необходимо использовать функцию E502_OpenByIpAddr().
|
||||
4. При необходимости, получить дополнительную информацию о устройстве с помощью X502_GetDevInfo() (в частности для проверки наличия сигнально процессора BlackFin).
|
||||
5. При наличии сигнального процессора (и желании работать с его использованием) загрузить прошивку сигнального процессора с помощью X502_BfLoadFirmware().
|
||||
6. Установка параметров модуля с помощью [набора функций для изменения настроек модуля](@ref func_config) (названия функций начинаются с X502_Set)
|
||||
7. Передача установленных параметров в модуль с помощью X502_Configure().
|
||||
8. Работа с модулем в синхронном и/или асинхронном режиме (описана в последующих подразделах).
|
||||
9. Закрытие модуля X502_Close().
|
||||
10. Освобождение описателя модуля функцией X502_Free().
|
||||
|
||||
|
||||
Работа с модулем при синхронном вводе {#sect_gen_sync_in}
|
||||
----------------------------------------------------------
|
||||
|
||||
Типичная работа с модулем при синхронном вводе состоит из следующих шагов:
|
||||
1. Разрешение нужных синхронных потоков (АЦП и/или цифровых данных) с помощью X502_StreamsEnable().
|
||||
2. Запуск синхронных потоков X502_StreamsStart().
|
||||
3. Чтение принятых данных из модуля с помощью X502_Recv().
|
||||
4. Обработка прочитанных данных с помощью X502_ProcessData(), X502_ProcessAdcData() или X502_ProcessDataWithUserExt().
|
||||
5. При необходимости приема и обработки следующего блока, переход к пункту 3.
|
||||
6. Останов синхронных потоков с помощью X502_StreamsStop().
|
||||
|
||||
|
||||
Работа с модулем при синхронном потоковом выводе {#sect_gen_sync_out}
|
||||
--------------------------------------------------------------
|
||||
|
||||
Типичная работа с модулем при синхронном выводе состоит из следующих шагов:
|
||||
1. Установка начальных значений для ЦАП с помощью асинхронного вывода X502_AsyncOutDac().
|
||||
2. Разрешение нужных синхронных потоков (каналы ЦАП, цифровые выходы) с помощью X502_StreamsEnable().
|
||||
3. Запуск предварительной загрузки данных на вывод с помощью X502_PreloadStart().
|
||||
4. Подготовка блока данных на запись с помощью X502_PrepareData().
|
||||
5. Запись подготовленного блока в модуль с помощью X502_Send().
|
||||
6. При необходимости повторить пункты 4. и 5. нужное количество раз. При этом общий размер предварительно загруженных данных не должен превысить размер буфера (по умолчанию 9 МСлов)
|
||||
7. Запуск синхронных потоков вызовом X502_StreamsStart().
|
||||
8. Каждый раз при необходимости подгрузить новые данные в буфер выполнить пункты 4. и 5.
|
||||
9. По завершению работы выполнить останов синхронных потоков с помощью X502_StreamsStop().
|
||||
|
||||
Работа с модулем при циклическом выводе {#sect_gen_cycle_out}
|
||||
-----------------------------------------------------------------
|
||||
Для выставления циклического сигнала без подкачки типичная последовательность выглядит так:
|
||||
1. Установка начальных значений для ЦАП с помощью асинхронного вывода X502_AsyncOutDac().
|
||||
2. Разрешение нужных синхронных потоков (каналы ЦАП, цифровые выходы) с помощью X502_StreamsEnable().
|
||||
3. Выделение циклического буфера указанного размера с помощью X502_OutCycleLoadStart().
|
||||
4. Загрузка данных указанного размера для циклического вывода с помощью одного или нескольких вызовов X502_Send().
|
||||
5. Сделать загруженный сигнал активным с помощью X502_OutCycleSetup() с флагом #X502_OUT_CYCLE_FLAGS_WAIT_DONE.
|
||||
6. Запустить синхронный ввод-вывод через X502_StreamsStart().
|
||||
7. При необходимости вывести новый сигнал выполнить шаги 3.-5.
|
||||
8. По завершению работы остановить синхронный ввод-вывод с помощью X502_StreamsStop() или только циклический вывод через X502_OutCycleStop().
|
||||
|
||||
|
||||
Работа с модулем при асинхронном вводе-выводе {#sect_gen_async}
|
||||
-----------------------------------------------------------------
|
||||
|
||||
Типичная работа при асинхронном вводе-выводе состоит из вызова одной из функций:
|
||||
- X502_AsyncInDig() - асинхронный ввод значений цифровых линий
|
||||
- X502_AsyncOutDig() - асинхронный вывод значений на цифровые линии
|
||||
- X502_AsyncOutDac() - асинхронный вывод значения на один из каналов ЦАП
|
||||
- X502_AsyncGetAdcFrame() - асинхронный прием одного кадра АЦП
|
||||
|
||||
|
||||
|
||||
|
||||
Создание и освобождение описателя модуля {#sect_descr}
|
||||
==============================================================
|
||||
|
||||
Вся работа с модулями @lcard_modules осуществляется через описатель модуля типа #t_x502_hnd. Описатель модуля представляет собой непрозрачный указатель на структуру, которая хранит всю информацию о модуле и состоянии соединения с ним. Пользователь не имеет прямого доступа к полям структуры и все действия с модулем выполняются посредством вызова соответствующих функций библиотеки, которые принимают описатель модуля в качестве первого параметра.
|
||||
|
||||
Перед попыткой установить связь с модулем необходимо создать описатель, вызвав функцию X502_Create(), которая выделяет память под структуру, инициализирует ее поля значениями по умолчанию и возвращает указатель на нее --- описатель модуля.
|
||||
|
||||
После того как работа с модулем завершена, выделенная функцией X502_Create() память должна быть освобождена посредством вызова X502_Free(). После освобождения описатель уже не может использоваться.
|
||||
|
||||
Открытие связи с модулем {#sect_open}
|
||||
==============================================================
|
||||
Общее описание процедуры установки связи с модулем {#sect_open_gen}
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Для работы с модулем необходимо установить с ним соединение с использованием ранее созданного описателя.
|
||||
|
||||
Функции для установки соединения с модулем зависят от используемого интерфейса и описаны в последующих подразделах.
|
||||
|
||||
Если функция открытия связи с модулем выполнена успешно, то соединение с модулем установлено и дальше можно использовать любые функции управления модулем. По завершению работы с модулем необходимо закрыть соединение с помощью X502_Close().
|
||||
|
||||
Если же функция открытия связи вернула ошибку, то это может соответствовать одной из следующих ситуаций:
|
||||
- Связь с модулем не удалось установить, т.к. модуль не найден или не отвечает корректно на запросы. В этом случае по завершению вызова функции описатель модуля остается в исходном состоянии, не связанном с каким-либо соединением и его можно использовать только для открытия нового соединения.
|
||||
- Связь с модулем установлена, но обнаружены проблемы в работе модуля. В этом случае соединение с модулем все равно остается открытым, однако большая часть функций работы с модулем не доступна.
|
||||
|
||||
При необходимости различить эти два разных состояния можно с помощью функции X502_IsOpened(), которая проверяет, открыто ли соединение с модулем в данный момент для указанного описателя. В большинстве случаев явно различать эти ситуации не требуется и достаточно вызвать функцию X502_Close(), которая закроет соединение, если оно не закрыто, при любой ошибке открытия соединения. Если функцию закрытия не вызывать по ошибке открытия соединения, то соединение может остаться открытым до освобождения памяти описателя с помощью X502_Free() или до повторного открытия соединения с помощью данного описателя.
|
||||
|
||||
Соединение может оставаться открытым при следующих ошибках:
|
||||
- #X502_ERR_FPGA_NOT_LOADED --- прошивка ПЛИС не была успешно загружена и ПЛИС находится в нерабочем состоянии. Ошибка актуальна только для модуля E-502, т.к. в модуле L-502 в ПЛИС реализован сам интерфейс PCI-Express и без загрузки прошивки ПЛИС модуль не будет даже определен в системе. В модуле E-502 прошивка ПЛИС загружается микроконтроллером из Flash-памяти при старте модуля. Ошибка может возникать, если повреждена информация во Flash-памяти или по каким-то причинам возникла ошибка при ее чтении из Flash-памяти или при ее загрузке в ПЛИС. В данном режиме доступны только функции работы с Flash-памятью, функции управления сетевыми настройками модуля и функция перезагрузки прошивки ПЛИС (E502_ReloadFPGA()).
|
||||
- #X502_ERR_REF_FREQ_NOT_LOCKED --- ошибка захвата опорной частоты синхронизации, идущей от гальваноотвязанной части управления вводом-выводом. Хотя доступ к Flash-памяти и регистрам ПЛИС может работать нормально, любые функции ввода-вывода аналоговых или цифровых данных не могут быть осуществлены при данной ошибке.
|
||||
|
||||
|
||||
|
||||
Установка связи с модулем L-502 по интерфейсу PCI-Express {#sect_open_pci}
|
||||
----------------------------------------------------------------------
|
||||
|
||||
Для начала работы с модулем необходимо установить с ним связь с помощью функции L502_Open(). Для различия модулей используется их серийные номера.
|
||||
|
||||
Получить список серийных номеров всех найденных модулей L-502 можно с помощью функции L502_GetSerialList(). Данная функция принимает плоский массив, в который будут сохранены найденные серийные номера, и максимальное количество серийных номеров, которое можно сохранить в переданный массив.
|
||||
|
||||
В простейшем случае можно задать максимальное значение модулей и для серийных номеров использовать статически выделенный массив:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||||
#define MAX_MODULES_CNT 16
|
||||
|
||||
char serial_list[MAX_MODULES_CNT][X502_SERIAL_SIZE];
|
||||
int32_t get_list_res = L502_GetSerialList(serial_list, MAX_MODULES_CNT, 0, NULL);
|
||||
if (get_list_res<0) {
|
||||
/* Ошибка получения списка серийных номеров */
|
||||
} else if (get_list_res==0) {
|
||||
/* Не найдено ни одного модуля */
|
||||
} else {
|
||||
/* Найдено get_list_res модулей */
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
В общем случае для работы с произвольным максимальным количеством модулей можно воспользоваться третьим параметром функции для получения количества найденных модулей в системе. При этом в качестве массива серийных номеров можно передать нулевой указатель и указать нулевой размер массива. После этого можно динамически выделить массив под полученное количество серийных номеров и повторно вызвать L502_GetSerialList() для получения серийных номеров всех модулей L-502:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||||
uint32_t dev_cnt;
|
||||
int32_t res;
|
||||
|
||||
/* Получаем количество модулей в системе */
|
||||
res = L502_GetSerialList(NULL, 0, 0, &dev_cnt);
|
||||
if (res<0) {
|
||||
/* Ошибка получения списка серийных номеров */
|
||||
} else if (dev_cnt==0) {
|
||||
/* Не найдено ни одного модуля */
|
||||
} else {
|
||||
/* Выделяем плоский массив под dev_cnt серийных номеров размером
|
||||
dev_cnt*L502_SERIAL_SIZE */
|
||||
t_x502_serial_list serial_list=
|
||||
(t_x502_serial_list)
|
||||
malloc(dev_cnt*X502_SERIAL_SIZE);
|
||||
if (serial_list == NULL) {
|
||||
/* Ошибка выделения памяти */
|
||||
} else {
|
||||
res = L502_GetSerialList(serial_list, dev_cnt, 0,
|
||||
NULL);
|
||||
if (res>0) {
|
||||
/* Получено res серийных номеров */
|
||||
}
|
||||
/* Освобождаем выделенный массив под серийные номера */
|
||||
free(serial_list);
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Следует отметить, что с одним модулем одновременно может быть установлено только одно соединение. При попытке открыть модуль, с которым уже установлено соединение через другой описатель (возможно, в другой программе) L502_Open() вернет #X502_ERR_DEVICE_ACCESS_DENIED. При этом L502_GetSerialList() по умолчанию возвращает список всех серийных номеров модуля, включая те, с которыми уже установлено соединение. Если нужно получить список только тех устройств, с которыми еще не установлено соединения, то в L502_GetSerialList() можно передать флаг #X502_GETDEVS_FLAGS_ONLY_NOT_OPENED.
|
||||
|
||||
Если в качестве серийного номера в L502_Open() передать нулевой указатель или пустую строку, то будет предпринята попытка открыть первый модуль, с которым удастся успешно установить соединение. Если ни с одним модулем установить соединение не удалось, то будет возвращена ошибка, полученная при попытки открыть последний модуль. То есть, при наличии двух модулей L-502 в системе, первый вызов L502_Open() установит соединение с первым модулем L-502, второй вызов - со вторым, а третий вернет уже ошибку доступа #X502_ERR_DEVICE_ACCESS_DENIED.
|
||||
|
||||
Установка связи с модулем E-502 по интерфейсу USB {#sect_open_usb}
|
||||
----------------------------------------------------------------------
|
||||
При работе по USB алгоритм установления связи абсолютно аналогичен открытию модуля L-502, с той разницей, что для получения списка серийных номеров используется функция E502_UsbGetSerialList(), а для открытия модуля E-502 по серийному номеру используется E502_OpenUsb().
|
||||
|
||||
Установка связи с модулем E-502 по интерфейсу Ethernet {#sect_open_eth}
|
||||
------------------------------------------------------------------------
|
||||
Установить связь с модулем по Ethernet можно как по явно заданному IP-адресу устройства, так и воспользоваться функциями обнаружения устройств в локальной сети, подробно описанными в главе @ref sect_eth_browsing.
|
||||
|
||||
При установке связи по IP-адресу достаточно вызвать функцию E502_OpenByIpAddr().
|
||||
|
||||
Следует отметить, что в отличие от других интерфейсов, для корректной работы по Ethernet должны быть настроены необходимые параметры, о чем описано в главе @ref sect_eth_config.
|
||||
|
||||
|
||||
Установка связи с модулями с использованием записей о устройстве {#sect_open_devrec}
|
||||
-------------------------------------------------------------
|
||||
Одним из минусов функций открытия по серийному номеру является то, что в момент открытия необходимо знать, устройству, подключенному по какому интерфейсу, соответствует данный номер, чтобы выбрать соответствующую функцию для открытия устройства. Для избежания этого введен специальный тип #t_x502_devrec, соответствующий записи о найденном устройстве. Данный тип содержит информацию о найденном устройстве (название, серийный номер, интерфейс, флаги с поддерживающимися возможностями и т.п.), а также содержит всю необходимую информацию о том, как установить связь и работать с соответствующим устройством. Соответственно, от устройства и интерфейса зависят только функции получения записей о устройстве, а установка связи осуществляется общей функцией X502_OpenByDevRecord().
|
||||
|
||||
Это позволяет получить все необходимые записи на отдельном этапе и сохранить их в общий массив, а в дальнейшем уже выполнить открытие связи по нужным записям, не разбирая отдельно, что это за устройство и по какому интерфейсу подключено.
|
||||
|
||||
Особенностью является необходимость пользователю очищать память, выделенную на этапе инициализации записи об устройстве. Очистка памяти выполняется с помощью X502_FreeDevRecordList(). Запись об устройстве используется исключительно внутри X502_OpenByDevRecord() и при желании может быть освобождена сразу после вызова данной функции, если список записей больше не нужен. Также следует учесть, что перед тем, как проинициализированную ранее запись передавать в функцию для получения или инициализации новой записи (например для обновления списка), необходимо ее сперва очистить для избежания утечек памяти.
|
||||
|
||||
Доступны следующие функции для инициализации записей:
|
||||
- L502_GetDevRecordsList() инициализирует записи, соответствующие подключенным модулям L-502 по интерфейсу PCI-Express. По параметрам и использованию аналогична L502_GetSerialList() с учетом необходимости освобождать записи.
|
||||
- E502_UsbGetDevRecordsList() инициализирует записи, соответствующие подключенным модулям E-502 по интерфейсу USB. По параметрам и использованию аналогична E502_UsbGetSerialList() с учетом необходимости освобождать записи.
|
||||
- E502_MakeDevRecordByIpAddr() инициализирует запись для установления соединения с модулем E-502 с заданным адресом по интерфейсу Ethernet.
|
||||
- E502_MakeDevRecordByEthSvc() инициализирует запись для установления соединения с модулем E-502, соответствующем автоматически обнаруженному сервису, по интерфейсу Ethernet
|
||||
|
||||
|
||||
Ниже приведен пример, который создает записи для всех найденных модулей, подключенных по интерфейсам USB и PCI-Express. Кроме того, предполагается, что в массиве <B> ip_addr_list </B> содержится <B> ip_cnt </B> адресов, для которых также создаются записи, а определение <B> TCP_CONNECTION_TOUT </B> задает таймаут в мс на подключение по сетевому интерфейсу. Затем предоставляется выбор нужного устройства, после чего с ним устанавливается связь и все записи после этого очищаются.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||||
uint32_t ip_addr_list[] = { .... } ; /* список ip-адресов устройств */
|
||||
uint32_t ip_cnt = ... ; /* размер этого списка */
|
||||
|
||||
uint32_t pci_devcnt = 0;
|
||||
uint32_t usb_devcnt = 0;
|
||||
int32_t fnd_devcnt = 0; /* общее кол-во найденных записей */
|
||||
t_x502_devrec *devrec_list = NULL; /* список записей о устройствах */
|
||||
t_x502_hnd hnd = NULL; /* описатель открытого устройства */
|
||||
|
||||
/* получаем количество подключенных устройств по интерфейсам PCI и USB */
|
||||
L502_GetDevRecordsList(NULL, 0, 0, &pci_devcnt);
|
||||
E502_UsbGetDevRecordsList(NULL, 0, 0, &usb_devcnt);
|
||||
|
||||
if ((pci_devcnt+usb_devcnt + ip_cnt) != 0) {
|
||||
/* выделяем память для массива для сохранения найденного
|
||||
количества записей */
|
||||
devrec_list = malloc((pci_devcnt + usb_devcnt + ip_cnt) *
|
||||
sizeof(t_x502_devrec));
|
||||
|
||||
if (devrec_list != NULL) {
|
||||
unsigned i;
|
||||
/* получаем записи о модулях L-502, но не больше pci_devcnt */
|
||||
if (pci_devcnt!=0) {
|
||||
int32_t res = L502_GetDevRecordsList(&devrec_list[fnd_devcnt],
|
||||
pci_devcnt, 0, NULL);
|
||||
if (res >= 0) {
|
||||
fnd_devcnt += res;
|
||||
}
|
||||
}
|
||||
/* добавляем записи о модулях E-502, подключенных по USB, в конец массива */
|
||||
if (usb_devcnt!=0) {
|
||||
int32_t res = E502_UsbGetDevRecordsList(&devrec_list[fnd_devcnt],
|
||||
usb_devcnt, 0, NULL);
|
||||
if (res >= 0) {
|
||||
fnd_devcnt += res;
|
||||
}
|
||||
}
|
||||
|
||||
/* создаем записи для переданного массива ip-адресов */
|
||||
for (i=0; i < ip_cnt; i++) {
|
||||
if (E502_MakeDevRecordByIpAddr(&devrec_list[fnd_devcnt],
|
||||
ip_addr_list[i], 0,
|
||||
TCP_CONNECTION_TOUT) == X502_ERR_OK) {
|
||||
fnd_devcnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fnd_devcnt != 0) {
|
||||
uint32_t dev_ind;
|
||||
|
||||
/* обработка списка и выбор нужного устройства, индекс которого
|
||||
для примера сохраняется в dev_ind */
|
||||
.....
|
||||
|
||||
|
||||
if ( <устройство выбрано> )
|
||||
hnd = X502_Create();
|
||||
if (hnd==NULL) {
|
||||
/* Ошибка создания описателя модуля! */
|
||||
} else {
|
||||
/* устанавливаем связь с модулем по записи */
|
||||
int32_t err = X502_OpenByDevRecord(hnd, &devrec_list[dev_ind]);
|
||||
if (err != X502_ERR_OK) {
|
||||
/* ошибка установления соединения */
|
||||
X502_Free(hnd);
|
||||
hnd = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* освобождение ресурсов действительных записей из списка */
|
||||
X502_FreeDevRecordList(devrec_list, fnd_devcnt);
|
||||
}
|
||||
/* очистка памяти самого массива */
|
||||
free(devrec_list);
|
||||
|
||||
|
||||
if (hnd != NULL) {
|
||||
/* работа с модулем */
|
||||
|
||||
X502_Close(hnd);
|
||||
X502_Free(hnd);
|
||||
}
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
В данном примере все ресурсы записей освобождаются сразу после выбора нужного устройства и установления с ним связи. При желании можно использовать другой подход, например, сохраняя записи вместе с созданными описателями устройства, чтобы в любой нужный момент можно было открыть, закрыть и снова открыть устройство, освобождая каждую запись только в момент завершения работы или получения нового списка устройств. При этом следует учитывать, что копировать запись о устройстве можно, но X502_FreeDevRecordList должна вызываться только один раз на одну копию каждой записи.
|
||||
|
||||
Следует отметить, что все функции получения серийных номеров и установления связи с модулями из предыдущих разделов реально реализованы через описанные в данном разделе функции и являются лишь обертками, созданными для упрощения процедуры поиска и установления связи с устройствами.
|
||||
|
||||
|
||||
|
||||
Режимы работы с сигнальным процессором и без него {#sect_modes}
|
||||
==============================================================
|
||||
|
||||
Модули L-502 и E-502 могут работать в двух режимах:
|
||||
- В штатном режиме (#X502_MODE_FPGA) вся обработка данных выполняется аппаратно в ПЛИС модуля, а управление модулем осуществляется путем прямой записи значений в регистры ПЛИС. В этом режиме доступны все штатные функции сбора данных, однако у пользователя нет возможности расширить функциональные возможности самого модуля. Этот режим доступен для всех модификаций L-502 и E-502.
|
||||
- В режим работы с сигнальным процессором (#X502_MODE_DSP) (отсутствует в E16) всё управление сбором данных выполняется сигнальным процессором BlackFin и все потоки данных на ввод и вывод идут через него. Таким образом, пользователь может путем создания модифицированной прошивки BlackFin реализовать дополнительные возможности (например, обратную связь в режиме реального времени). Этот режим доступен только для модификаций L-502-P-G, L-502-P-G-D и E-502-P-EU-D. Узнать о наличие сигнального процессора программно можно также по флагу #X502_DEVFLAGS_BF_PRESENT в [флагах в записи о устройстве](@ref t_x502_devrec::flags) или [в флагах информации о модуле](@ref t_x502_info::devflags), которая может быть получена после установления связи с модулем через функцию L502_GetDevInfo().
|
||||
|
||||
При включении питания модуль всегда находится в штатном режиме работы без использования сигнального процессора. Для работы сигнального процессора необходимо предварительно загрузить в него программу (прошивку). Это можно сделать из файла формата ldr с помощью функции X502_BfLoadFirmware(). После этого модуль будет автоматически переведен в режим с сигнальным процессором.
|
||||
|
||||
При необходимости, можно специально переключить режим работы с помощью X502_SetMode(). Это может потребоваться, например, если прошивка загружена в BlackFin по интерфейсу JTAG. Кроме того, следует иметь ввиду, что при открытии связи с устройством не производится изменение режима работы модуля. Т.е. если одна программа установила режим #X502_MODE_DSP, то при последующем открытии модуля из другой программы этот режим сохранится. В этой связи может понадобиться явно перевести модуль в штатный режим с помощью X502_SetMode(). Поэтому если программа не предполагает, что модуль мог работать в режиме #X502_MODE_DSP и выполнять какие-то функции, которые не нужно прерывать, а работает с модулем с "чистого листа", рекомендуется сразу после установки связи установить явно нужный режим работы.
|
||||
|
||||
Все настройки модуля и работа с синхронным вводом-выводом должны выполняться после установки нужного режима.
|
||||
|
||||
В любой момент можно узнать текущий режим работы с помощью X502_GetMode().
|
||||
|
||||
|
||||
Установка настроек модуля {#sect_config}
|
||||
==============================================================
|
||||
|
||||
Перед использованием модуля, как правило, необходимо выполнить настройку его параметров. Сперва все настройки записываются в поля структуры описателя модуля с помощью функций, начинающихся с X502_Set, которые будут описаны в последующих подразделах, после чего установленные параметры передаются в модуль с помощью X502_Configure().
|
||||
|
||||
Настройка последовательности опроса каналов АЦП {#sect_config_adc_table}
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Модули @lcard_modules представляют собой АЦП с последовательной коммутацией каналов. То есть измерение нескольких каналов происходит последовательно, путем переключения входного коммутатора АЦП. Как и в большинстве моделей "Л Кард" последовательность опроса каналов задается с помощью управляющей таблицы логических каналов АЦП. Всего таблица может содержать от одного до #X502_LTABLE_MAX_CH_CNT логических каналов.
|
||||
|
||||
Каждый логический канал задает следующие параметры:
|
||||
- номер физического канала, с которого производится измерение. Номер физического канала задается, считая от 0, то есть 0 означает первый канал, 1 – второй и т.д. Таким образом, в дифференциальном режиме номер канала может быть от 0 до 15, а в режиме измерения с общей землей --- от 0 до 31.
|
||||
- режим измерения АЦП из #t_x502_lch_mode.
|
||||
- используемый диапазон измерения (из #t_x502_adc_range или #t_e16_adc_range).
|
||||
- коэффициент усреднения по заданному логическому каналу (см. раздел @ref sect_config_lch_avg, не реализовано в Е16).
|
||||
|
||||
Задать параметры логического канала с нужным номером можно с помощью функции X502_SetLChannel(), а количество логических каналов в управляющей таблице --- с помощью X502_SetLChannelCount().
|
||||
|
||||
Например, необходимо измерить сперва напряжение входа X1 относительно общей земли для диапазона +/-10В, затем измерить значение на 16 канале в дифференциальном режиме (между входами X16 и Y16) с диапазоном +/-1В, а затем измерить напряжение между Y1 и общей землей (17 канал в режиме с общей землей) с диапазоном +/-0.2В (Назначение выводов сигнального разъема и подключение сигналов к модулю описано в [\"Руководстве пользователя\"](http://www.lcard.ru/download/l-502_users_guide.pdf)). В этом случае настройка логической таблицы будет выглядеть следующим образом:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||||
/* устанавливаем 3 логических канала */
|
||||
int32_t err = X502_SetLChannelCount(hnd, 3);
|
||||
if (err == X502_ERR_OK) {
|
||||
/* первый логический канал соответствует измерению 1 канала
|
||||
относительно общей земли */
|
||||
err = X502_SetLChannel(hnd,0,0,X502_LCH_MODE_COMM,X502_ADC_RANGE_10,0);
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
/* второй логический канал соответствует измерению 16 канала
|
||||
в диф. режиме */
|
||||
err = X502_SetLChannel(hnd,1,15,X502_LCH_MODE_DIFF,X502_ADC_RANGE_1, 0);
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
/* третий логический канал - измерение 17-го канала
|
||||
относительно общей земли */
|
||||
err = X502_SetLChannel(hnd,2,16,X502_LCH_MODE_COMM, X502_ADC_RANGE_02, 0);
|
||||
}
|
||||
|
||||
if (err == X502_ERR_OK) {
|
||||
/* установка других настроек */
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
/* передаем настройки в модуль */
|
||||
err = X502_Configure(hnd,0);
|
||||
}
|
||||
|
||||
if (err != X502_ERR_OK) {
|
||||
/* произошла ошибка при настройке параметров... */
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
После завершения измерения с настройками, соответствующими последнему логическому каналу, следует измерение, соответствующее снова первому (с нулевым номером) логическому каналу. Последовательность измерений соответствующая одному проходу логической таблицы называется кадром.
|
||||
|
||||
При желании, между завершением измерения, соответствующего последнему логическому каналу кадра, и началом измерения, соответствующего первому логическому каналу следующего кадра, может быть вставлена межкадровая задержка.
|
||||
|
||||
|
||||
Настройка частоты синхронного ввода/вывода {#sect_config_freq}
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Все частоты потокового сбора и выдачи данных основываются на опорной частоте синхронизации. В качестве опорной частоты может использоваться внутренний источник частоты или внешний. В первом случае, опорная частота может быть 2МГц либо 1.5МГц. По умолчанию используется 2МГц. Изменить ее можно с помощью функции X502_SetRefFreq().
|
||||
|
||||
При внешней опорной частоты может использоваться сигнал с произвольной частотой до 1.5 МГц. При этом для того, чтобы функции библиотеки могли оптимально подобрать настройки передачи данных (если они не задаются вручную), а также для того, чтобы корректно работали функции подбирающие делители (см. ниже) для получения нужных частот ввода/вывода необходимо задать значение внешней опорной частоты, которая будет подана. Это значение можно задать с помощью функции X502_SetExtRefFreqValue().
|
||||
|
||||
Частота сбора АЦП получается с помощью деления значения опорной частоты на установленный коэффициент, который может быть в диапазоне от 1 до #X502_ADC_FREQ_DIV_MAX. Кроме того, как уже упоминалось [в предыдущем разделе](@ref sect_config_adc_table), между измерением последнего логического канала одного кадра и началом следующего кадра, может быть добавлена межкадровая задержка. Межкадровая задержка задается в виде количества периодов опорной частоты синхронизации.
|
||||
|
||||
Делитель частоты сбора АЦП и количество периодов опорной частоты для межкадровой задержки можно задать явно с помощью функций X502_SetAdcFreqDivider() и X502_SetAdcInterframeDelay() соответственно. Вместо этих функций для удобства можно использовать функцию X502_SetAdcFreq(), которой можно передать значения частоты сбора АЦП и частоты кадров в Герцах, а функция сама рассчитает нужный делитель и значение межкадровой задержки, чтобы полученные частоты были наиболее близки к указанным. При этом функция вернет реально установившиеся значения частот.
|
||||
|
||||
Под частотой сбора АЦП (f_acq) понимается величина, обратная времени одного преобразования, соответствующего одному логическому каналу. Под частотой кадров (f_frame) понимается величина, обратная времени от начала измерения первого логического канала одного кадра до начала измерения первого логического канала следующего кадра. Это частота соответствует частоте сбора для одного логического канала.
|
||||
|
||||
Ниже приведена диаграмма, иллюстрирующая на примере сбора при заданных трех логических каналах, как определяются упомянутые выше частоты.
|
||||
|
||||
\image latex doc/images/adc_frame.jpeg "Диаграмма сбора АЦП для трех логических каналов" width=0.6\textwidth
|
||||
\image html adc_frame.jpeg "Диаграмма сбора АЦП для трех логических каналов"
|
||||
|
||||
Если межкадровая задержка не нужна, то можно передать нулевой указатель в качестве второго параметра X502_SetAdcFreq(), тогда будет использоваться всегда нулевая межкадровая задержка (т.е. измерение следующего кадра начнется сразу после завершения предыдущего).
|
||||
|
||||
Помимо синхронного ввода с АЦП модули @lcard_modules позволяют осуществлять синхронный ввод с цифровых входов (количество зависит от типа модуля, что описано в разделе @ref sect_modules_diff_features). Также как и для синхронного сбора данных АЦП, частота синхронного цифрового ввода определяется как опорная частота, деленная на коэффициент, который можно установить с помощью X502_SetDinFreqDivider(). Так же можно вызывать функцию X502_SetDinFreq(), чтобы она рассчитала этот коэффициент для получения наиболее близкой частоты к указанной. Для синхронного ввода цифровых линий нет ни логической таблицы (так как каждый раз считывается значение всех цифровых входов и передается в виде одного слова), ни межкадровой задержки --- при запуске синхронного ввода все измерения выполняются через одинаковые промежутки времени. При этом частота для ввода с цифровых линий может отличаться от частоты сбора АЦП.
|
||||
|
||||
Также модули @lcard_modules позволяют осуществить синхронный вывод параллельно на два канала ЦАП (опция) и цифровые выводы. При этом максимальная частота вывода каждого канала в два раза меньшей значения опорной частоты. Для модуля E-502, а также L-502 с прошивкой ПЛИС версии 0.5 или выше, можно установить делитель частоты вывода (относительно опорной частоты в диапазоне от #X502_OUT_FREQ_DIV_MIN до #X502_OUT_FREQ_DIV_MAX) либо явно с помощью функции X502_SetOutFreqDivider(), либо вызвать функцию X502_SetOutFreq(), чтобы она подобрала такой делитель так, чтобы частота была наиболее близка к заданной. При этом частота задается общая для всех потоков вывода.
|
||||
|
||||
|
||||
Коэффициент усреднения для логического канала (не реализовано в Е16) {#sect_config_lch_avg}
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
Реально микросхема АЦП всегда работает на частоте равной опорной частоте синхронизации. В случае, если частота сбора АЦП установлена меньше, чем опорная частота синхронизации, то на одно измерение значения логического канала приходится n измерений АЦП (n = f_acq/f_ref --- отношение установленной частоты сбора АЦП к опорной частоте дискретизации).
|
||||
|
||||
При отключенном усреднении, первые n-1 измерений отбрасывается, что увеличивает время установления сигнала. При необходимости можно использовать несколько последних отсчетов (navg) для получения результирующего значения. Тогда результирующего значение будет являться средним между navg последними измерениями, однако это сокращает соответственно время на установления сигнала. Естественно navg всегда меньше либо равно n. Кроме того navg не может превышать максимального значения, равного #X502_LCH_AVG_SIZE_MAX.
|
||||
|
||||
Значение navg задается последним параметром функции X502_SetLChannel(). Значение равное 1 означает отсутствие усреднения. Значения равное 0 означает, что коэффициент усреднения может быть выбран по усмотрению библиотеки. В текущей реализации значение 0 аналогично значению 1, но это может быть изменено в последующих версиях.
|
||||
|
||||
|
||||
Настройка режимов синхронизации {#sect_config_sync_mode}
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
По умолчанию в качестве опорной частоты синхронизации используется внутренняя частота модуля, а запуск всех синхронных измерений осуществляется при выполнении функции X502_StreamsStart().
|
||||
|
||||
Однако, при необходимости, возможно задать как внешний источник опорной частоты, так и внешний сигнал запуска синхронного сбора/выдачи данных.
|
||||
|
||||
Для этого могут быть использованы входы цифрового разъема DI_SYN1 и DI_SYN2 (может использоваться как фронт, так и спад одного из этих сигналов), либо также может использоваться разъем синхронизации для организации синхронного сбора данных по принципу ведущий-ведомые.
|
||||
В модуле E16 для этих же целей используются контакты INT (19 контакт цифрового разъема) и TRIG (20 контакт аналогового разъема), при этом в E16 нет выделенных портов (START/CONV)_(IN/OUT), а TRIG и INT могут быть настроены как на вход, так и на выход и играть роль входов или выходов сигналов START и CONV.
|
||||
|
||||
Выбор внешнего сигнала для задания опорной частоты синхронизации задается с помощью X502_SetSyncMode(), а условие запуска с помощью функции X502_SetSyncStartMode(). Следует отметить, что если задано внешнее событие запуска, то для того, чтобы модуль перешел в режим ожидания этого события, необходимо вызвать X502_StreamsStart().
|
||||
|
||||
Останов синхронного сбора/выдачи данных всегда осуществляется программно с помощью X502_StreamsStop().
|
||||
|
||||
При использовании разъема синхронизации для организации сбора данных по принципу ведущий-ведомые, для ведущего модуля источником опорной частоты синхронизации остается внутренняя частота (режим #X502_SYNC_INTERNAL), а каждый ведомый модуль использует опорную частоту и/или признак запуска сбора от внешнего мастера, т.е. для каждого ведомого модуля должен быть установлен режим #X502_SYNC_EXTERNAL_MASTER.
|
||||
|
||||
|
||||
|
||||
Синхронный и асинхронный режимы работы {#sect_sync_async}
|
||||
===========================================================================
|
||||
|
||||
Для модулей @lcard_modules доступны следующие данные на ввод:
|
||||
- отсчеты с АЦП
|
||||
- значения цифровых входов
|
||||
|
||||
Также модуль может быть использована для вывода:
|
||||
- отсчетов на первый канал ЦАП
|
||||
- отсчетов на второй канал ЦАП
|
||||
- значений на цифровые выходы
|
||||
|
||||
Таким образом, имеется 2 канала на ввод и 3 канала на вывод.
|
||||
|
||||
Каждый из этих каналов может работать как в синхронном режиме, так и асинхронно. При этом каждый канал может быть настроен индивидуально, то есть можно выполнять, например, асинхронный ввод цифровых линий на фоне синхронного потокового сбора с АЦП или выводить на один канал ЦАП сигнал в синхронном потоковом режиме, в то время как в другой выставлять значения асинхронно. Единственное исключение --- невозможно осуществить асинхронный ввод с АЦП на фоне синхронного сбора данных с цифровых входов.
|
||||
|
||||
Также существует ограничение использования асинхронного режима вместе с синхронным в случае запуска синхронного ввода-вывода по внешнему условию. В момент времени, когда модуль ожидает внешний сигнал запуска синхронного ввода-вывода (т.е. после того, как была вызвана функция X502_StreamsStart(), но до того, как возникло внешнее условие старта), асинхронный ввод или вывод невозможен.
|
||||
|
||||
Асинхронный режим работы {#sect_async_mode}
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
При включении питания все каналы находятся в асинхронном режиме.
|
||||
В асинхронном режимы при вызове функции асинхронного ввода/вывода производится однократный ввод или вывод указанной информации. При этом задержка от вызова функции до непосредственно момента измерения данных для ввода или выставления указанного значения на выходе для вывода точно не определена. Также точно не может быть определена задержка между двумя последовательными операциями ввода/вывода.
|
||||
|
||||
Плюсом асинхронного режима является простота его использования --- достаточно одного вызова требуемой функции:
|
||||
- X502_AsyncInDig() - асинхронный ввод значений цифровых линий
|
||||
- X502_AsyncOutDig() - асинхронный вывод значений на цифровые линии
|
||||
- X502_AsyncOutDac() - асинхронный вывод значения на один из каналов ЦАП
|
||||
|
||||
Для однократного ввода данных с АЦП используется функция X502_AsyncGetAdcFrame(), которая выполняет ввод одного кадра данных АЦП. В отличии от других функций асинхронного ввода-вывода, перед вызовом данной функции необходимо выполнить настройку модуля: необходимо задать управляющую таблицу АЦП (см. @ref sect_config_adc_table). Измерение логических каналов внутри кадра происходит синхронно с заданной частотой сбора АЦП. Асинхронным является ввод самих кадров, то есть задержка между измерением кадров при последовательном вызове X502_AsyncGetAdcFrame() не определена.
|
||||
|
||||
Например, код для выполнения однократного измерения с 7-го физического канала в дифференциальным режиме с диапазоном +/-0.5В может выглядеть следующим образом:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
||||
/* устанавливаем 1 логический канал в управляющей таблице */
|
||||
int32_t err = X502_SetLChannelCount(hnd, 1);
|
||||
if (err == X502_ERR_OK) {
|
||||
/* логический канал соответствует измерению 7 канала
|
||||
в диф. режиме */
|
||||
err = X502_SetLChannel(hnd,0,6,X502_LCH_MODE_DIFF,L502_ADC_RANGE_05,0);
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
/* передаем настройки в модуль */
|
||||
err = X502_Configure(hnd,0);
|
||||
}
|
||||
if (err == X502_ERR_OK) {
|
||||
/* Считываем кадр данных АЦП из одного отсчета */
|
||||
double val;
|
||||
err = X502_AsyncGetAdcFrame(hnd,
|
||||
X502_PROC_FLAGS_VOLT, 1000, &val);
|
||||
if (err == X502_ERR_OK) {
|
||||
/* верно считали значение val */
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Синхронный режим работы {#sect_sync_mode}
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
|
||||
В синхронном режиме ввод или вывод данных осуществляется с заданной частотой, то есть время между соседними измерениями или выводом соседний отсчетов определено. Частоты сбора для каждого канала задаются относительно общей опорной частоты синхронизации (подробнее см. главу [\"Настройка частоты синхронного ввода/вывода\"](@ref sect_config_freq)) и запуск синхронного ввода-вывода для всех каналов осуществляется одновременно.
|
||||
|
||||
Для запуска синхронного режима, необходимо сперва с помощью функции X502_StreamsEnable() разрешить синхронный режим по требуемым каналам, а затем запустить синхронный ввод/вывод по всем разрешенным каналам с помощью X502_StreamsStart().
|
||||
|
||||
При синхронном вводе модуль производит измерения с заданной частотой и сам передает данные по интерфейсу в буфер (для L-502 этот буфер находится в драйвере и передается модулем с использованием BusMaster DMA, а для E-502 --- буфер выделяется бибилотекой). Принятые в буфер данные могут быть прочитаны программой с помощью X502_Recv().
|
||||
|
||||
Аналогично, для синхронного вывода, модуль сам по мере необходимости считывает данные из буфера и выводит считанные отсчеты с заданной частотой. Данные в буфер драйвера должны быть предварительно записаны с помощью X502_Send(). При этом, если к моменту вывода очередного отсчета данные в буфер драйвера не поступили, то будет выведено предыдущее значение.
|
||||
|
||||
В драйвере или библиотеке выделяется всего два буфера --- один на прием и один на передачу. То есть значения для синхронного ввода с цифровых линий и отсчеты АЦП передаются одним потоком, также одним потоком передаются все данные на вывод. Каждый отсчет передается в виде 32-битного слова, содержащего дополнительную информацию, включающую в себя признак, к какому типу данных относится данный отсчет.
|
||||
|
||||
Разбор принятых данных на отсчеты АЦП и значения цифровых выводов осуществляется с помощью X502_ProcessData(). Помимо этого, данная функция также может осуществить перевод отсчетов АЦП в Вольты.
|
||||
Следует учесть, что в отличие от некоторых других изделий "Л Кард", применение калибровочных коэффициентов осуществляется аппаратно и значения уже приходят в виде 24-битных отсчетов с уже примененными коэффициентами.
|
||||
|
||||
В 32-битном слове, соответствующем отсчету АЦП, передается дополнительно режим измерения и номер физического канала. X502_ProcessData() сравнивает эти значения с теми, которые были заданы при настройке управляющей таблицы, чтобы убедиться в корректности принимаемых данных. При этом X502_ProcessData() ожидает, что с ее помощью будут обрабатываться все принятые данные.
|
||||
|
||||
Данные от АЦП приходят в том порядке, в котором производятся измерения, т.е. сперва измерения соответствующие всем логическим каналам первого кадра, затем второго и т.д. В этом же порядке X502_ProcessData() возвращает и преобразованные отсчеты АЦП. При этом в X502_ProcessData() можно передавать и нецелое количество кадров (например, если запущен синхронный ввод с цифровых линий, то заранее сложно определить, сколько в принятом блоке данных содержится отсчетов с цифровых линий, а сколько отсчетов с АЦП), в этом случае X502_ProcessData() обработает и выдает все отсчеты, включая отсчеты нецелого кадра, а при следующем ее вызове проверяет, что отсчеты АЦП начинаются с логического канала, следующего за последним обработанным до этого каналом. Какой логический канал ожидается следующим для обработки можно узнать с помощью функции X502_GetNextExpectedLchNum().
|
||||
|
||||
Например, пусть в управляющей таблице АЦП установлено 7 логических каналов. Если был принят блок данных от модуля содержащий 5 отсчетов АЦП (и произвольное количество значений цифровых входов, если включен синхронный ввод с цифровых линий) и обработан с помощью X502_ProcessData(), то X502_ProcessData() вернет преобразованные 5 отсчетов АЦП, соответствующие логическим каналом с индексами 0,1,2,3,4. Следующий логический канал, который ожидается для обработки --- логический канал с индексом 5, поэтому X502_GetNextExpectedLchNum() вернет значение 5. Если обработать следующий блок данных, содержащий 5 следующих отсчетов, то X502_ProcessData() вернет отсчеты соответствующие каналам с индексами 5,6,0,1,2. Т.е. с помощью вызова X502_GetNextExpectedLchNum() можно узнать, какому логическому отсчету будет соответствовать первый элемент выходного массива при последующем вызове X502_ProcessData().
|
||||
|
||||
Следует учесть, что по умолчанию буфер в драйвере или библиотеке рассчитан на количество отсчетов, которое будет введено за 4с непрерывного сбора. Если вовремя не считывать данные с помощью X502_Recv(), то произойдет переполнение буфера в драйвере и часть данных, для которых не нашлось в буфере места, будет потеряна. При последующем появлении места в буфере, в то место в потоке, где произошел разрыв непрерывного потока данных, будет вставлено слово, представляющее собой сообщение о переполнении буфера. Если X502_ProcessData() во входном массиве обнаружит это слово, то функция вернет ошибку #X502_ERR_STREAM_OVERFLOW. При этом, как и в случае возникновения других ошибок обработки, все отсчеты, которые были до возникновения ошибки будут обработаны и возвращены в выходных массивах (размеры которых будут соответственно обновлены).
|
||||
|
||||
Аналогично, для формирования общего потока на вывод в требуемом формате используется функция X502_PrepareData(), принимающая данные из трех массивов и сохраняющая их во внешний массив. Если какой-либо из источников не должен использоваться, то в качестве массива передается нулевой указатель. Для каналов, которые не были настроены на синхронный режим с помощью X502_StreamsEnable(), входной массив на анализируется и данные из него не используются..
|
||||
|
||||
Следует отметить, что если для синхронного ввода инициализация потока передачи происходит по X502_StreamsStart(), так как данные начнут поступать только после запуска синхронного ввода, то с синхронным выводом дело обстоит несколько иначе. Так как по X502_StreamsStart() уже должна начаться выдача синхронных данных, то часть данных уже должна быть загружена в модуль. Таким образом, после разрешения синхронного вывода по нужным каналам с помощью X502_StreamsEnable() и до запуска синхронного вывода с помощью X502_StreamsStart() необходимо осуществить предзагрузку части данных синхронного потока. Для этого следует вызвать функцию X502_PreloadStart(), по которой в драйвере или библиотеке будет выделен буфер на передачу и инициализирован поток на передачу, а затем записать часть синхронных данных в буфер драйвера с помощью X502_PrepareData() и X502_Send(). Если этого не сделать, то синхронный вывод начнется лишь после того, как данные будут записаны в модуль и не будет привязан к началу синхронного сбора/выдачи данных.
|
||||
|
||||
Кроме того, для синхронной выдачи данных на ЦАП рекомендуется предварительно установить начальные значения на ЦАП с помощью функции асинхронного вывода. В противном случае при начале синхронного вывода может быть небольшой переходный процесс от значения на ЦАП, которое было до запуска синхронного вывода, до выставления первых нужных значений, т.к. ЦАП имеет свой фильтр и ограничения на скорость изменения сигнала.
|
||||
|
||||
|
||||
Циклический вывод {#sect_cycle_out}
|
||||
-------------------------------------------------------------------------
|
||||
Для модуля L-502, начиная с версии 1.0.4 драйвера и библиотеки, а также для модуля E-502 (начиная с версии 1.1.0), введена поддержка циклического вывода на ЦАП и цифровые выводы. Этот режим позволяет загрузить сигнал полностью в буфер внутри драйвера (для L-502) или процессора Cortex-M4 (для E-502), содержимое которого будет циклически выводиться без необходимости дальнейшей подкачки.
|
||||
|
||||
Данные для загрузки в циклический буфер подготавливаются также как и для потокового вывода с помощью X502_PrepareData() и записываются с помощью X502_Send() и могут содержать комбинацию данных на оба канала ЦАП и на цифровые выводы. Циклический вывод является вариантом синхронного вывода и для его работы нужно разрешить нужные потоки на вывод через X502_StreamsEnable() и должен быть запущен синхронный ввод-вывод через X502_StreamsStart(). Также как и с обычным потоковым выводом, часть каналов может использоваться для вывода циклического сигнала, а часть --- асинхронно. Однако нельзя часть каналов вывода использовать в циклическом режиме, а часть в потоковом режиме с подкачкой (естественно, циклический режим на вывод можно использовать с потоковым на ввод).
|
||||
|
||||
Для вывода циклического сигнала используется двойная буферизация --- то есть может быть выделено два буфера, пока из одного сигнал циклически выводится, в другой может подгружаться следующий сигнал. Смена сигнала происходит по концу периода предыдущего. При этом после записи одного сигнала необходимо, чтобы успела пройти смена сигналов перед тем как можно будет загружать следующий, в противном случае функция X502_OutCycleLoadStart() вернет ошибку (что можно использовать как признак, что буфер еще не готов для загрузки нового сигнал). Проверку завершения смены сигнала можно сделать при соответствующих версиях ПО (см. описание функции X502_OutCycleCheckSetupDone()) и явно с помощью функции X502_OutCycleCheckSetupDone() или используя флаг #X502_OUT_CYCLE_FLAGS_WAIT_DONE во время вызова X502_OutCycleSetup(), чтобы функция вернула управление только после выполнения смены сигналов.
|
||||
|
||||
Для загрузки сигнала сперва вызывается функция X502_OutCycleLoadStart(), в которой задается размер циклического буфера, который будет использован для хранения отсчетов всех используемых каналов вывода. Например, если нужно использовать два канала ЦАП, на каждый из которых вывести сигнал из 1000 точек, то размер должен быть указан 2000. После этого отсчеты загружаются как и при потоковом выводе с подкачкой с помощью функций X502_PrepareData() и X502_Send(). При этом суммарно должно быть записано ровно столько же отсчетов, сколько было указано при вызове X502_OutCycleLoadStart(). После загрузки по вызову X502_OutCycleSetup() происходит переключение на загруженный буфер, при этом, в зависимости от текущего состояния, это приводит к следующему:
|
||||
- если синхронный ввод-вывод не запущен (не было вызова X502_StreamsStart()) то начинается предзагрузка циклического сигнала в модуль, однако реально выдача сигнала начнется только при вызове X502_StreamsStart() (или по внешнему условию запуска). Это позволяет привязать начало вывода первого отсчета циклического сигнала к началу ввода. При этом необходимо вызывать X502_OutCycleSetup() с флагом #X502_OUT_CYCLE_FLAGS_WAIT_DONE, чтобы гарантировать, что загрузка сигнала завершится до X502_StreamsStart() (актуально в первую очередь для E-502, где передача данных идет по интерфейсу и может занимать значительное время).
|
||||
- если синхронный ввод-вывод запущен, но не было выведено ни одного циклического сигнала до этого, то по X502_OutCycleSetup() начинается вывод циклического сигнала.
|
||||
- если синхронный ввод-вывод запущен и уже выводится предыдущий циклический сигнал, то после вызова X502_OutCycleSetup() в драйвере (или модуле для E-502) будет взведен флаг о необходимости переключить сигналы. После этого события по достижению конца предыдущего циклического буфера будет произведена смена буферов вывода. Таким образом это позволяет производить смену сигнала всегда в известной точке. При смене сигнала происходит освобождение старого буфера и только после реальной смены можно будет вызвать следующий раз X502_OutCycleLoadStart() для загрузки следующего сигнала. При использовании флага #X502_OUT_CYCLE_FLAGS_WAIT_DONE, функция вернет управление только в момент, когда сама смена уже произойдет (если эта возможность поддерживается ПО).
|
||||
|
||||
Останов циклического вывода можно осуществить одним из следующий способов:
|
||||
- X502_OutCycleStop() останавливает циклический вывод после вывода последней точки на границе циклического буфера. То есть эта функция используется, чтобы циклический вывод был завершен точно в известной точке и на выходах остались значения, соответствующие последним отсчетам в циклическом сигнале. При этом сама функция не дожидается останова вывода, если не указан флаг #X502_OUT_CYCLE_FLAGS_WAIT_DONE.
|
||||
- X502_StreamsDisable() с указанием всех используемых каналов вывода приводит к немедленному завершению вывода и освобождением всех буферов. На выходах останутся значения, которые были в момент вызова. После этого можно будет заново разрешить и проинициализировать вывод как в циклическом так и в потоковом режиме с подкачкой.
|
||||
- X502_StreamsStop() приводит к немедленному останову всех потоков и останову генерации опорной частоты синхронизации. На выходе остаются те значения, которые были в момент вызова функции.
|
||||
|
||||
|
||||
|
||||
Размер буфера и шаг для синхронного режима {#sect_sync_mode_buf}
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
В данном разделе приводится дополнительная информация о том, как можно настроить дополнительные параметры, управляющие передачей потока данных в синхронном режиме между модулем и ПК. Эти параметры по умолчанию настраиваются библиотекой автоматически. Предполагается, что большинству пользователей должны подойти автоматически настраиваемые параметры и данный раздел не является обязательным. Однако для случаев, когда автоматически определенные параметры не подходят, пользователь может задать их самостоятельно. Для этого в этом разделе приводится описание, как выбирается размер буфера и шаг библиотекой, что означают эти параметры и как их можно настроить вручную.
|
||||
|
||||
Как уже было сказано [в предыдущем разделе](@ref sect_sync_mode) прием и передача синхронных данных осуществляется через буфера в драйвере или библиотеке -- один буфер на прием, один на передачу.
|
||||
|
||||
Выделение буфера на ввод осуществляется по X502_StreamsStart(), если был разрешен хотя бы один источник для синхронного ввода. Выделение буфера на вывод осуществляется по X502_PreloadStart().
|
||||
|
||||
При этом размер буфера определяется автоматически библиотекой в зависимости от установленной частоты передачи данных. Размер буфера рассчитывается так, чтобы его хватило на 4 секунды при синхронном вводе и на 3 секунды при синхронном выводе.
|
||||
|
||||
Вторым параметром, характеризующим передачу, является шаг передачи.
|
||||
Для модуля L-502 этот параметр определяет шаг прерываний. Передача данных между буфером драйвера и модулем осуществляется непосредственно самим модулем по DMA. При этом, чтобы драйвер мог узнать о том, что данные были записаны в буфер или прочитаны из него, при передаче определенного количества отсчетов модуль генерирует прерывание. То есть реально драйвер "узнает" о том, что были переданы данные только после того как будет передано заданное количество отсчетов, называемое в данной главе шагом прерываний (Точнее сказать, не позже, чем будет передано заданное количество отсчетов, так как драйвер может прочитать значение счетчика переданных данных из модуля и по другим условиям).
|
||||
|
||||
Таким образом, малый шаг прерываний позволяет драйверу раньше узнает о принятых или переданных данных, но приводит к большей загрузке системы. Библиотека рассчитывает шаг прерываний так, чтобы прерывания происходили с частотой 64 раза в секунду.
|
||||
|
||||
Для модуля E-502 этот параметр определяет используемый размер запроса по USB. Кроме того при вводе данные ставятся на передачу в ПК при из размере равным шагу, но при этом при отсутствие поступления новых данных могут быть поставлен на передачу и меньший объем данных.
|
||||
|
||||
Если пользователя по каким-либо причинам не устраивают эти значения он может настроить их вручную с помощью функций X502_SetStreamBufSize() и X502_SetStreamStep(). Эти функции должны быть вызваны до инициализации потоков передачи (до X502_StreamsStart() или X502_PreloadStart()).
|
||||
|
||||
В частности, случаями когда значения библиотеки могут не устроить, могут быть следующие:
|
||||
- Пользователь использует свою прошивку BlackFin и использует каналы синхронных данных для передачи пользовательских данных, которые сильно изменяют скорость передачи данных. В этом случае библиотека не может правильно определить частоту передачи, так как не знает скорости передачи пользовательских данных.
|
||||
- Пользователь изменяет каналы, которые используются в синхронном режиме, на лету (после X502_StreamsStart()) и при этом скорости передачи по этим каналам существенно отличаются. Так как расчет размера буфера выполняется при инициализации канала, то он осуществляется только по тем каналам, которые были разрешены на тот момент. Если, например, был разрешен только синхронный сбор с АЦП на относительно небольшой частоте, то буфер будет выделен также небольшой. При этом, если после запуска сбора данных будет разрешен синхронный ввод с цифровых линий на частоте 2МГц, то вероятнее всего этот буфер окажется недостаточного размера, и с большой вероятностью произойдет его переполнение.
|
||||
Если же оба этих потока были разрешены изначально, а потом синхронный ввод цифровых линий будет запрещен, то рассчитанный изначально шаг прерывания будет слишком большим и данные от медленного потока АЦП будут обновляться с большими задержками. Если же частоты каналов соизмеримы, то включение/отключение одного из них не приведет к существенному изменению параметров.
|
||||
Изменение шага прерывания и размера буфера при запущенном сборе данных на текущий момент невозможно.
|
||||
|
||||
|
||||
Особенности работы по интерфейсу Ethernet и настройка сетевых параметров {#sect_eth_config}
|
||||
============================================================================
|
||||
Если USB-интерфейс в модуле E-502 всегда работает и не требует дополнительной конфигурации, то для работы по интерфейсу Ethernet необходимо выполнить настройку параметров интерфейса и разрешить данный интерфейс.
|
||||
Следует отметить, что при разрешенном Ethernet-интерфейсе с модулем можно работать как по USB, так и по Ethernet. При этом сбор/генерация данных могут выполняться одновременно только по одному интерфейсу (по которому пришла команда на запуск сбора/выдачи).
|
||||
|
||||
Основными параметрами для работы по Ethernet являются:
|
||||
- IP-адрес устройства. Записывается как 4 цифры от 0 до 255 (модуль поддерживает только протокол IPv4), разделенные точками (например, 192.168.0.10). Состоит из адреса подсети и адреса устройства внутри подсети. Последний должен быть уникальным внутри подсети.
|
||||
- Маска подсети. Определяет какая часть адреса относится к адресу подсети, а какая к адресу устройства. Маска 255.255.255.0 означает, что первые 3 цифры (192.168.0) обозначают адрес подсети, последняя цифра (10) - адрес устройства в подсети.
|
||||
- IP-адрес шлюза. Используется только когда модуль E-502 и хост, с которого выполняется управление модулем, находятся в разных подсетях. Модуль передает пакеты по адресу шлюза, если адрес назначения находится не в той же подсети, что и модуль. При работе в локальной сети не используется.
|
||||
- MAC-адрес модуля (6 цифр от 0 до 255, которые записываются в 16-ричном формате). Физический адрес устройства, который должен быть уникален внутри локальной сети. В "Л Кард" для каждого модуля прописывается свой заводской MAC-адрес, который нельзя изменить. Однако, при необходимости, пользователь может задать свой пользовательский MAC адрес и разрешить его использование вместо заводского. При этом всегда есть возможность вернутся к заводскому MAC-адресу, запретив пользовательский.
|
||||
- Имя экземпляра устройства. Уникальное имя данного экземпляра в виде строки (до 64 английских символов или 32 русских). Используется для возможности автоматического обнаружения модулей в локальной сети (подробнее в главе @ref sect_eth_browsing).
|
||||
|
||||
Для работы в первую очередь необходимо задать правильные IP-параметры (адрес, маску и, при необходимости, адрес шлюза), подробнее о чем описано в [соответствующем разделе FAQ](http://lcard.ru/support/faq/tcpip_settings).
|
||||
|
||||
IP-параметры модуля E-502 могут быть установлены 3-мя способами:
|
||||
- Заданы вручную (статические параметры). Пользователь сам должен позаботиться о том, чтобы адрес принадлежал нужной подсети и был уникальный в ней.
|
||||
- Получены автоматически от DHCP-сервера. Если задано автоматическое получение адреса и в локальной сети присутствует DHCP-сервер, то модуль делает запрос к нему и использует выделенные DHCP-сервером IP-адреса.
|
||||
- Может использоваться автоматически получаемый локальный (link-local) адрес (в соответствии с [RFC3927](https://tools.ietf.org/html/rfc3927)). Адрес выбирается случайным образом в диапазоне от 169.254.1.0 до 169.254.254.255 и проверяется, что в сети нет другого устройства с таким адресом (если есть, то идет попытка выбора следующего адреса и т.д.). Это делает возможным подключение к устройству в локальной сети без специальной конфигурации. Следует однако отметить, что т.к. адрес действителен только в одной сети, то два разных устройства в разных сетях могут иметь одинаковый link-local адрес, что приводит к тому, что если у ПК несколько активных интерфейсов (и на обоих используется link-local адрес или наоборот обычный адрес), то хост не знает на каком интерфейсе искать нужное устройство. Т.е. для подключения по link-local адресу на ПК должен быть либо один активный сетевой интерфейс, либо на нужном интерфейсе должен использоваться link-local адрес, а на другом статический или полученный по DHCP адрес.
|
||||
|
||||
При включении автоматического получения адреса модуль выбирает себе link-local адрес (и проверяет его уникальность), параллельно выполняя поиск в сети DHCP-сервера. Если DHCP сервер не обнаружен, то используется link-local адрес. Как только будет обнаружен DHCP-сервер, то предпочтение отдается полученному от него адресу (в частности при старте в сети с DHCP сервером модуль может некоторое время до получения адреса от него использовать link-local адрес). Подобный алгоритм используется при автоматическом получении адреса в частности в ОС Windows, а также и во многих дистрибутивах Linux (иногда предоставляя возможность отдельного разрешения DHCP и link-local адреса). Следует также иметь ввиду, что автоматически получаемый адрес модуль проверяет на уникальность в сети, поэтому существует задержка в несколько секунд от подключения к сети модуля до назначения адреса.
|
||||
Автоматическое получение адреса не требует дополнительных настроек, однако при этом неизвестен адрес устройства со стороны ПК для установления соединения. Для решения этой проблемы возможно использование процедуры поиска устройств в локальной сети, описанной [в следующем разделе](@ref sect_eth_browsing).
|
||||
|
||||
Изменить сетевые настройки можно с помощью программы [X502Studio](https://gitlab.com/l-card/acq/devices/x502/x502studio).
|
||||
|
||||
Также изменение сетевых настроек модуля возможно программным образом через API библиотеки. Для этого существует отдельный тип описателя конфигурации #t_e502_eth_config_hnd. Для изменения конфигурации нужно выполнить следующие шаги:
|
||||
1. Создать описатель конфигурации с помощью E502_EthConfigCreate().
|
||||
2. Прочитать текущую конфигурацию устройства с помощью E502_EthConfigRead() (соединение с модулем должно быть установлено)
|
||||
3. Можно получить нужные параметры с помощью функций E502_EthConfigGetXXX() и/или установить новые значения с помощью функций E502_EthConfigSetXXX().
|
||||
4. После завершения изменений можно записать измененную конфигурацию в модуль с помощью E502_EthConfigWrite(). Модуль сохранит новую конфигурацию в энергонезависимой памяти, запрещает Ethernet-интерфейс, после чего снова его переинициализирует уже с новыми параметрами. При этом, если соединение с устройством было выполнено по Ethernet, то для дальнейшей работы нужно разорвать соединение и установить заново (используя новые параметры)
|
||||
|
||||
Для избежания непреднамеренного изменения конфигурации по сети, конфигурация может быть защищена простым паролем. Пока пароль не установлен в качестве пароля нужно передавать пустую строку. Установка нового пароля выполняется аналогично любым другим изменениям параметров конфигурации (с помощью E502_EthConfigSetNewPassword()).
|
||||
|
||||
В случае, если пароль забыт, то можно установить соединение по USB и изменить конфигурацию (включая пароль), введя в качестве текущего пароля серийный номер модуля.
|
||||
|
||||
Обнаружение модулей в локальной сети {#sect_eth_browsing}
|
||||
===========================================================================
|
||||
В отличие от интерфейсов USB и PCI-Express, для интерфейса Ethernet нет стандартной возможности определения подключенных устройств. Однако есть ряд протоколов, реализация которых позволяет обнаружить устройства заданного типа в локальной сети. Для этой возможности модуль E-502 поддерживает протоколы mDNS (в соответствии с [RFC6762](https://tools.ietf.org/html/rfc6762)) и DNS-SD ([RFC6763](https://tools.ietf.org/html/rfc6763)).
|
||||
В соответствии с ними, каждое устройство при подключении объявляет набор сервисов, который оно поддерживает.
|
||||
|
||||
Чтобы различать экземпляры устройств, поддерживающие одинаковый тип сервисов, у каждого экземляра есть свое уникальное имя. Это имя задается во время конфигурации модуля. Если оно не установлено, то в качестве имени экземпляра используется \"E502_\<серийный_номер\>\", однако пользователь может задать свое имя, характеризующее назначение конкретного модуля для более наглядной идентификации. Кроме имени экземпляра у каждого сервиса может быть набор текстовых параметров, описывающих данный экземпляр (для E-502 это параметры задающие имя типа устройства (поле devname, значение равно всегда E-502) и серийный номер (поле serial).
|
||||
|
||||
В соответствии с этим протоколом у хоста в локальной сети есть возможность найти все экземпляры заданного сервиса в сети.
|
||||
Для обнаружения должна быть запущена соответствующая служба (или демон), отслеживающая изменения наличия устройств в сети, а уже функции e502api работают с данной службой. В ОС Linux в качестве реализации данного протокола используется демон Avahi, который включен в большинство современных дистрибутивов и входит в стандартную установку (или нужно установить соответствующий пакет вручную).
|
||||
В ОС Windows используется служба Bonjour, которая штатно не установлена, однако установщик включен в @lpcie_sdk и данная служба будет установлена при выборе соответствующего пункта (следует отметить, что так как служба является отдельным продуктом, который может использоваться и другим ПО, то она не удаляется автоматически при удалении @lpcie_sdk. При необходимости следует вручную удалить службу через установку и удаление программ в "Панели управления").
|
||||
|
||||
Использование данного API позволяет автоматически обнаруживать подключенные в локальной сети устройства, во многом подобно другим интерфейсам.
|
||||
Однако существуют следующие особенности:
|
||||
- Обнаружение модуля связано с посылкой пакетов и приемом ответов, которые могут быть потеряны при определенных условиях и потребовать переповторов. Это выполняется на уровне протокола и невидимо для пользователя, однако надо иметь ввиду, что обнаружение устройства может потребовать некоторого времени.
|
||||
- Так как отключение отслеживается на уровне протокола, нет оповещения о физическом отключении кабеля. Соответственно при выключении питания или выдергивании кабеля отключение модуля может быть не обнаружено на протяжении длительного времени.
|
||||
|
||||
Для поиска устройств следует вызвать E502_EthSvcBrowseStart(), после чего использовать полученный [контекст поиска устройств в сети](@ref t_e502_eth_svc_browse_hnd) для последующих вызовов E502_EthSvcBrowseGetEvent(). Каждый вызов возвращает информацию максимум об одном событии и немедленно возвращает управление, как только оно произошло. Каждому новому обнаруженному модулю соответствует событие #E502_ETH_SVC_EVENT_ADD. В случае изменения параметров (например адреса) приходит событие #E502_ETH_SVC_EVENT_CHANGED, а при исчезновении (при условии описанных выше особенностей) --- #E502_ETH_SVC_EVENT_REMOVE. Для каждого события возвращается [описатель сетевого сервиса](@ref t_e502_eth_svc_record_hnd), по которому можно определить, какому модулю соответствует событие (узнать имя экземпляра и серийный номер модуля), а также запросить IP-адрес модуля. Для каждого события (кроме случая, когда событие не обнаружено и возвращен код #E502_ETH_SVC_EVENT_NONE) этот описатель необходимо освободить с помощью E502_EthSvcRecordFree() как только он станет ненужным.
|
||||
В простейшем случае можно вызвать E502_EthSvcBrowseGetEvent() пока не будет обнаружено появление нужного устройства или не истечет таймаут на поиск устройства. При желании также можно использовать периодический вызов E502_EthSvcBrowseGetEvent() для постоянного мониторинга устройств в сети.
|
||||
В любом случае, когда поиск устройств закончен, необходимо вызвать E502_EthSvcBrowseStop().
|
||||
|
||||
Установить связь с модулем по [описателю сетевого сервиса](@ref t_e502_eth_svc_record_hnd) можно как вручную по полученному адресу через E502_EthSvcRecordResolveIPv4Addr(), так создать запись о устройстве с помощью E502_MakeDevRecordByEthSvc() для последующего открытия через X502_OpenByDevRecord().
|
||||
|
||||
|
||||
\tableofcontents
|
||||
BIN
x502api-1.1.34/doc/images/adc_frame.jpeg
Normal file
BIN
x502api-1.1.34/doc/images/adc_frame.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
x502api-1.1.34/doc/images/adc_frame.odg
Normal file
BIN
x502api-1.1.34/doc/images/adc_frame.odg
Normal file
Binary file not shown.
11
x502api-1.1.34/doc/mainpage.md
Normal file
11
x502api-1.1.34/doc/mainpage.md
Normal file
@ -0,0 +1,11 @@
|
||||
Описание библиотеки l502api {#mainpage}
|
||||
============
|
||||
Описание состоит из следующих частей:
|
||||
-# \subpage sect_about
|
||||
-# \subpage sect_setup
|
||||
-# \subpage sect_gen_descr
|
||||
-# Список всех определений
|
||||
-# \subpage const_list
|
||||
-# \subpage type_list
|
||||
-# \subpage func_list
|
||||
|
||||
171
x502api-1.1.34/doc/setup.md
Normal file
171
x502api-1.1.34/doc/setup.md
Normal file
@ -0,0 +1,171 @@
|
||||
Подключение библиотеки {#sect_setup}
|
||||
==============================================================
|
||||
|
||||
Для написания собственного программного обеспечения, работающего с модулями L-502 и E-502, необходимо выполнить следующее:
|
||||
1. Установить драйвер для модулей:
|
||||
- Для работы с модулями, подключенными по интерфейсу PCI Express, необходим специальный драйвер, предоставляемый фирмой "Л Кард"
|
||||
- Для работы с модулями, подключенными по интерфейсу USB, используется библиотека [libusb-1.0](http://libusb.info). Под Windows сама библиотека включена в стандартную библиотеку \filename{e502api.dll}, а в качестве драйвера используется стандртный драйвер [WinUSB](https://msdn.microsoft.com/en-us/library/windows/hardware/ff540196%28v=vs.85%29.aspx). Под ОС Linux необходимо установить библиотеку [libusb-1.0](http://libusb.info), при этом никаких специальных драйверов не требуется.
|
||||
- Для работы с модулями, подключенными по интерфейсу Ethernet (TCP/IP), специальных драйверов не требуется. Для возможности выполнять поиск модулей в локальной сети должна быть установлена соответствующая служба (см. главу @ref sect_eth_browsing).
|
||||
2. Установить необходимые динамические библиотеки (.dll для Windows или .so для Linux) в директорию, присутствующую в соответствующей переменной окружения, либо в директорию с проектом. Динамическая библиотека необходима при написании программ на любом языке программирования, так как все привязки к языкам работают через указанные библиотеки.. Всего предоставляется три библиотеки:
|
||||
- \filename{x502api} --- содержит общие функции для обоих модулей. Должна включаться в любой проект, работающий с одним из модулей, за исплючением проектов, написанных только для L-502 до появления библиотеки x502api, которые могут использовать только l502api
|
||||
- \filename{l502api} --- содержит специфические функции для модуля L-502, а также функции, оставленные для совместимости с проектами, написанными до появления x502api.
|
||||
- \filename{e502api} --- содержитспецифические функции для модуля E-502.
|
||||
3. Подключить библиотеку к проекту.
|
||||
|
||||
Для ОС Windows предоставляется общий установщик @lpcie_sdk, который автоматически устанавливает все необходимые драйвера, динамические библиотеки в системную директорию, а также все файлы, необходимые для подключения библиотеки к проекту и примеры в указанную директорию. В дальнейшем в данной главе с помощью @lpcie_sdk_dir будет обозначаться указанная при установке @lpcie_sdk директория.
|
||||
|
||||
Установка для ОС Linux описана в разделе @ref sect_setup_linux.
|
||||
|
||||
Подключение к проекту зависит от используемого языка и среды программирования.
|
||||
|
||||
Подключение библиотеки при написании программы на языках C/C++ {#sect_setup_c}
|
||||
=========================================================================
|
||||
|
||||
При написании на C/С++ при подключении необходимо выполнить следующее:
|
||||
1. Включить в проект заголовочный файл "l502api.h" и/или "e502api.h", добавив при этом в проекте к путям для заголовочных файлов директорию @lpcie_sdk_dir/include.
|
||||
2. Добавить в проект файл линкера нужных библиотек для используемого компилятора:
|
||||
- <B> Microsoft Visual С++ </B>: @lpcie_sdk_dir/lib/msvc
|
||||
- <B> Microsoft Visual С++ </B> 64-битный компилятор (подробнее о 64-битной версии [описано ниже](@ref sect_setup_64)): @lpcie_sdk_dir/lib/msvc64
|
||||
- <B> Borland C++/Borland C++ Builder </B>: @lpcie_sdk_dir/lib/borland
|
||||
- <B> Borland C++/Borland C++ Builder </B> 64-битный компилятор: @lpcie_sdk_dir/lib/borland64
|
||||
- <B> MinGW </B>: @lpcie_sdk_dir/lib/mingw
|
||||
- <B> MinGW </B> 64-битный компилятор: @lpcie_sdk_dir/lib/mingw64
|
||||
|
||||
Примеры программ на @langname{C} находятся в @filename{@lpcie_sdk_dir/examples/c}. Специальные примеры для <B> Borland C++ Builder </B> --- в @filename{@lpcie_sdk_dir/examples/CppBuilder}.
|
||||
|
||||
|
||||
Использование библиотеки в проекте на Delphi {#sect_setup_delphi}
|
||||
=========================================================================
|
||||
|
||||
Для написания программ на @langname{Delphi} с использованием библиотеки для работы с модулями L-502 и E-502, необходимо включить в проект программы файл @filename{@lpcie_sdk_dir/pas/x502api.pas}, а также файл @filename{@lpcie_sdk_dir/pas/l502api.pas} и/или @filename{@lpcie_sdk_dir/pas/e502api.pas}, которые представляют собой обертку над библиотеками на @langname{C}.
|
||||
В файлах проекта, которые используют типы и функции из этого документа, необходимо подключить модуль x502api, а также l502api и/или e502api с помощью `uses x502api;`, `uses l502api;` и `uses e502api;` соответственно. При этом для 64-битного компилятора используются те же файлы, что и для 32-битного (см. @ref sect_setup_64).
|
||||
|
||||
Следует отметить, что по сравнению с версиями до поддержки E-502, файл @lpcie_sdk_dir/pas/lpcieapi.pas больше не используется. Т.к. этот файл не должен был использоваться в проектах напрямую, то он не включен в новых версиях библиотеки.
|
||||
|
||||
Все функции, типы и константы библиотеки отображаются в @langname{Delphi} один к одному, за исключением следующих моментов:
|
||||
- все строки (серийные номера, строки с описанием кодов ошибок) преобразуются оберткой в тип `string`, который используется стандартно для представления строк в @langname{Delphi} (следует не забывать, что в последних версиях среды этот тип представляет собой юникодную строку). Исключением является структура #t_x502_info с информацией о модуле, в которой строки представлены массивом `AnsiChar` фиксированной длины.
|
||||
- все функции, работающие с массивами, принимают в качестве параметра открытый массив (open array parameter), что означает, что в эти функции можно передать как статический массив, так и динамический (установив предварительно его длину с помощью `SetLength()`). При этом, так как массивы Delphi содержат в себе длину, то в функции L502_GetSerialList() и E502_UsbGetSerialList(), а также L502_GetDevRecordsList() и E502_UsbGetDevRecordsList() отдельно передавать размер массива не требуется. Однако в функциях для работы с данными (например, X502_Recv()) длина передается так же, как и в функциях @langname{C}, чтобы можно было использовать для приема не обязательно весь массив. При этом дополнительно проверяется, что переданная отдельным параметром длина не превышает реальную длину массива. В случае превышения будет возвращена ошибка #X502_ERR_INSUFFICIENT_ARRAY_SIZE.
|
||||
|
||||
Пример программы на @langname{Delphi} находится в @filename{@lpcie_sdk_dir/examples/Delphi}.
|
||||
|
||||
Использование библиотеки в проекте на C# {#sect_setup_sharp}
|
||||
=========================================================================
|
||||
|
||||
Для написания программ, работающих с модулями L-502 и E-502, на языке @langname{C#} (или на любом другом, поддерживаемым NetFramework), реализована специальная библиотека-обертка lpcieNet.dll. Она использует описанные ранее библиотеки на @langname{C}, в которых реализована вся логика работы с устройством.
|
||||
Установщик позволяет установить lpcieNet.dll в системный кэш (GAC), что позволяет не копировать библиотеку вместе с Вашим проектом. Однако, к сожалению, Visual Studio не позволяет добавлять в проект ссылки из системного кеша и Вам все равно придется саму ссылку делать на локальную копию (просто ее не обязательно будет распространять вместе с проектом). Библиотека в кеше имеет преимущество перед локальной и будет всегда использованна именно она, если установлена.
|
||||
|
||||
Для использования библиотеки достаточно добавить в проект ссылку на lpcieNet.dll и в исходниках подключить нужные пространства имен:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
using x502api;
|
||||
using lpcieapi;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Для совместимости с программами, написанными до включения поддержки L-502, оставлена старая версия всех определений в пространстве имен l502api со старой версией класса L502.
|
||||
|
||||
По сравнению с функциями языка @langname{C} в обертке @langname{C#} сделаны следующие изменения:
|
||||
- Так как @langname{С#} --- объектно ориентированный язык, то для управления модулями созданы специальные классы L502 и E502, которые наследуются от общего класса X502.
|
||||
- Все функции, которые принимают описатель модуля первым параметром реализованы методами классов L502, E502 или X502, при этом сам префикс L502_, E502_ или X502_ не используется.
|
||||
Например, вместо `L502_Open(hnd, serial)`, используется `hnd.Open(serial)`. Для сетевой конфигурации модуля E-502 используется отдельный класс E502.EthConfig.
|
||||
- Функции X502_Create() и X502_Free() вызывается в конструкторе и деструкторе класса X502, отдельными функциями не реализованы. Аналогично обстоит дело c X502_FreeDevRecordList() и классом X502.DevRec, а также с функциями E502_EthConfigCreate() и E502_EthConfigFree() и классом E502.EthConfig.
|
||||
- Для создания нужного объекта устройства (L502 или E502) по имени модуля реализован статический метод `X502.Create(devname)`.
|
||||
- Функции, которые не требуют экземпляра модуля (не принимают описатель первым параметром), реализованы как статические функции соответствующих классов. Например `X502_GetErrorString(err)` раеализована как `X502.GetErrorString(err)`.
|
||||
- Функции типа Get/Set, которые принимают описатель модуля и один параметр, реализованы в виде свойств (properties). Например, вместо `X502_SetLChannelCount(hnd, value)`, используется `hnd.LChannelCount = value`. Однако следует быть внимательным, так как неправильно устанавливаемое значение вызовет исключение `X502.Exception`.
|
||||
- Константы объявлены внутри классов и без префикса L502_, E502_ или X502_.
|
||||
- Перечисления также объявлены как перечисления внутри класса и без префикса `X502_ПЕРЕЧИСЛЕНИЕ`. Например не #X502_SYNC_INTERNAL, а `X502.Sync.INTERNAL`.
|
||||
- Коды ошибок, так как планируется использовать общие коды ошибок и для будущих модулей, вынесены в перечисление ERR в классе lpcie.
|
||||
- Все функции, использующие в C строки в виде `char *`, используют в обертке строки типа `String`.
|
||||
- Функции `L502.GetSerialList()`, `E502.UsbGetSerialList()`, а также функции `L502.GetDevRecordsList()` и `E502.UsbGetDevRecordsList()` возвращают созданный внутри функции динамический массив строк/записей о устройстве (а не заполняет переданный), который уже содержит длину. Поэтому дополнительный параметр размера массива не требуется.
|
||||
- Как и в Delphi, при работе с массивами данных передается длина дополнительным параметром, так как можно принимать меньше данных, чем в выделенном массиве.
|
||||
- Функции, принимающие указатели в @langname{C}, принимают параметры со спецификаторами out или ref, в зависимости от того, должна ли быть переменная проинциализирована перед вызовом функции или является выходным параметром.
|
||||
|
||||
Пример программы на @langname{C#} находится в @filename{@lpcie_sdk_dir/examples/cs}.
|
||||
|
||||
|
||||
Использование библиотеки в проекте LabView {#sect_setup_labview}
|
||||
=========================================================================
|
||||
|
||||
Вы можете управлять модулями L-502 и E-502 из @langname{LabView}, используя тот факт, что @langname{LabView} поддерживает управляемые библиотеки NetFramework. Соответственно, Вы имеете доступ ко всем функциям, которые реализует оболочка @langname{C#} lpcieNet.dll, т.е. все доступные функции библиотеки, с учетом отличий, описанных в [предыдущем разделе](@ref sect_setup_sharp)).
|
||||
|
||||
В отличие от Visual Studio LabView автоматически подхватывает .Net библиотеки из системного кэша (GAC) и Вы можете ссылаться на нее, а не хранить локальную копию вместе с программой.
|
||||
|
||||
Для работы с классами .Net в LabView есть специальная панель <B> Connectivity -> .Net </B>.
|
||||
|
||||
Вам необходимо использовать следующие блоки:
|
||||
- <B> Constructor Node </B> - создает объект. Должен быть создан для каждого модуля L-502 или E-502, с которым будете работать. При создании LabView предложит выбрать библиотеку и класс (нужно выбрать lpcieNet.dll и L-502 или E-502 из пространства x502api). Одним из выходов этого блока является ссылка на объект, которая используются как вход для остальных блоков для работы с модулем. Также с помощью конструктора создается объект логического канала со всеми настройками. Альтернативным вариантом создания объекта модуля является использование метода X502.Create, который создает нужный объект по имени модуля.
|
||||
- <B> Close Reference </B> - закрывает и удаляет объект. Должен вызываться для каждого созданного объекта по завершению работы.
|
||||
- <B> Invoke Node </B> - вызов функции (метода класса). При работе с объектом на вход подается ссылка и входные параметры, а на выходе --- выходные параметры и обновленная ссылка (которая должна использоваться для блоков, которые будут вызваны после текущего). Входная ссылка и определяет, методы какого объекта используются (после заведения ссылки на вход имя класса появится в верхней строке, а при нажатии на вторую будет предложен на выбор его метод). Для функций, которые не работают с конкретным объектом (GetErrorString, GetSerialList и т.д. --- эти функции статические и при выборе помечены [S] в начале) ссылку на вход подавать не обязательно. Однако они все равно принадлежат классу, который надо выбрать нажав правой кнопкой на блок и далее <B> Select Class/.Net </B>
|
||||
- <B> Property Node </B> - используется для установки или получения свойств. Через свойства устанавливается часть параметров (логическая таблица, режим синхронизации) и также можно получить информацию о модуле (в виде класса, каждое поле которого является также отдельным свойством). Можно устанавливать несколько свойств одним блоком, расширив его вниз. Также с помощью свойств можно задавать константы из перечислений (что может быть более понятно, чем просто подавать на вход числа) - в этом случае надо выбрать класс перечисление, а каждому значению соответствует свое свойство.
|
||||
|
||||
Следует отметить особенность передачи массивов в качестве выходных параметров. Сами функции библиотеки для эффективности не выделяют массивов данных внутри себя, а используют переданные массивы для сохранения результатов. Поэтому такие параметры в @langname{LabView} являются входными и выходными одновременно. На вход необходимо подать массив размера, достаточного для сохранения результатов (при этом сами данные не имеют значения), а в качестве выходного параметра возвращается тот же массив, но уже заполненный результатами выполнения функции. Примером таких параметров могут служить параметр <B> buf </B> функции X502_Recv(), параметры <B> adc_data </B> и <B> din_data </B> функции X502_ProcessData(), а также параметр <B> out_buf </B> функции X502_PrepareData().
|
||||
|
||||
Примеры программ на @langname{LabView} находится в @filename{@lpcie_sdk_dir/examples/LabView}.
|
||||
|
||||
Использование библиотеки в Visual Basic 6 {#sect_setup_vb6}
|
||||
=========================================================================
|
||||
Для работы с модулями из программы на @langname{Visual Basic 6} нужно в проект добавить файлы модулей @filename{x502api.bas}, @filename{e502api.bas} и @filename{l502api.bas}, которые можно взять из примера @filename{@lpcie_sdk_dir/examples/vb6/x502_general}. Файлы содержат объявления всех типов, констант и функций.
|
||||
Параметры функций совпадают с функциями языка @langname{C}, за исключением следующих особенностей:
|
||||
- так как в Visual Basic не используются указатели, то для всех описателей используется просто тип `Long`
|
||||
- Функции L502_GetSerialList(), E502_UsbGetSerialList(), а также функции L502_GetDevRecordsList() и E502_UsbGetDevRecordsList() принимают в качестве параметра динамический массив и изменяют его размер в соответствии с количеством найденных элементов. Соответственно, дополнительные явные параметры, задающие размер массива на вход и количество найденных элементов не требуются.
|
||||
- Строки в функциях преобразовываются в строки Visual Basic автоматически. Строки же в структурах представлены массивом байт. Для перевода их в String можно воспользоваться функцией `X502_StrConvert()`
|
||||
- Для освобождения ресурсов одной записи дополнительно введена функция `X502_FreeDevRecord()`, вызывающая X502_FreeDevRecordList() для одного элемента, чтобы не преобразовывать элемент в массив вручную
|
||||
|
||||
Следует отметить, что при отладке из среды @langname{Visaul Basic 6} при останове незавершенной программы, если на момент останова были незакрытые соединения с модулями, то эти соединения могут не закрываться автоматически до перезапуска среды. Соответственно, т.к. количество одновременных соединений ограничено, то модуль может быть не видим в списке найденных устройств или с ним нельзя будет установить соединение до перезапуска среды.
|
||||
|
||||
|
||||
64-битная версия библиотеки {#sect_setup_64}
|
||||
=========================================================================
|
||||
На 64-биной версии Windows могут выполняться программы, как собранные 32-битным, так и 64-битным компилятором, поэтому большинство программ для Windows существует только в 32-битном варианте. 64-битный компилятор используют как правило для программ, работающих с большим количеством данных, так как это позволяет иметь процессу виртуальное пространство больше 4 Гбайт.
|
||||
|
||||
Для 64-битной Windows установщик @lpcie_sdk ставит в соответствующие системные директории 32-битную версию библиотек, так и 64-битную. При этом директория @filename{ Windows/system32} указывает на одну из этих директорий в зависимости от разрядности самого приложения, которое обращается по указанному пути. Для 32-битного приложения в @filename{Windows/system32} находятся 32-битные библиотеки, а 64-битные в@filename{ Windows/Sysnative}, а для 64-битного в @filename{Windows/system32} находятся 64-битные, а @filename{ Windows/Sysnative} не существует. При этом в @filename{Windows/SysWOW64} всегда лежат 32-битные библиотеки и она всегда существует независимо от разрядности приложения.
|
||||
|
||||
При загрузке приложения, если используются системные библиотеки, то они ищутся по путям из переменной окружения PATH, среди которых есть @filename{Windows/system32}. Так как эта директория ссылается на разные места в зависимости от разрядности запускаемого приложения, то выбор библиотеки нужной разрядности из @filename{Windows/system32} происходит автоматически. Если библиотеки распространяются вместе с программой, то нужно следить, чтобы разрядность собранного приложения и библиотек в одной директории совпадала.
|
||||
|
||||
Единственным отличием при написании программ на @langname{C или C++} является необходимость подключить lib-файл в соответствии с разрядностью используемого компилятора.
|
||||
|
||||
Для программ на @langname{Delphi} необходимо только указать, для какой платформы будет собираться проект (win32 или win64) и собранная программа будет использовать библиотеку той разрядности, для которой программа была скомпилирована.
|
||||
|
||||
Программы на языке @langname{C#} (или на любом другом, использующем NetFramework) компилируются в машинный код при выполнении. При этом один раз созданная программа может выполняться как на 32-битной версии, так и на 64-битной версии виртуальной машины NetFramework (в проекте можно указать явно, для какой разрядности NetFramework предназначена программа). Таким образом, одна и та же программа в 32-битной версии Windows будет выполняться с использованием 32-битной версии библиотек, а в 64-битной --- с использованием 64-битной. Для библиотеки .Net разрядность определяется разрядностью использующего его приложения.
|
||||
|
||||
Соответственно, в проекте на @langname{LabView}, который использует .Net библиотеку, разрядность используемой библиотеки определяется разрядностью используемой среды @langname{LabView}.
|
||||
|
||||
Установка библиотеки и драйвера для ОС Linux {#sect_setup_linux}
|
||||
=========================================================================
|
||||
Для установки драйвера и библиотеки под ОС Linux существует два варианта:
|
||||
- Воспользоваться готовыми собранными пакетами, предоставляемыми "Л Кард". Это рекомендованный способ для дистрибутивов, для которых предоставляются собранные пакеты. Список поддерживаемых дистрибутивов можно посмотреть в документе [\"Использование внешних репозиториев 'Л Кард' для дистрибутивов Linux\"](http://www.lcard.ru/download/lcard_linux_distributions.pdf)
|
||||
- Скачать исходные коды @lpcie_sdk и собрать их самостоятельно (подробнее [в следующем разделе](@ref sect_sdk_src)).
|
||||
|
||||
Для примеров работы с модулями L-502 и E-502 на @langname{C} под Linux можно скачать архив с исходниками SDK и посмотреть на примеры в @filename{api/x502api/examples/msvc}. Несмотря на название, они могут быть собраны GCC под ОС Linux. Для каждого примера есть makefile (с комментариями), а также файл CMakeList.txt для предпочитающих сборку с использованием cmake .
|
||||
|
||||
|
||||
О том, как подключить внешний репозиторий, установить собранные пакеты и о преимуществах данного метода установки описано в документе [\"Использование внешних репозиториев 'Л Кард' для дистрибутивов Linux\"](http://www.lcard.ru/download/lcard_linux_distributions.pdf). Здесь же будет приведен список самих пакетов, использующихся при работе с модулями L-502 и E-502, с указанием зависимостей. При подключении внешнего репозитория зависимости разрешаются автоматически (за исключением пакета @filename{lpcie-dkms} , о чем описано ниже). При установке пакетов вручную без подключения внешнего репозитория, следует учитывать зависимости при установке пакетов (например библиотеки следует ставить в следующем порядке: сперва @filename{libx502api1}, затем @filename{libl502api1} и @filename{libe502api1}, и только затем при необходимости @filename{libx502api1-dev} или @filename{libx502api1-devel}).
|
||||
|
||||
|
||||
Для работы с модулями L-502 и E-502 используются пакеты:
|
||||
- @filename{libx502api1-dev} или @filename{libx502api1-devel} --- Пакет с файлами для разработчика: заголовочные файлы и ссылки на библиотеки нужной версии. Нужен при написании своих программ с использованием описанных в данном документе библиотек (зависит от @filename{libx502api1}, @filename{libl502api1} и @filename{libe502api1}, благодаря чему сами библиотеки тоже ставятся автоматически при установке файлов разработчика)
|
||||
- @filename{libx502api1}, @filename{libl502api1} и @filename{libe502api1} --- Пакеты непосредственно с библиотеками нужной версии. Если вы распространяете свою программу, то Вам достаточно включить в зависимости только пакет, соответствующие используемым библиотекам (без пакета с файлами для разработчика), что при создании rpm и deb пакетов выполняется автоматически. Пакет @filename{libx502api1} содержит библиотеку общих функций, которая используются в @filename{libl502api1} и @filename{libe502api1}, поэтому последние зависят от первой. Пакет @filename{libe502api1} также зависит от пакета с библиотекой [libusb-1.0](http://libusb.info) для данного дистрибутива, чтобы она устанавливалась автоматически, а также ставит правила udev для предоставления прав доступа к устройству E-502, подключенного по USB.
|
||||
- @filename{lpcie-dkms} --- Пакет с исходниками драйвера (модуля ядра) для работы с модулями по интерфейсу PCI-Express (L-502), использующий систему сборки внешних модулей dkms (подробнее описано ниже).
|
||||
- @filename{lxfw-update} --- Утилита для обновления прошивок ПЛИС модулей L-502 и E-502. Пакет включает в себя последнюю версию прошивок и скрипты l502-fpga-update-all.sh и e502-fpga-update-all.sh для обновления прошивок всех найденных устройств L-502 или E-502 соответственно.
|
||||
|
||||
Так как драйвер должен быть собран под конкретную версию ядра (а ядро может обновляться в одной версии дистрибутива или даже могут использоваться разные варианты ядра), то драйвер не может распространятся в уже собранном виде. Его сборка выполняется непосредственно при установке пакета. При этом необходимо предварительно поставить пакет с заголовочными файлами текущего ядра (обычно в пакетах с именами @filename{linux-headers} или @filename{kernel-devel}). Для некоторых дистрибутивов может быть несколько вариантов ядра (и соответственно несколько пакетов), более того Вы можете использовать свое ядро. Именно по этой причине пакет не задан зависимостью для @filename{lpcie-dkms}, в отличие от других зависимостей. Узнать текущую версию ядра можно командой: `uname -r`. Убедиться, что нужные файлы установлены можно проверив наличие файлов в директории @filename{/lib/modules/}\`uname -r\`@filename{/build} (обычно это ссылка на заголовки ядра в @filename{/usr/src/linux-\<version\>} или @filename{/usr/src/kernels/\<version\>}).
|
||||
|
||||
Если заголовки текущего ядра установлены, то при установке пакета @filename{lpcie-dkms} будет выполнена сборка драйверов с использованием DKMS (пакет dkms входит в зависимости @filename{lpcie-dkms}, как и make и gcc, необходимые для сборки). DKMS это достаточно широко распространенная система сборки и управления внешними модулями ядра (она находится в основном репозитории большинства дистрибутивов Linux, хотя ее нет в OpenSuse, но для нее распространяется пакет dkms через тот же Open Build System).
|
||||
|
||||
DKMS позволяет:
|
||||
- централизованно отслеживать, какие сторонние модули ядра, какие их версии и для каких версий ядра установлены (dkms status)
|
||||
- хранит всегда исходники драйвера разных версий в централизованном месте (@filename{/usr/src/lpcie-\<version\>})
|
||||
- позволяет автоматически пересобирать драйвер при переходе на новое ядро
|
||||
- позволяет в любой момент удалить драйвер или любую его версию и все связанные с ним файлы (dkms remove -m lpcie -v \<version\> --all)
|
||||
|
||||
Таким образом, хотя в пакете находятся исходники драйвера, а не собранный драйвер, установка мало чем отличается от установки других пакетов, кроме того, что требует дополнительной установки заголовочных файлов ядра и установка пакета требует значительного времени на сборку.
|
||||
|
||||
При установки нового ядра модуль будет пересобран под него автоматически либо при установке пакета, либо при первом входе в систему с новым ядром.
|
||||
|
||||
Исходные коды SDK {#sect_sdk_src}
|
||||
=========================================================================
|
||||
|
||||
Исходные коды всех составных компонентов SDK открыты. Пользователю предоставляется доступ на чтение к репозиторию системы контроля версий [git](https://git-scm.com/), расположенному по адресу https://gitlab.com/l-card/acq/devices/x502/sdk/lpcie_sdk.
|
||||
|
||||
Также возможно скачать архив со всеми исходными кодами SDK по ссылке https://lcard.ru/download/lpcie_sdk_src.zip.
|
||||
|
||||
Инструкции по сборке находятся в файле исходников INSTALL.txt.
|
||||
70
x502api-1.1.34/doc/tstp_descr.md
Normal file
70
x502api-1.1.34/doc/tstp_descr.md
Normal file
@ -0,0 +1,70 @@
|
||||
Работа с метками времени в потоке данных{#sect_tstp_descr}
|
||||
==============================================================
|
||||
Режим синхронизации времени по протоколу PTP {#sect_ptp_descr}
|
||||
==============================================================
|
||||
В модификации E502-P1 добавлен механизм внутренних часов с возможностью их плавной подстройки.
|
||||
Также добавлена поддержка протокола PTP для синхронизации времени по сети Ethernet и реализована возможность вставки меток времени в поток данных "на ввод",
|
||||
Таким образом при включении меток времени появилась возможность вычислять точное время для конкретных слов из потока.
|
||||
E502-P1 поддерживает только Peer-to-Peer режим протокола PTP, поэтому сервер реального времени с которым происходит синхронизация должен быть настроен именно на этот режим.
|
||||
В режиме PTP Peer-to-Peer каждый узел сети (в т.ч. коммутаторы) должен быть PTP - совместимым и учитывать задержку до ближайшего соседнего, иначе работа PTP синхронизации не возможна.
|
||||
|
||||
Если все условия для работы PTP соблюдены, то синхронизация внутреннего значения времени (внутренних часов) в E502-P1 должна заработать автоматически, устройство будет получать значение точного времени с сервера и корректировать внутренние часы.
|
||||
|
||||
Для того чтобы метки времени появились в потоке "на ввод", необходимо специально включить такой режим через соотвтствующее API, по умолчанию этот режим выключен.
|
||||
|
||||
Для работы с PTP в E502-P1 были добавлены несколько новых регистров.
|
||||
Ранее зарезервированный бит в слове "на ввод" теперь означает что слово является меткой времени и для нее вводится признак "захват PTP".
|
||||
|
||||
Признак "захват PTP" - атрибут слова метки времени, означает что для потока слов полученных между двумя метками времени с установленным признаком захвата можно вычислить время каждого слова с определенной точностью.
|
||||
|
||||
Для обеспечения требуемой точности синхронизации в E502-P1 введены несколько настроек.
|
||||
|
||||
- <B>Допустимая рассинхронизация часов, +-нс/с.</B>
|
||||
При каждом получении значения точного времени от сервера, E502-P1 вычисляет разность значения внутренних часов со значением принятым от сервера. Далее эта разность делится на время прошедшее после последней синхронизации (вычисленное по внутренним часам).
|
||||
Вычисленное значение сравнивается с заданным параметром. Синхронизация считается успешной, если вычисленное значение не выходит за заданный интервал.
|
||||
|
||||
- <B>Минимальное кол-во успешных синхронизаций.</B>
|
||||
Для того чтобы признак "захват PTP" появился, должно произойти минимальное количество успешных синхронизаций.
|
||||
В случае неудачной синхронизации, признак "захват PTP" сбрасывается и цикл ожидания минимального количества успешных синхронизаций повторяется.
|
||||
|
||||
|
||||
Работа с модулем при использовании меток времени {#sect_gen_ptp_in}
|
||||
----------------------------------------------------------
|
||||
|
||||
Работа с метками времени из API реализована отдельно от функций управления потоком и функций получения данных из потока.
|
||||
|
||||
1. Включение вставки меток времени в поток данных "на ввод": X502_FpgaRegWrite(hnd, E502_REGS_ARM_TIME_CTRL, 1);
|
||||
2. Установка настроек захвата: X502_FpgaRegWrite(hnd, E502_REGS_PTP_LOCK_LIMIT, (ptp_limit_ns & 0xffff) | (ptp_req_hits << 16))
|
||||
2. Узнать состояние признака "захват PTP": X502_FpgaRegRead(E502_REGS_ARM_TIME_CTRL, &status);
|
||||
3. Инициализировать контекст для обработки меток времени: X502_tstp_init(&tstp_state, adc_freq, din_freq).
|
||||
4. Обработка меток времени из прочитанных данных с помощью X502_tstp_process_wrd(&tstp_state, cur_wrd), где cur_wrd - очередное слово полученное с помощью X502_Recv()
|
||||
|
||||
|
||||
Описание регистров PTP
|
||||
-------------------------------------------
|
||||
E502_REGS_ARM_TIME_CTRL
|
||||
|
||||
Address: 0x110
|
||||
|
||||
| Bit | `Name ` | Access | Description | Reset<br>Value |
|
||||
|---------|----------------------------|--------|---------------------------------------|-------------|
|
||||
| [1] | STATUS | R | признак "захват PTP"<br>1: признак "захват PTP" присутствует, условия захвата выплнены<br>0: признак "захват PTP" отсутствует | 0 |
|
||||
| [0] | ENABLE | RW| 1: добавлять метки времени в поток ввода<br>0: поток ввода без меток времени | 0 |
|
||||
|
||||
E502_REGS_PTP_LOCK_LIMIT
|
||||
|
||||
Address: 0x706
|
||||
|
||||
| Bit | `Name ` | Access | Description | Reset<br>Value |
|
||||
|---------|----------------------------|--------|---------------------------------------|-------------|
|
||||
| [31:16] | ENABLE | RW | Минимальное кол-во успешных синхронизаций | 0 |
|
||||
| [15:0] | STATUS | R | Допустимая рассинхронизация часов, +-нс/с | 0 |
|
||||
|
||||
|
||||
PTP-совместимое оборудование
|
||||
-------------------------------------------
|
||||
|
||||
Оборудование, совместная работа которого с E502-P1 по протоколу PTP была проверена.
|
||||
|
||||
Сервер времени: блок коррекции времени ЭНКС-2 производства ООО «Инженерный центр „Энергосервис“» (www.enip2.ru)
|
||||
Сетевой коммутатор с поддержкой PTP: блок L-VIMS-SWITCH производства ООО "Л КАРД" (www.lcard.ru)
|
||||
80
x502api-1.1.34/doc/x502api.tex
Normal file
80
x502api-1.1.34/doc/x502api.tex
Normal file
@ -0,0 +1,80 @@
|
||||
\documentclass[12pt,a4paper,titlepage]{report}
|
||||
\usepackage{lcard}
|
||||
\usepackage{doxygen}
|
||||
|
||||
\hypersetup{
|
||||
pdftitle = {Руководство программиста для модулей L-502 E-502 и E16},
|
||||
pdfauthor = {Борисов А.В.}
|
||||
}
|
||||
\ltextmargin{}
|
||||
\emergencystretch=75pt
|
||||
|
||||
\setcounter{secnumdepth}{3}
|
||||
\setcounter{tocdepth}{4}
|
||||
|
||||
\begin{document}
|
||||
\lcardtitlepage{Современные устройства сбора данных}{L-502/E-502/E16}{Руководство программиста}{1.1.13}{Сентябрь 2024}
|
||||
\lcardinfopage{Автор руководства}{\href{mailto:borisov@lcard.ru}{Борисов Алексей}}{Модули L-502 E-502 и E16}
|
||||
%----------------------------------------------------
|
||||
% Ревизии документа
|
||||
%---------------------------------------------------------
|
||||
\begin{longtable}{|m{0.18\linewidth}|m{0.18\linewidth}|m{0.54\linewidth}|}
|
||||
\caption{Ревизии текущего документа}\\\hline
|
||||
\textbf{Ревизия} & \textbf{Дата} & \textbf{Описание}\\\hline
|
||||
1.0.0 & 27.06.2012 & Первая ревизия данного документа \\\hline
|
||||
1.0.1 & 22.11.2012 & Добавлено описание использования библиотеки с программами на C\# и в LabView, добавлено описание установки для ОС Linux, а также описание функций для циклического вывода \\\hline
|
||||
1.0.2 & 20.02.2013 & Добавлена ссылка на исходные коды SDK. Описание установки пакетов для Linux вынесено в отдельный документ \\\hline
|
||||
1.0.3 & 16.02.2015 & Исправлена последовательность шагов для работы с модулем при синхронном потоковом выводе. Добавлено примечание о передачи массивов в качестве выходных параметров в LabView \\\hline
|
||||
1.1.0 & 02.06.2015 & Описание изменено в соответствии с изменениями, внесенными в библиотеку для поддержки модуля E-502 (введение общих и специализированных функций). Включено краткое описание различий модулей с программной стороны. Добавлены отдельные главы, описывающие настройку модуля при работе по Ethernet и поиск модулей в локальной сети. \\\hline
|
||||
1.1.1 & 06.07.2015 & Добавлено описание возможности ожидания завершения установки циклического сигнала, добавленной в версии 1.1.2 библиотеки. В разделе отличий модулей при описании наличия ARM-контроллера в E-502 указан путь для скачивания обновлений прошивки с рекомендацией обновления. \\\hline
|
||||
1.1.2 & 10.07.2015 & Добавлено описание нового алгоритма расчета максимального размера циклического сигнала для E-502 с прошивкой ARM 1.0.3 и выше \\\hline
|
||||
1.1.3 & 28.07.2015 & Добавлено описание функций X502\_SetExtRefFreqValue() и X502\_GetRefFreqValue() \\\hline
|
||||
1.1.4 & 29.06.2016 & Указано, что установка частоты вывода доступна в L-502, начиная с версии 0.5 прошивки ПЛИС. Рекомендация при синхронном выводе на ЦАП предворительно асинхронно установить начальные значения. Добавлено описание функций X502\_CheckFeature() и X502\_OutGetStatusFlags(). \\\hline
|
||||
1.1.5 & 03.08.2016 & Добавлено описание использования библиотеки в Visual Basic 6 \\\hline
|
||||
1.1.6 & 23.08.2016 & Изменена ссылка во вступлении на обновленное общее низкоуровневое описание программиста для L-502 и E-502 \\\hline
|
||||
1.1.7 & 16.11.2016 & Добавлено описание функций X502\_CalcAdcFreq(), X502\_CalcDinFreq(), X502\_CalcOutFreq() \\\hline
|
||||
1.1.8 & 27.02.2015 & При описании синхронного и асинхронного режимов работы добавлено описание ограничения их совместного использования при запуске синхронного ввода-вывода от внешнего сигнала \\\hline
|
||||
1.1.9 & 25.12.2019 & Добавлено описание функции X502\_IsOpened(). Добавлено общее описание процедуры открытия соединения с модулем, где в частности описана ситуация, когда соединение может остаться открытым, несмотря на возвращенную ошибку при его открытии \\\hline
|
||||
1.1.10 & 21.09.2020 & Исправление ссылок на исходные коды. Переименование lqmeasstudio в X502Studio \\\hline
|
||||
1.1.11 & 26.07.2022 & В информацию о модуле добавлены флаги для определения типа ЦАП и типа процессора \\\hline
|
||||
1.1.12 & 11.04.2024 & Для E502-P1 добавлено описание функций для работы с метками времени \\\hline
|
||||
1.1.13 & 30.09.2024 & Поддержка E16 со стороны x502api\\\hline
|
||||
\end{longtable}
|
||||
\newpage
|
||||
|
||||
\tableofcontents
|
||||
|
||||
|
||||
\chapter{О чем этот документ}
|
||||
\input{sect_about}
|
||||
\chapter{Установка и подключение библиотеки к проекту}
|
||||
\input{sect_setup}
|
||||
\chapter{Общий подход к работе с библиотекой}
|
||||
\input{sect_gen_descr}
|
||||
|
||||
|
||||
\chapter{Константы, типы данных и функции библиотеки}
|
||||
\input{constants}
|
||||
|
||||
\input{types}
|
||||
%\input{struct_l502_cbr_coef.tex}
|
||||
%\input{struct_l502_cbr.tex}
|
||||
%\input{struct_l502_info.tex}
|
||||
\section{Функции}
|
||||
\input{funcs_hnd}
|
||||
\input{funcs_open}
|
||||
\input{funcs_devrec}
|
||||
\input{funcs_config}
|
||||
\input{funcs_async}
|
||||
\input{funcs_streams}
|
||||
\input{funcs_eth_config}
|
||||
\input{funcs_eth_svc_browse}
|
||||
\input{funcs_dsp}
|
||||
\input{funcs_flash}
|
||||
\input{funcs_misc}
|
||||
\chapter{Метки времени (только для E502-P1)}
|
||||
\input{sect_tstp_descr}
|
||||
\input{tstptypes}
|
||||
\input{funcs_tstp}
|
||||
|
||||
\end{document}
|
||||
Reference in New Issue
Block a user