Форум: "Основная";
Текущий архив: 2003.09.01;
Скачать: [xml.tar.bz2];
ВнизНасколько цензурно выражение? Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.009 c