Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

проблема с COM портом

16K
03 мая 2007 года
k_serg
11 / / 13.09.2006
Необходимо перенатраивать бит четности в процессе передачи
проблем не было на медленных машинах. на быстрых возникла проблема.
делаю так
Код:
SetCommMask( CommHandle_01,EV_TXEMPTY);
  DCBCommport_01.Parity=MARKPARITY;  
  SetCommState(CommHandle_01,&DCBCommport_01);
  TransMask=0;
  WriteFile(CommHandle_01,Transmit_01,1,&KolByte,&Ovr_w_01);
  Sleep(1);
  WaitCommEvent( CommHandle_01,&TransMask,&Ovr_w_01);
  if ((TransMask & EV_TXEMPTY)==EV_TXEMPTY )
 {
  DCBCommport_01.Parity=SPACEPARITY;
  SetCommState(CommHandle_01,&DCBCommport_01);
 // WriteFile(CommHandle_01,&(Transmit_01[1]),kol_pered-1,&KolByte,&Ovr_w_01);
  }


пока не добавляется задержка (закоментированный Sleep) осциллографом вижу , что бит четности не переустанавливается. т.е SPACEPARITY забивает предыдущий MARKPARITY.
программно все работает.
пробовал другие проверки
WaitForSingleObject,GetOverlappedResult - что байт ушел
GetCommState что перезапись произошла. программно все работает , на осциллографе пока нет задержки бита четности нет.
помогите разобраться с вопросом.
15K
03 мая 2007 года
Iceman
19 / / 20.04.2006
Сталкивался с подобной проблемой при программировании COM-порта в Линуксе. Дело в том, что у порта есть буфер вывода, куда попадают все байты на отправку и ждут там своей очереди быть посланными. При изменении настроек COM-порта (например, настройки паритета) эти изменения применяются к БУФЕРУ, а не к БАЙТУ (символу) в нем. Поэтому происходит примерно следующее - ты посылаешь один символ с паритетом MARK, потом сразу второй с паритетом SPACE. При переключении настроек паритетов первый символ не успевает отправится, он еще в буфере, и все изменения применятся и к нему, т.е. он тоже будет со SPACE'ом.
А когда ты используешь задержку - все ок, первый отправился, из буфера ушел, поменялись настройки, второй ушел - и т.д.
При использовании стандартного драйвера COM-порта в Линуксе у меня было несколько вариантов решения проблемы. Дело в том, что такое поведение порта можно несколько изменить, например:
1. при изменении настроек все текущие байты в буфере удалить, а потом применять новые настройки (навряд ли этот вариант тебе подойдет :) )
2. при изменении настроек сначала дождаться, пока все содержимое буфера уйдет, а потом применять новые настройки - скорее всего этот вариант тебя устроит.
У меня это настраивалось программно настройками порта. В чем и как программируешь ты, я не знаю, поэтому читай доку к своим средствам программироания.

ЗЫ. При использовании второго варианта есть одно но - если настройки меняются часто, то возможна большая (относительно) задержка между байтами, которая связана с временем ожидания опустошения буфера каждый раз при изменении настроек - меня, например, это никак не устраивало, пришлось писать свой драйвер.
16K
03 мая 2007 года
k_serg
11 / / 13.09.2006
Цитата: Iceman
2. при изменении настроек сначала дождаться, пока все содержимое буфера уйдет, а потом применять новые настройки - скорее всего этот вариант тебя устроит.


не просто устроит, а так и делается. но , к сожалению, ни к чему хорошему эта проверка не приводит.
EV_TXEMPTY проверяется был ли передан последний символ из буфера и программно буфер чист.
ClearCommError проверял число символов в передающем буфере. было =0
GetOverlappedResult проверял количество переданных и =1.
и только после этого менялся бит четности.

15K
03 мая 2007 года
Iceman
19 / / 20.04.2006
Вот нашел одну любобытную статейку - http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1126 . Там, среди всего прочего, написано, что проверять только по EV_TXEMPTY пустоту буфера нельзя, так как это событие показывает, что в буфер можно дописать байты, а не то, что он пуст.
И вот еще кое-что с того же сайта - http://www.delphikingdom.com/asp/answer.asp?IDAnswer=41030, возможно, станет полезным...
16K
04 мая 2007 года
k_serg
11 / / 13.09.2006
посмотрел , спасибо за ссылки.про EV_TXEMPTY интересно . но начинал я с кода практически повторяющего MSDN. а уже потом начались эксперименты. к нему и вернулся теперь.
Код:
GetCommState(CommHandle_01,&DCBCommport_01);
DCBCommport_01.Parity=MARKPARITY;
SetCommState(CommHandle_01,&DCBCommport_01);

if (!WriteFile(CommHandle_01,Transmit_01,1,&KolByte,&Ovr_w_01))
   if (GetLastError() != ERROR_IO_PENDING ) {   Memo1->Lines->Add("ошибка записи");}
    else
    {
     dwait=WaitForSingleObject(Ovr_w_01.hEvent,1);
     switch (dwait)
    { case  WAIT_OBJECT_0 :
       {
         if (!GetOverlappedResult(CommHandle_01,&Ovr_w_01,&Kols_01,false))
           {
              if (GetLastError() != ERROR_IO_INCOMPLETE ) Memo1->Lines->Add("незавершение записи");
           }
         else{
             if (Kols_01==1){
                //Sleep(1);                
                DCBCommport_01.Parity=SPACEPARITY;
                SetCommState(CommHandle_01,&DCBCommport_01);
               


                            }
             }
       break;
       }
     case WAIT_TIMEOUT :{
                break;
                        }
     case WAIT_FAILED :  {  
                     //   break;
                         }
   } //switch
   }  //else


ResetEvent(Ovr_w_01.hEvent);


так вот там , где стоит sleep это место окончания операции записи. а на самом деле это не так. без задержки не работает.
по ходу исследования с различными портами возник еще один вопрос : про переобозначении порта для СОМ1..СОМ9 все переобозначается и работает. а вот при СОМ10 и более
порт не открывается по ERROR_FILE_NOT_FOUND
CommHandle_01 = CreateFile("COM12",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED ,NULL);
if (CommHandle_01 == INVALID_HANDLE_VALUE )
{
LastError=GetLastError();
if (LastError==ERROR_FILE_NOT_FOUND) {}
}
как с этим пробороться?
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог