Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.09.01;
Скачать: CL | DM;

Вниз

Насколько цензурно выражение?   Найти похожие ветки 

 
AZ ©   (2003-08-17 07:46) [0]

Насколько корректен код для приема данных неопределенной длины из СОМ-порта:

..
var
Samples: array[0..65535] of byte;
HСomm, Readed: cardinal;
..
repeat
ReadFile(HComm,Samples,Length(Samples),Readed,nil);
k:=Readed;
Sleep(500);
until k=Readed;
ShowMessage("Принято байт: "+IntToStr(Readed));


Как ни странно, код работает, но есть сомнения...


 
Anatoly Podgoretsky ©   (2003-08-17 11:06) [1]

Не понятно зачем здесь цикл, все равно выражение выполняется только один раз?


 
AZ ©   (2003-08-17 11:29) [2]

Если данные достаточно длинные, то невозможно предусмотреть время задержки. (По подсчетам, до 2-х мин., скорость мала). В то же время, не хочется делать ожидание слишком длинным.


 
AZ ©   (2003-08-17 11:38) [3]

В том и фокус, что чтение производится, как минимум, 3 раза.


 
app ©   (2003-08-17 11:57) [4]

Не смешите
k:=Readed;
until k=Readed;


 
Юрий Зотов ©   (2003-08-17 12:02) [5]

И все же цикл при таком коде выполнится всего один раз (а затем сработает условие выхода в until). Тогда зачем он вообще нужен? Вот так - не будет ли то же самое:

ReadFile(HComm, Samples, Length(Samples), Readed, nil);
ShowMessage("Принято байт: " + IntToStr(Readed));

Еще - IMHO, это чтение блока в 65536 6айт (либо меньшего, если поступило EOF), а не "данных неопределенной длины". Если нужно читать порциями неопределенной длины, то перед чтением каждой порции сначала надо из того же потока прочитать саму длину этой порции. И как раз посылка нулевой длины может служить очень четким признаком EOF. То есть, протокол такой: длина+порция в цикле, а для завершения цикла вместо длины посылается ноль. В итоге получаем что-то типа этого:

// Для перенастройки просто меняем BuffSize. Длина порции должна
// посылаться последовательностью из SizeOf(TBaseType) байт,
// начиная с младшего (для x86).

const
BuffSize = 65536;
type
TBaseType = 0..(BuffSize - 1);
var
Buff: packed array[TBaseType] of Byte; // Строго packed!!!
Count: DWORD; // Кол-во реально заполненных байт в Buff

procedure FillBuff(FileHandle: HFILE);

function ReadData(var Data; Len: DWORD; Check: Boolean): Boolean;
// False - конец потока данных
var
Num: DWORD;
DataValue: TBaseType absolute Data;
begin
Win32Check(ReadFile(FileHandle, Data, Len, Num, nil));
Result := not Check or (DataValue <> 0);
if Result and (Len <> Num) then
raise Exception.Create("Ошибка приема")
end;

var
Len: TBaseType;
Over: Boolean;
begin
Count := 0;
while ReadData(Len, SizeOf(TBaseType), True) do
begin
Over := Len > BuffSize - Count;
if Over then Len := BuffSize - Count;
ReadData(Buff[Count], Len, False);
Inc(Count, Len);
if Over then
raise Exception.Create("Переполнение буфера приема")
end
end;

И последнее - это все же СИНХРОННОЕ чтение. Раньше Вы говорили об асинхронном.


 
AZ ©   (2003-08-17 12:27) [6]

Спасибо.
Все же осталось непонятным, почему если Sleep дать меньше и без цикла, то считывается обрубок данных. А если выкинуть, то вообще ничего.


 
Anatoly Podgoretsky ©   (2003-08-17 12:30) [7]

Как создан файл, похоже в ассинхронном режиме


 
AZ ©   (2003-08-17 12:50) [8]

Перед приемом выдается

WriteFile(HComm,Qry,1,Writed,nil);
//Qry - запрос на передачу

