Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.008 c
3-1306
The X
2003-08-07 13:32
2003.09.01
Возможность создания многостраничного отчета без данных из БД


1-1447
kuchumovkv
2003-08-18 19:18
2003.09.01
Поле memo


6-1538
Hff
2003-06-25 14:51
2003.09.01
Как разобрать входящую почту ?


14-1661
wm.warning
2003-08-12 15:00
2003.09.01
PHP+MsSql


14-1646
Johnny Smith
2003-08-12 11:15
2003.09.01
Давайте поговорим о софтверных патентах. И их нарушении.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский