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

Вниз

Чтение из COM-порта   Найти похожие ветки 

 
Sherev   (2002-09-18 17:31) [0]

Точно известно, что аппаратура посылает в порт 15 байт, а вот в программе принимаются только первые 8.
Подскажите, пожалуйста, в чем проблема.

Следующей процедурой осуществляется чтение из порта:

var Buf1: Array[1..20] of Byte;
read_bytes: DWORD;
j,i: Integer;
begin
repeat
FillChar(Buf1,SizeOf(Buf1),0);
ReadFile(hPort, Buf1, SizeOf(Buf1), read_bytes, nil);
if read_bytes>0 then begin
for i:=1 to SizeOf(Buf1) do
if Buf1[i]<>0 then
Form1.Memo2.Lines.Add(" Byte: "+IntToStr(Buf1[i])+
" Char: "+Chr(Buf1[i])+
" Bin: "+DecToBin(Buf1[i]));
end;
PurgeComm(hPort, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);


 
REA   (2002-09-18 18:02) [1]

А таймаут какой? Осторожнее с PurgeComm - он шлет нули


 
Пурген   (2002-09-19 03:50) [2]

Ты пробовал применять пурген на себе?
PurgeComm не шлет нули. Он очищает приемный (или передающий) буфер с полной потерей данных, так же как пурген очищает организм. В остальном, как указал REA (18.09.02 18:02) - имеют значение таймауты порта.
Но главное. В общем случае прием данных из СОМ-порта не стоит выполнять одним вызовом ReadFile.


 
Sherev   (2002-09-19 08:59) [3]

Timeout устанавливаю следующим образом:
{ Set ComPort Time outs }
TimeOuts.ReadIntervalTimeout := MaxDWord;
TimeOuts.ReadTotalTimeoutMultiplier := MaxDWord;
TimeOuts.ReadTotalTimeoutConstant := 10;
SetCommTimeOuts(hPort, TimeOuts);

и полная функция чтения данных из порта (в отдельном потоке)

function MainReadDataOne(Data: Pointer): Integer; stdcall;
var Buf1: Array[1..20] of Byte;
read_bytes: DWORD;
j,i: Integer;
begin
repeat
FillChar(Buf1,SizeOf(Buf1),0);
ReadFile(hPort, Buf1, SizeOf(Buf1), read_bytes, nil);
if j>=10000 then begin Form1.Memo2.Clear; j:=0; end;
if read_bytes>0 then begin
for i:=1 to 20 do
if Buf1[i]<>0 then
Form1.Memo2.Lines.Add(" Byte: "+IntToStr(Buf1[i])+
" Char: "+Chr(Buf1[i])+
" Bin: "+DecToBin(Buf1[i]));
end;
PurgeComm(hPort, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);
until not Form1.CBox1.Checked;
Result:=0;
end;

а это не связано с аппаратным буфером?


 
Veey   (2002-09-19 09:38) [4]

Есть хороший компонентик Async32. Принимает все, что посылает аппаратура. Проверял


 
Sherev   (2002-09-19 09:53) [5]

Компоненты не желательны... хотелось бы на API.


 
REA   (2002-09-19 10:43) [6]

> PurgeComm не шлет нули. Он очищает приемный (или передающий) буфер с полной потерей данных, так же как пурген очищает организм

Я тоже так думал, пока на осциллограф не посмотрел.
Он не во всех режимах шлет (PURGE_TXCLEAR только кажется).
Так что аналогия с пургеном очень к месту.

Sherev:
Может 10мс нехватает? Можно установить таймаут более чем на неск. байт, но не менее чем на 1 и читать пока читается в цикле, а буффер суммировать. Если некритично ко времени - просто увеличить таймаут. И еще: Checked может и не прокатить - события то не обрабатываются. И еще: раз данные в отдельном потоке используй синхронизацию при выводе в форму.


 
Sherev   (2002-09-19 11:43) [7]

Если убрать
PurgeComm(hPort, PURGE_TXABORT or PURGE_RXABORT or PURGE_TXCLEAR or PURGE_RXCLEAR);

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


 
Александр Спелицин ©   (2002-09-19 11:46) [8]

Все очень просто. Ваша программа / Железо / ОС / драйвер Com порта не знают (и не обязаны знать), сколько байт собирается послать некое устройство в порт.
ReadFile вернет управление, как только в буфере порта появятся какие-то данные. Если Вы говорите про 8 байт, значит так решила ОС. Это не означает, что про оставшиеся 7 она забыла, просто информация о том, что они помещены в буфер появится в следующий квант времени, отведенный системному потоку, который отвечает за работу с последовательными портами. 7 оставшихся байт Вы получите вызвав еще раз (или несколько раз) ReadFile.
А PurgeComm действительно очищает входящий буфер, вместе с 7-ю байт принятых следом. Используйте ее только при инициализации порта, а также перед отключением от него.


 
pasha676   (2002-09-19 12:11) [9]

Разберись с эвентами порта. Там есть всякие фенечки, типа читать порт только когда в нем набралось 15 символов или по приходу определенного символа. Ориентируйся на эти эвенты, а не на таймер.


 
Sherev   (2002-09-19 13:43) [10]

Так оно и было: принималось 8 байт, затем очищались приемный и передающий буферы вместе с последними 7-ю байтами...

Все большое спасибо! ;-)



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

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

Наверх




Память: 0.49 MB
Время: 0.026 c
1-59238
Fog
2002-11-05 20:00
2002.11.18
Научите...


14-59435
Сатир
2002-10-31 20:14
2002.11.18
Updates for Delphi 6


1-59213
irmantukas
2002-11-06 00:54
2002.11.18
StringGrid


1-59218
Lamak
2002-11-03 02:56
2002.11.18
Генератор


7-59452
Ал
2002-09-16 11:12
2002.11.18
Синхронизация часов РС с атомными часами