Файл создается девайсом.


 
Юрий Зотов ©   (2003-08-17 12:56) [9]

В FileCreate выставлен флаг FILE_FLAG_OVERLAPPED ?


 
Anatoly Podgoretsky ©   (2003-08-17 12:57) [10]

"Файл создается девайсом". Пока такое не возможно ReadFile( HComm, это создано тобой!!!


 
AZ ©   (2003-08-17 13:16) [11]

Естественно, CreateFile делаю я. А сами данные, т.е. собственно файл, делает девайс.

Инициализация порта

HComm:=CreateFile("COM2", GENERIC_READ or GENERIC_WRITE,
0, nil, OPEN_EXISTING, 0,0);
with Mode do begin
BaudRate:=4800;
ByteSize:=8;
Parity:=NOPARITY;
StopBits:=ONESTOPBIT;
Flags:=EV_RXCHAR or EV_EVENT2;
end;
SetCommState(HComm,Mode);

Далее в девайс передается запрос, в ответ он выдает данные.


 
VD602   (2003-08-17 20:59) [12]

Юрий Зотов © (17.08.03 12:02) [5]

Buff: packed array[TBaseType] of Byte; // Строго packed!!!

Юрий, не понял, а зачем packed? Код один и тот же генерируется, байты в памяти располагаются последовательно...


function ReadData(var Data;
DataValue: TBaseType absolute Data;

А нельзя было TBaseType(Data)? Чем это лучше?


 
Юрий Зотов ©   (2003-08-17 21:37) [13]

> VD602 (17.08.03 20:59) [12]

> байты в памяти располагаются последовательно...

Выравнивание элементов массива. В текущей версии компилятора оно одно, завтра возможно другое... А packed дает гарантию. Хотя, конечно, вряд ли завтра что-то изменится, но я предпочитаю писать код так, чтобы устранить потенциальную проблему навсегда, а не искать потом неизвестно откуда взявшуюся ошибку.

> А нельзя было TBaseType(Data)? )? Чем это лучше?

Можно, и ничем не лучше, и ничем не хуже.


 
VD602   (2003-08-17 22:02) [14]

Спасибо за разъяснения, премного благодарен :)


 
AZ ©   (2003-08-18 06:47) [15]

Задача решена.
Заставил девайс выдавать текстовые записи длиной по 20 байт с $0D $0A в конце непрерывным потоком.

Установил таймауты

with Timeouts do begin
ReadIntervalTimeout :=50;
ReadTotalTimeoutMultiplier :=1;
ReadTotalTimeoutConstant :=500;
WriteTotalTimeoutMultiplier :=0;
WriteTotalTimeoutConstant :=0;
end;
SetCommTimeouts(HComm,Timeouts);

Установил позаписное считывание.

CtB:=0;
Records:=0;
for i:=0 to 3000 do begin //3000 – максимально возможное число записей
Sleep(20);
ReadFile(HComm,Bf,20,Readed,nil);
if Readed=0 then
Break;
CtB:=CtB+Readed;
Inc(Records);
end;
ShowMessage("Принято байт: "+IntToStr(CtB)+#$0D+#$0A+
"Записей: "+IntToStr(Records));

Кстати, увеличение параметра Sleep приводит к затянутому ожиданию, но считывается верно.
Уменьшение – к пропуску данных.
Такой вот синхронно-асинхронный режим :)



Страницы: 1 вся ветка

Текущий архив: 2003.09.01;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.031 c
3-1326
BigError
2003-08-07 20:49
2003.09.01
MySQL - вопрос по libmySQL.dll (+)


4-1742
MMMaloy
2003-06-25 20:00
2003.09.01
Trey


1-1452
Cranium
2003-08-18 14:56
2003.09.01
Кто работал с ActionMainMenuBar?


1-1413
Nucl
2003-08-15 17:15
2003.09.01
Сохранение отображения дерева


14-1649
Serginio666
2003-08-12 16:51
2003.09.01
А работает ли Поиск на данном форуме????