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

Вниз

COM порт Win API. Проблемы с приёмом.   Найти похожие ветки 

 
PooHer   (2009-07-06 23:58) [0]

Умные люди, не бросьте в беде :)!
Совсем уже нет мыслей по чему такое может может произойти.
Создаю поток, в котором ожидаю приёма, но ничего не принимается (слушаю эхо). Передача проходит корректно (проверено).
procedure TComRead.Execute;
var
ComStat: TComStat;
dwMask, dwError: DWORD;
OverRead: TOverlapped;
Buf: array[0..20] of char;
dwRead: DWORD;
dd: string;
begin
FreeOnTerminate := True;
while not Terminated do
begin
dwMask:=0;
WaitCommEvent(CId, dwMask, @OverRead);
if dwMask = EV_RXCHAR then
begin
ClearCommError(CId, dwError, @ComStat);
dwRead := ComStat.cbInQue;
if dwRead > 0 then
begin
ReadFile(CId, Buf, dwRead, dwRead, @OverRead);
Form2.Panel1.Caption:=string(Buf);
end;
end; {while}
end;
end;

Всё упрощено, но по моему работать должно??


 
KilkennyCat ©   (2009-07-07 00:03) [1]

а проконтролировать выполнение условий?


 
KilkennyCat ©   (2009-07-07 00:10) [2]

И вообще, не маловат ли Buf?
И не стоит ли его очищать перед приемом?
И каким макаром выбран именно этот компорт, а не какой-нить еще, коих в системе дофига может быть? И где его инициализация?


 
PooHer   (2009-07-07 00:17) [3]


> И вообще, не маловат ли Buf?

Передаю и принимаю 1 байт.

> И каким макаром выбран именно этот компорт, а не какой-нить
> еще, коих в системе дофига может быть? И где его инициализация?
>

Инициализация в основном потоке, я хе говорил, передача происходит корректно.
> а проконтролировать выполнение условий?

Контроль убран уже от безысходности. С ним тоже ничего не работает.


 
KilkennyCat ©   (2009-07-07 00:19) [4]

А, я подумал, что имеется ввиду передача от того, кто передает...


 
Германн ©   (2009-07-07 02:21) [5]


> PooHer   (07.07.09 00:17) [3]
>
>
> > И вообще, не маловат ли Buf?
>
> Передаю и принимаю 1 байт.

Уууу. Опять "идиотская" синхронная работа с асинхронным по своей сути устройством.


 
KilkennyCat ©   (2009-07-07 03:38) [6]


> Германн ©

а с чего ты решил, что устройство асинхронно? только из-за протокола? Так это очень и очень спорно. Зависит от параметров синхронности. предположим, раз в год в течении суток. Что, асинхронность передачи в этом случае будет так заметна и как-то влиять?
Да и синхронность тут тоже совершенно не видна.


 
Вариант   (2009-07-07 08:01) [7]


> PooHer   (06.07.09 23:58)


> dwMask:=0;
> WaitCommEvent(CId, dwMask, @OverRead);

Я так понимаю, ты открыл порт указав флаг  FILE_FLAG_OVERLAPPED?
WaitCommEvent  у тебя использует OverRead и вернется не ожидая событий. Для ожидания событий надо вызвать  WaitForXXX функцию и/или GetOverlappedResult. И ты не проверяешь результат возврата WaitCommEvent (false/true + GetLastError  в случае ошибки). Может быть и ошибка, но указывающая , что идет  операция перекрытого ввода/вывода (это нормально) или другая.... И кстати, а SetCommMask ты вызывал?


 
Сергей М. ©   (2009-07-07 09:24) [8]

+ и опять те же грабли с обращением к VCL-контролам в доп.потоке


 
Сергей М. ©   (2009-07-07 09:32) [9]

Черным же по белому в справке написано:

If hFile was opened with FILE_FLAG_OVERLAPPED, the lpOverlapped parameter must .. point to a valid OVERLAPPED structure


> Контроль убран уже от безысходности


Вот если бы ты не убирал контроль результатов вызовов WinAPI-функций (сомневаюсь что он вообще у тебя был), то он бы сразу показал тебе, что WaitCommEvent() вернула отказ по причине очевидной инвалидности переданного ей параметра OverRead.


 
Сергей М. ©   (2009-07-07 09:34) [10]

То же самое касается вызова ReadFile - те же грабли в ту же точку приложения)


 
PooHer   (2009-07-07 11:19) [11]

