Российский производитель и разработчик сертифицированного измерительного оборудования с 1987 года


Вопрос про ReadData(); Delphi7

Вы не вошли.

 Поиск | Регистрация | Вход 

Константин
16.05.2011 22:20:07
#1

Гость

Вопрос про ReadData(); Delphi7

Вопрос в следущем, функцию ReadData() можно выполнять в цикле без START_ADC() и STOP_ADC()?
Или все-таки в цикле нужно останавливать и запукать АЦП.
А то в справке непонятно написано, что ReadData() должна использоваться совместно с START_ADC() и STOP_ADC().

Привожу свой код:
START_ADC();
REPEAT
BEGIN
    BytesTransferred := 0;
    pE440.ReadData(AdcBuffer, @DataStep, @BytesTransferred, @ReadOv);
         repeat
        if GetOverlappedResult(pE440.GetModuleHandle(), ReadOv, ReadBytesTransferred, FALSE) then break
        else if (GetLastError() <>  ERROR_IO_INCOMPLETE) then
          begin
       Application.MessageBox( //'Не могу собрать данные с платы!//', //'ОШИБКА!!!//', MB_OK + MB_ICONINFORMATION);
               break;
            end
    until pause;

//Тут я работаю непосредственно с данными полученнымы в буфере

END
until pause;

STOP_ADC();

Будет работать моя программа? (возможности проверить на данный момент нету)
или все-таки там где ReadData необходимо в цикле сначала Стартовать АЦП, а потом Останавливать..?

2. Немогу понять что означает @ перед переменными и что за переменная BytesTransferred := 0, правильно что она каждый раз в цикле обнуляется?

17.05.2011 12:01:38
#2

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: Вопрос про ReadData(); Delphi7

Константин,
@ - это оператор взятия адреса (@foo = указатель на переменную foo).
Так была описана функция при портировании ее интерфейса с C на Delphi - с указателями. Паскалевский синтаксис позволяет передавать параметры по ссылке через var, то есть на низком уровне
procedure set_zero_1(pdest: ^integer);
begin
  pdest^ := 0;
end;
практически то же, что
procedure set_zero_2(var dest: integer);
begin
  dest := 0;
end;

Но синтаксис вызова будет
var my_var: integer;
set_zero_1(@my_var);
set_zero_2(my_var);

Заодно - цикл repeat-until не нуждается в begin-end.
Возможно, не помешает какая-нибудь книжка про Delphi или просто Pascal.

Обнуление BytesTransferred тут в основном для красоты и защиты от ошибок программиста - если вызов WINAPI ReadFile вернет ошибку, то эта переменная, возможно, не будет установлена (останется то, что было), и ее значение не следует использовать. Этот нуль дает осмысленное значение "ничего не прочиталось".

Но вообще-то эта переменная тут вообще мусорная - при overlapped запросе количество реально переданных данных получается из GetOverlappedResult.

Ожидание завершения overlapped i/o делать опросом в цикле - не надо. Вообще-то в этом примере вполне подойдет GetOverlappedResult(..., TRUE) - с ожиданием завершения. А по-хорошему (с таймаутами и прочим) - делается WaitForSingleObject или WaitForMultipleObjects.

Также посмотрите вот эту ветку:
http://www.lcard.ru/forumthreads/9977

Стартовать в цикле ничего не надо, конечно. START_ADC и STOP_ADC - это команды прибору начать/закончить сбор данных и посылку их в компьютер. Это кран, открывающий воду, а ReadData - это ведро, которое подставляют под кран. Поэтому самый корректный способ - сначала ReadData без ожидания, потом START_ADC, потом по завершении чтения STOP_ADC. А если непрерывный поток данных больше, чем на один буфер, то надо использовать двойную буферизацию (два ведра: пока одно несут и выливают в бассейн, набирается второе).

А в черновом виде Ваша программа

17.05.2011 12:04:21
#3

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: Вопрос про ReadData(); Delphi7

(оторвалось)
А в черновом виде должно заработать, только надо не забыть установить параметры АЦП до запуска.

Константин
17.05.2011 13:42:33
#4

Гость

Re: Вопрос про ReadData(); Delphi7

Большое спасибо за ответ, а особенно за пример с ведром - все стало сразу понятно!

Константин
25.05.2011 16:49:19
#5

Гость

Re: Вопрос про ReadData(); Delphi7

1. Ещё возник такой вопрос, как мне отслеживать только один конкретный канал? Как например, сделано в Lgraph1.
Например, структура аp, как я понял, передает значение общих активных каналов в модуль, а не какие-то определенные каналы.

// установим желаемые параметры АЦП
    ap.ChannelsQuantity := 4;

2. Свою программу делал на основе примера ReadData, LusbApi.dll 2.0. Сменил драйвера на более новые, так же библиотеку на версию Lusbapi.dll 3.3 - программа уже при самом запуске, когда инициализируется - вылетает, подскажите, что именно мне начинать копать при переходе со старой библиотеки на более новую.

26.05.2011 12:56:35
#6

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: Вопрос про ReadData(); Delphi7

1. Не совсем понял вопрос. В структуре ADC_PARS описывается, какие каналы нужно опрашивать и в каком порядке они будут расположены в получаемых данных. Ненужные каналы просто не надо включать в таблицу.
Если опрашивается всего один канал, то ChannelsQuantity = 1 и заполняете один элемент ControlTable[0].
Если опрашивается несколько каналов, то разбирать полученные данные должна программа. Данные идут кадрами, т.е. если функция канала с логическим номером i от времени (точнее, от номера отсчета n) равна fi(n), то данные, прочитанные из модуля, будут в следующем порядке:
  f0(0), f1(0), ..., fN-1(0),
  f0(1), f1(1), ..., fN-1(1),
  ...
(здесь N = ChannelsQuantity)

2. Программу ОБЯЗАТЕЛЬНО собирать с lusbapi.h/.lib, соответствующих dll.
Посему очень советую держать правильную копию lusbapi.dll в каталоге с .exe файлом Вашего приложения.
Во всех примерах именно поэтому специально делается вызов GetDllVersion() и жесткая проверка на равенство.
Более того, в 2.x и 3.x есть отличия в прототипах некоторых функций (например, ReadData использует вспомогательную структуру), поэтому придется немного подправить исходник. Там все просто - прочитайте .pdf и .h и сразу разберетесь.

Константин
26.05.2011 19:54:38
#7

Гость

Re: Вопрос про ReadData(); Delphi7

Александр, ещё по 1му вопросу:
например, у меня данные поступают только по 12-му каналу. Следовательно мне нужно сделать:

ap.ChannelsQuantity := 1;
ControlTable[0] := 12-1;
верно ли я понял?

30.05.2011 15:41:44
#8

Сотрудник "Л Кард"
Здесь с 18.04.2014
Сообщений: 810

Re: Вопрос про ReadData(); Delphi7

В принципе да, только прочитайте в руководстве 1.3.2.3 формат логического номера канала (элемента ControlTable) - там не только номер канала, но и режим (дифференциальный или с общей землей), и коэффициент усиления (диапазон измерений).
12 - 1 = 11 это будет дифференциальный вход X12-Y12 с усилением x1 (диапазон -10В..+10В)