Jump to content

    
Sign in to follow this  
uvw

Работа с СОМ портом

Recommended Posts

Здравствуйте, уважаемые!

Если кто сталкивался, помогите плизз. Долбаюсь уже 2 недели, и ничего не получается. Ситуация следующая: Есть некий контроллер и общается он с компьютером через RS232, в Win98 все работает, а вот Операционка Win2000

блокирует прямое обращение к портам. Мне подсказали прогу WinDriver для обхода этой проблемы... но опять-же, для LPT порта там есть стандартная заготовка, которая прекрасно работает... а о СОМ порте ни слова. Сразу оговорюсь, я не являюсь системным программистом и с железом дел никогда не имел... а тут пришлось ;) Искренне надеюсь на Вашу помощь. Заранее спасибо.

З.Ы.

Я впервые на этом форуме, и вполне возможно что запостил тему не совсем в тот раздел куда следовало бы.

ЗЗ.ЫЫ

Работать с этой штукой через CreateFile/ReadFile/WriteFile тоже не получается,

в ReadFile постоянно нули возвращаются, хотя команда сформирована верно и контроллером принята...

Share this post


Link to post
Share on other sites

Спасибо, но эту статью я недавно читал (на сайте www.rs232.ru) но, дело в том, что я никак не могу получить вообще ничего от контроллера... Я пробовал событийную модель(с помощью Overlapped и WaitCommEvent) с различными масками. Как поется, "Крикну, а в ответ - тишна"...

Тут вопрос стоит в прямом обращении к порту, а это возможно только при наличии соответстующего драйвера(во всяком случае, в Win200/XP и им подобным) Для написания драйвера, посоветовали использовать WinDriver...

Если кто ее использовал при работе с СОМ портом, подскажите плизз!!!

Share this post


Link to post
Share on other sites

Зачем такие сложности с прямым доступом если и через API всё прекрасно работает?

Вы видимо не очень тщательно разобрались. Я делал всё как сказано в статье и всё получилось и под Win98 и под Win2000.

Share this post


Link to post
Share on other sites

Могу привести исходник на паскале, присланный разработчиками железки, и свой, на С++ который пытаюсь переписать с паскалевской и перевести на WinAPI... Был бы благодарен, если укжете в чем ошибка...

Share this post


Link to post
Share on other sites

а вы попробуйте RxD и TxD закоротить, и отправить в порт чтенить.

если ничего не приниматься не будет - проверьте настройку DCB структуры, у меня было что в настройках проверку DSR , CTS , RTS или DTR отключить надо. давно было не могу сказать что точно. но история таже - в 98 работало, а в 2к нет. потом все пучком стало

 

О!!! нашел

 

fDsrSensitivity = NULL

Задает чувствительсть коммуникационного драйвера к состоянию линии DSR. Если это поле равно TRUE, то все принимаемые данные игнорируются драйвером (коммуникационный драйвер расположен в операционной системе), за исключением тех, которые принимаются при установленом сигнале DSR.

 

его в ноль,

 

fDtrControl = DTR_CONTROL_DISABLE и fRtsControl = RTS_CONTROL_DISABLE

По идее дожно зафурыкать. :)

Share this post


Link to post
Share on other sites

Фуухх, я уже окончательно запутался....

выкладываю настройку DCB

....
   DriverHandle = CreateFile (Com_Name, GENERIC_READ | GENERIC_WRITE,
                              0, NULL, OPEN_EXISTING, 0, NULL);

   if (DriverHandle == INVALID_HANDLE_VALUE) 
   {
       return (DriverHandle);
   }
   else
   {


       SetupComm (DriverHandle, 1024, 1024);

       GetCommState (DriverHandle, &Our_DCB);

       Our_DCB.BaudRate = DCB_Baud_Rate;
       Our_DCB.fParity = 0;
       Our_DCB.fOutxCtsFlow = 0;
       Our_DCB.fOutxDsrFlow = 0;
       Our_DCB.fDtrControl = DTR_CONTROL_ENABLE;
       Our_DCB.fDsrSensitivity = NULL;
       Our_DCB.fTXContinueOnXoff = 0;
       Our_DCB.fOutX = 0;
       Our_DCB.fInX = 0;
       Our_DCB.fErrorChar = 0;
       Our_DCB.fNull = 0;
       Our_DCB.fRtsControl = RTS_CONTROL_DISABLE;
       Our_DCB.fAbortOnError = 0;
       Our_DCB.ByteSize = 8;
       Our_DCB.Parity = NOPARITY;
       Our_DCB.StopBits = ONESTOPBIT;

       SetCommState (DriverHandle, &Our_DCB); 

       SetCommMask (DriverHandle, EV_TXEMPTY);
   }
....

А потом вызываю WriteFile... Данные приходят

на контроллер, причем правильно им "понимаются"... а при вызове

ReadFile нет ни одного быйта в очереди...

а вот что происходит в паскале...

{проверка контроллера на СОМ1}
{в первом байте -младший адрес, идентификатор}
{во втором байте-старший адрес, идентификатор, тип модуля, интервал ответа}
{третий байт (первый байт массива)-команда, идентификатор, интервал между ответами}
{если нужно передать данные, то следующие байт(ы) массива-данные}
{последний байт-контрольная сумма}

program com;
uses crt,dos;
var a,b,c,n,rs,P:byte;
   rs_old:pointer;
   r:registers;
   KS:word;
   I:byte;
const
   MAX:byte = 1;{1-если нет данных}  {команда---данные}
   BUF:array[1..10] of byte =        ($e0,      $8f,$8f,$8f,$8f,$8f,$8f,$8f,$8f,$8f);

label no_RX_,no_0,no_1,no_2,no_RX__,yes_key;