Чтение изначально было такое:
procedure TReadThread.Execute;
var
ComStat: TComStat;
dwMask, dwError: DWORD;
OverRead: TOverlapped;
Buf: array[0..$FF] of Byte;
dwRead: DWORD;
begin
OverRead.hEvent := CreateEvent(nil, True, False, nil);
if OverRead.hEvent = Null then
raise Exception.Create("Error creating read event");

FreeOnTerminate := True;

while not Terminated do
begin
if not WaitCommEvent(cId, dwMask, @OverRead) then
begin
if GetLastError = ERROR_IO_PENDING then
WaitForSingleObject(OverRead.hEvent, INFINITE)
else
raise Exception.Create("Error waiting port event");
end;

if not ClearCommError(cId, dwError, @ComStat) then
raise Exception.Create("Error clearing port");

dwRead := ComStat.cbInQue;

if dwRead > 0 then
begin
if not ReadFile(cId, Buf, dwRead, dwRead, @OverRead) then
raise Exception.Create("Error reading port");
// В Buf находятся прочитанные байты
// Далее идет обработка принятых байтов
end;
end;
end;


Инициализация:
cId:= CreateFile(‘COM1’, GENERIC_READ or GENERIC_WRITE, 0, nil,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if cId= INVALID_HANDLE_VALUE then
raise Exception.Create("Error opening port");

if not GetCommState(cId, Dcb) then
raise Exception.Create("Error setting port state");

Dcb.BaudRate := CBR_9600;
Dcb.Parity := NOPARITY;
Dcb.ByteSize := 8;
Dcb.StopBits := ONESTOPBIT;

if not SetCommState(cId, Dcb) then
raise Exception.Create("Error setting port state");
if not PurgeComm(cId, PURGE_TXCLEAR or PURGE_RXCLEAR) then
raise Exception.Create("Error purging port");


 
Сергей М. ©   (2009-07-07 11:34) [12]


> Чтение изначально было такое


И что же подвигло тебя убрать проверки (пусть даже элементарные), фигурировашие в изначальном варианте ?


 
PooHer   (2009-07-07 11:43) [13]


> И что же подвигло тебя убрать проверки (пусть даже элементарные),
>  фигурировашие в изначальном варианте ?

Да то, что не работает ничего, замучался уже.
Во втором потоке программа крутится на ожидании звента, фактически данные отправляются и приходят в порт на 100%.


 
PooHer   (2009-07-07 11:47) [14]

Вообще, с Delphi только начинаю работать. Проектирую устройства на микроконтроллерах, пишу на АСМе. Встал вопрос о сопряжении МК и ПК. С Delphi последний раз общался лет 8 назад, забыл всё что знал, а знал мало :)
То, что данные уходят корректно проверено на железяке(МК).


 
PooHer   (2009-07-07 11:53) [15]

100% рабочий пример кода есть у кого? Пусть даже самый простой, без проверок(сам допишу). Просто мне кажется, что у меня какая-то ПРИНЦИПИАЛЬНАЯ ошибка в коде, но в виду отсутствия опыта, определить её не представляется возможным.
Можно, конечно, использовать готовые библиотеки, но очень хочется познать суть (Собственно по этому и пишу для МК на АСМе, а не на Си или Баскоме).


 
Сергей М. ©   (2009-07-07 12:07) [16]


> не работает ничего


И в этом, надо понимать, виноваты те самые проверки, которые ты убрал ?

Но ведь если изначально эти проверки тобой выполнялись, то значит ты же ожидал увидеть хоть какой-либо результат их "деятельности"  ?
А вместо ожидаемого сообщения "Error при попытке выполнения такой-то конкретно функции", ты, значит,  увидел сообщение "Не работает ничего ! Да ну их нафих эти проверки, все равно толку от них ноль !", потому и убрал проверки ? Я правильно логику твоих действий понимаю ?)


 
Вариант   (2009-07-07 13:00) [17]


> PooHer   (07.07.09 11:19) [15]

Как уже писали выше - этот вариант в [11] ближе к нормальному. Но и в нем нет SetCommMask - и какие тогда события ты хочешь отслеживать, если не указал это? ПРочитай про SetCommMask, поставь это в инициализации  порта и мне кажется что-то у тебя уже должно заработать.


 
Вариант   (2009-07-07 13:08) [18]

Кстати и про SetCommTimeouts тоже стоит почитать
Посмотри статьи на
http://www.delphikingdom.com/asp/section.asp?id=2
http://www.delphikingdom.com/asp/itemq.asp?Mode=1&ItemID=151
На том же сайте можешь поискать статьи
"Работа с портами ввода-вывода в DELPHI"


 
Вариант   (2009-07-07 13:19) [19]

