Меню

+7 (495) 785-95-25
sale@lcard.ru
sale@lcard.ru
Страницы 1
Тема закрыта
|
||||
|
отсчеты по иксу и время(е14-140)меня интересует пара вопросов
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)по 2)
Не думаю, что хорошая идея принимать данные по таймеру. Лучше принимать данные постоянно, т.е. с той скоростью, с которой они поступают. Для этого и служат асинхронные запросы (overlapped I/O). Но можно подобрать размер одного буфера под нужную порцию данных, тогда сама последовательность событий (events) по завершению запросов на чтение образует своего рода «таймер» (когда сбор данных запущен, разумеется). |
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)Александр Е как так Период частоты 10 кГц равен 100 мкс.?
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)>Не думаю, что хорошая идея принимать данные по >таймеру. Лучше принимать данные постоянно, т.е. с >той скоростью, с которой они поступают. Для этого >и служат асинхронные запросы (overlapped I/O). Но >можно подобрать размер одного буфера под нужную >порцию данных, тогда сама последовательность >событий (events) по завершению запросов на чтение >образует своего рода «таймер» (когда сбор данных >запущен, разумеется). Александр Е, можете продемонстрировать пример как это? не совсем понял как это реализовать программно |
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)WORD i;
// общее кол-во собираемых данных
// формируем необходимую структуру для сбора данных
это пример кода инициализации ,тут Overlapped присваивается &ReadOv; Мне бы пример какой -нибудь простой использования в асинхронном режиме |
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)>как так Период частоты 10 кГц равен 100 мкс.?
>не совсем понял как это реализовать программно
Или можете посмотреть bidir.cpp http://www.lcard.ru/download/e140-console-test.zip - там пример одновременной работы АЦП и ЦАП + передача команд между потоками. Обычно я рекомендую использовать очередь из двух буферов: сначала делается сразу два запроса (они встают в очередь в системе), потом по завершению одного запроса забираются данные и он поскорее вновь ставится в очередь. Таким образом обеспечивается, чтобы в ядре всегда висел хотя бы один запрос на чтение, и данные забирались из модуля в компьютер. Иными словами, из трубы льются данные, Вы берете два ведра, наполняете первое, тут же подставляете второе пустое и спокойно идете выливать воду, например, в файл на диске. Тем временем второе ведро уже начало наполняться, данные не проливаются на пол, и у Вас есть время. Про overlapped i/o советую прочитать в MSDN http://msdn.microsoft.com/en-us/library … 85%29.aspx и описания функций ReadFile, WriteFile, WaitForSingleObject, WaitForMultipleObjects, GetOverlappedResult, CancelIo. Поток чтения может быть чем-то вроде:
DWORD WINAPI ADC_Thread(LPVOID param)
hEvent[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
/* Ставим в очередь первый запрос чтения данных */
for (;;)
idx ^= 1;
if (!GetOverlappedResult(hDevice, &ov[idx], &TransferSize, TRUE))
} /* for (;;) */ CancelIo(hDevice);
return 0;
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)При написании многопоточных программ надо учитывать особенности синхронизации доступа к переменным.
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)мда, мало что понял, ну на этом спасибо, посмотрю.
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140) |
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)1) А как вызвать поток этот?
2) в том месте где у вас написано
к данным обращаться так? for (int i = 0; i < 100; i++) {
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)Александр Е, на builder c++ сделал. Посмотрите пожалуйста, правильно ли делаю?
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)- Не надо ставить на C точки с запятой после }, это лишнее.
Один раз в начале работы: hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); Перед каждым запуском потока:
По команде остановки:
То есть мы сигнализируем событие, по которому WaitForMultipleObjects() внутри потока мгновенно вывалится с WAIT_OBJECT_0 (см. описание WINAPI), и поток корректно завершится (выйдет из своей ACD_Thread()). А в это время основная программа, выставившая Event, этого и ждет (WaitFor... с параметром хендл потока - это ожидание завершения потока).
Еще чтение: http://forum.ixbt.com/topic.cgi?id=26:4468 Удачи! И советую уделить особое внимание изучению многопоточной синхронизации, если Вы раньше не писали программы с потоками. Это очень хитрая штука - потоки выполняются параллельно, ОС в любой момент (по таймеру) может прервать один поток после ближайшей машинной инструкции и дать управление другому потоку. Доступ к общим переменным и прочим объектам надо синхронизировать. Если Вы когда-нибудь писали программы с обработчиками аппаратных прерываний (хотя бы под DOS), то очень похоже. Только тут нельзя запретить прерывания, но можно использовать mutex-ы и критические секции.
|
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)Александр Е,
А что если в этом месте заполнять например массив какой нибудь, включать таймер и в таймере по тику выводить синхронизированно по времени обработанный сигнал? Так будет правильней? |
|||
|
||||
|
Re: отсчеты по иксу и время(е14-140)>если в этом месте заполнять например массив какой нибудь, включать таймер и в таймере по тику выводить синхронизированно 1) В принципе да, однако, как я писал выше, доступ к переменным из разных потоков тоже надо делать внимательно. Например, защищать критическими секциями, помечать как volatile и т.п. Иногда этого можно и избежать, тщательно спланировав последовательность доступа к данным, но тут надо очень внимательно вникать. 2) Однако действие «включить таймер» - это разве не обращение к объекту VCL? Тогда все равно нужен Synchronize. Я бы посоветовал использовать класс TThread и метод Synchronize, а в более общем случае (если нужно не только VCL) - да, можно сделать промежуточный буфер, а о поступлении данных лучше сигнализировать событиями (Event). А можно всю обработку сделать в том же потоке и даже в файл писать - чтение же уже само по себе асинхронное. P.S. Я Вас так упорно пугаю сложностью многопоточного программирования, потому что в нем наивный, как будто бы безобидный код может привести к сумасшедшим с точки зрения отладки (случайным и с трудом воспроизводимым) ошибкам. Например: /* thread A */
/* thread B */
В зависимости от процессора и компилятора код count++ может состоять из нескольких машинных инструкций: условно запишем
Допустим, что count = 100500, и после (2) операционная система прерывает выполнение потока A и передает потоку B, где выполняется count = 0. После чего управление вновь получает поток A и радостно пишет в count значение tmp = 100501.
Другой пример.
/* thread A */
/* thread B */
И оно никогда не выходит из цикла while, хоть убей. Оказывается, оптимизирующий компилятор (он не знает про многопоточность) проанализировал код потока B и увидел, что переменная flag всегда равна 0 (в теле цикла нет обращений к коду, меняющему flag). Он убирает лишний код - получается while (1) sleep(1);
В общем, для этого примера я бы посоветовал засунуть поток в TThread (это даже красиво: поток выглядит как экземпляр класса, код ThreadProc потока записывается как виртуальный метод Execute, ожидание завершения через WaitFor, доступ к элементам VCL через Synchronize...)
|
Страницы 1
Тема закрыта