begin
KS:=0;
I:=0;

port[$3fb]:=$83;{без паритета}

port[$3f8]:=$06;
port[$3f9]:=$00;{19200бод}

port[$3fb]:=$03;
port[$3f9]:=$00;

port[$3fc]:=$03; {настроить преобразователь RS232/485 на передачу}

delay(500);

b:=0;
KS:=0;


{--ФОРМИРОВАНИЕ МЛАДШЕГО АДРЕСА с битами идентификатора, типа модуля--}
P:=$00;
KS:=P;
port[$3f8]:=P;{передать адрес младший}

no_0:
rs:=port[$3fd];
rs:=rs and 64;
if rs<>64 then goto no_0
else
{goto yes_key;}

{-------------------------------------}
{--ФОРМИРОВАНИЕ СТАРШЕГО АДРЕСА с битами идентификатора, типа модуля и интервала ответа--}
P:=$70;
KS:=KS+P;
port[$3f8]:=P;{передать адрес старший}

no_1:
rs:=port[$3fd];
rs:=rs and 64;
if rs<>64 then goto no_1
else
{goto yes_key;}


{----------------------------}
{--СФОРМИРОВАТЬ КОМАНДУ с битом идентификатора и интервалом между байтами ответа--}
{если необходимо передать данные- изменить индекс и уст. данные массива}
while (I < MAX) do
 begin
 I:=I+1;

P:=BUF[I];
KS:=KS+P;
port[$3f8]:=P;{передать команду И ДАННЫЕ}

no_2:
rs:=port[$3fd];
rs:=rs and 64;
if rs<>64 then goto no_2
else

 end;

{goto yes_key;}

{----------------------------}
{--СФОРМИРОВАТЬ К.С. с битом идентификатора--}
KS:=KS and $00ff;
P:=KS;
P:=P or $80;
port[$3f8]:=P;{передать КС}

port[$3fc]:=$02;{настроить преобразователь RS232/485 на прием}

write('com ');

{----------------------------}
{--ПРИНЯТЬ ВСЕ ПОДРЯД--}
no_RX_:
if memw[0:$41a]<>memw[0:$41c] then goto yes_key;
rs:=port[$3fd];
rs:=rs and 1;
if rs<>1 then goto no_RX_
else

a:=port[$3f8];a:=a and 127; {стереть, для вывода на экран, бит идентификатор}

write(a,';');

goto  no_RX_;

yes_key:

writeln(KS);
 end.
end

Может кто что подскажет....

Share this post


Link to post
Share on other sites

Our_DCB.fDtrControl = DTR_CONTROL_ENABLE;

 

этой настройкой ты запрещаешь прием данных на комп, если в не устройстве установлен DTR.

короче

1 попробуй сменить на DTR_CONTROL_DISABLE

2 посмотри осцилографом идет ли вообще сигнал?

 

еще

????SetCommMask (DriverHandle, EV_TXEMPTY);

 

после

SetCommState(port, &dcb);

я ставлю

SetupComm(port, 50, 50);

 

а перед записью и считыванием

//сброс буфера порта

PurgeComm(port, PURGE_RXCLEAR|PURGE_TXCLEAR);

 

 

то Sam: включи аську

Share this post


Link to post
Share on other sites

При установке DTR_CONTROL_DISABLE данные на контроллер не приходят

вообще... Хе, а осциллографа у меня нет ;) и наврядли когда-то появится...

я ж говорю, до этого никогда с "железом" не работал... по-сути дела, мне вооюще должно быть по-барабану что там за устройство, как оно работает и т.д. главное знать структуру посылки и структуру ответа, вот и все... а тем чем я занимаюсь, вообще должны, по-идее заниматься разработчики контроллера... а то, что это получается... там мы хотим работать, а там не хотим... ну, да ладно, это не важно... важно то, что оно должно работать, вот и оббиваю штукатурку головой ;) я уже облазил весь www.RS232.ru, перечитал кучу материала...но, никак не найду источник проблемы и метод устранения... с помошью WinDriver'a, тоже что-то не получается... хотя, код драйвера он генерит сам, главное настроить ресурсы устройства, а, потом, зарегить новый драйвер(удалив перед этим виндозный)... я в шоке.

а всем, кто принимает участие в обсуждении, большой :a14:

Share this post


Link to post
Share on other sites

я бы отправил тебе свои исходники, да у меня как раз все настройки в файле сохраняются

если надо могу отправить.

но это завтра....

засиделся я, пора домой.

Share this post


Link to post
Share on other sites
а вот что происходит в паскале...

...
port[$3fc]:=$03; {настроить преобразователь RS232/485 на передачу}
...
port[$3fc]:=$02;{настроить преобразователь RS232/485 на прием}
...

Не в этом ли дело? Может, в Вашем примере для Win преобразователь RS232/485 все время на передачу работает? Я, правда, назначение портов UART не помню, поэтому сходу не скажу, как то же самое можно сделать в WinAPI. Если нужно, могу выслать исходники на Паскале (Delphi), где у меня реализована связь с контролером (правда, используется только TxD и RxD, управления преобразователем нет).

Share this post


Link to post
Share on other sites

При порты в прикладной программе забудьте- это привелегия драйверов (vxd, sys). Вот хороший компонент для Дельфей с примерами. Работает на всем, и на USB переходниках тоже.

RS485 к сожалению под Виндой работает отвратительно. И переключать направление из программы корректно неполучится. Т.к. физическая передача в порт разнесена по времени с вызовом WriteFile, то даже ESC команды не переключат направление RS485 вовремя.

Если скорость постоянна, то направление можно переключать одновибратором в разъеме. Хотя более эффективное решение- маленькая схема на AT89c2051. Там же делали и опторазвязку.

cport_3.0.zip

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this