И снова не все увидел, у тебя в [11] вообще нет обработки событий порта. Зачем тебе тогда WaitCommStatus? Ладно, почитай статьи....


 
PooHer   (2009-07-07 14:58) [20]

cId := CreateFile(PChar("COM"+IntToStr(Num)),GENERIC_READ or GENERIC_WRITE,0,nil,OPEN_EXISTING,
                   FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED,0);

SetCommMask(cId, EV_RXCHAR);

Вот так было.


 
Сергей М. ©   (2009-07-07 15:23) [21]


> PooHer   (07.07.09 14:58) [20]


Работа с маской событий вообще не нужна, равно как и Wait/ClearCommEvent
Равно как лишен смысла и overlapped ввод-вывод в доп.потоке, не делающем более ничего существенного, кроме собственно ввода-вывода из/в СОМ-порт


 
PooHer   (2009-07-07 15:50) [22]


> Работа с маской событий вообще не нужна, равно как и Wait/ClearCommEvent

Ну а как тогда работать?


 
Вариант   (2009-07-07 15:55) [23]


> PooHer   (07.07.09 15:50) [22]

Если не нужна специфика работы с портом и подробная расшифровка специфичных ошибок, то достаточно ReadFile и WriteFile. Но настройка порта нужна.


 
Вариант   (2009-07-07 15:57) [24]


> PooHer   (07.07.09 15:50) [22]

Статьий глянь, их много в интернете. На королевстве дельфи посмотри, ссылки давал


 
PooHer   (2009-07-07 18:51) [25]

Ну если просто вот так, в цикле сразу после передачи читать, должно работать?
(Не смеяться, это просто в качестве эксперимента.
procedure TForm2.Button4Click(Sender: TObject);

var
datas: string;
dwWrite: DWORD;
OverWrite: TOverlapped;
//WriteBytes: array of Byte;
//********************************
Buf: array[0..1] of Char;
dwRead, Read: DWORD;
i: integer;
//********************************
begin
//передача
datas:="a";
//dwWrite:=datas;
OverWrite.hEvent := CreateEvent(nil, True, False, nil);
if OverWrite.hEvent = Null then
raise Exception.Create("Error creating write event");

if (not WriteFile(cId, datas, SizeOf(datas),
dwWrite, @OverWrite))
and (GetLastError <> ERROR_IO_PENDING) then
raise Exception.Create("&#206;&#248;&#232;&#225;&#234;&#224; &#238;&#242;&#239;&#240;&#224;&#226;&#234;&#232;");

//********************************
//цикл приёма
for i:=1 to 2000 do
begin
dwRead:=10;
buf:="0";
ReadFile(cId, Buf, dwRead, Read, nil);
if Buf[0] <> "0" then
panel1.caption:=string(Buf);
end;
//********************************
end;


 
Вариант   (2009-07-08 06:48) [26]


> PooHer   (07.07.09 18:51) [25]

Не смеюсь.Нет, работать не будет. " В одну телегу впрячь не можно. Коня и трепетную лань." (с) А. С. Пушкин - это к тому, что есди ты используешь перектрытый ввод/вывод, открыл порт с флагом FILE_FLAG_OVERLAPPED, то и запись и чтение у тебя должны быть overlapped, а ты читать пытаешься синхронно.
И потом, если ты делаешь overlapped(перекрытую) операцию ввода/вывода, то где -то и как-то надо получить и результат ее завершения - это значит использовать или GetOverlappedResult и/или WaitForSingleObject или WaitForMultipleObjects. И ты не читал статей ?

Прочитай, выбери один какой-то вариант работы и доводи его до ума. А то у тебя тут куча вариантов, все разные. И ошибки появляются снова и не уходят из-за этого.


 
Сергей М. ©   (2009-07-08 10:26) [27]


> PooHer   (07.07.09 18:51) [25]


Зачем тебе overlapped ввод-вывод ?
Не нужен он тебе вообще.
Не усложняй себе жизнь.



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

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

Наверх




Память: 0.54 MB
Время: 0.012 c
15-1292362195
Юрий
2010-12-15 00:29
2011.03.27
С днем рождения ! 15 декабря 2010 среда


11-1232496242
Jon
2009-01-21 03:04
2011.03.27
FPC + KOL 2.88


2-1293713150
сергей2010
2010-12-30 15:45
2011.03.27
Подскажите...


15-1292323166
ixen
2010-12-14 13:39
2011.03.27
Setup и Firebird


2-1293339350
adminmax
2010-12-26 07:55
2011.03.27
ошибка при компиляции