Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 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
4-59502
lety
2002-10-04 00:05
2002.11.18
завершить работу другой программы из своей


1-59106
jcrush
2002-11-08 06:15
2002.11.18
RichEdit - прозрачным?


1-59193
Мазут Береговой
2002-11-06 07:14
2002.11.18
как правильно открывать MS WORD в приложении Delphi, что бы он по


1-59205
Weare
2002-11-06 13:31
2002.11.18
Install InterBase5


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





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский