Форум: "Система";
Текущий архив: 2002.11.18;
Скачать: [xml.tar.bz2];
ВнизЧтение из 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;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.009 c