Форум программистов, компьютерный форум, киберфорум
C++/CLI
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.77/43: Рейтинг темы: голосов - 43, средняя оценка - 4.77
4 / 4 / 1
Регистрация: 11.11.2008
Сообщений: 66
1

Работа с Com портом

21.11.2008, 11:14. Показов 8086. Ответов 3
Метки нет (Все метки)

Добрый день!

Использую API функции работы с портом.
Есть девайс, протокол ModBus TRU передача работает нормально, а вот прием .
При первом запросе ответ получаю не полностью, а при втором запросе получаю остаток от первого ответа, дальше обмен идет в нормальном режиме. Помогите советом кто может.

Вот код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
OVERLAPPED OverlappedRW;
HANDLE COMport1;        //дескриптор порта
 
// Конструктор
uComPort::uComPort(void)
{
  pBufRead = gcnew cli::array<unsigned char>(256);   // буфер приема
  pBufWrite = gcnew cli::array<unsigned char>(256);  // буфер передачи
 
  // создать поток передачи данных
  ThreadRW = gcnew Thread( gcnew ThreadStart(this, &uComPort::ThreadWork ));
  ResetEventWrite = gcnew AutoResetEvent( false ); // будем слать по событию
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Открыть порт
bool uComPort::Open( TParamPort ^ p )
{
DCB dcb;                          // структура для общей инициализации порта DCB
COMMTIMEOUTS timeouts;  // структура для установки таймаутов
  // открыть порт
  COMport1 = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL );
  if ( COMport1 == INVALID_HANDLE_VALUE )
   {  //если ошибка открытия порта
      MessageBox::Show( "Ошибка открытя порта", "", System::Windows::Forms::MessageBoxButtons::OK, System::Windows::Forms::MessageBoxIcon::Error);
      return false;
   }
 
  //инициализация порта
  dcb.DCBlength = sizeof( DCB );
 
  //считать структуру DCB из порта
  if ( !GetCommState( COMport1, &dcb ) )    
   {  // если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
      MessageBox::Show( "Ошибка открытя порта", "", System::Windows::Forms::MessageBoxButtons::OK, System::Windows::Forms::MessageBoxIcon::Error);
      return false;
   }
 
  //инициализация структуры DCB
  dcb.BaudRate = 9600;
  dcb.fBinary = TRUE;
  dcb.fOutxCtsFlow = FALSE;
  dcb.fOutxDsrFlow = FALSE;
  dcb.fDtrControl = DTR_CONTROL_DISABLE;
  dcb.fDsrSensitivity = FALSE;
  dcb.fNull = FALSE;
  dcb.fRtsControl = RTS_CONTROL_DISABLE;
  dcb.fAbortOnError = FALSE;
  dcb.ByteSize = 8;
  dcb.Parity = NOPARITY;
  dcb.StopBits = ONESTOPBIT;
 
  //загрузить структуру DCB в порт
  if ( !SetCommState( COMport1, &dcb ) )
   { //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
     MessageBox::Show( "Ошибка открытя порта", "", System::Windows::Forms::MessageBoxButtons::OK, System::Windows::Forms::MessageBoxIcon::Error);
    return false;
   }
 
  //установить таймауты
  timeouts.ReadIntervalTimeout = 10; //таймаут между двумя символами
  timeouts.ReadTotalTimeoutMultiplier = 0; //общий таймаут операции чтения
  timeouts.ReadTotalTimeoutConstant = 0; //константа для общего таймаута операции чтения
  timeouts.WriteTotalTimeoutMultiplier = 0; //общий таймаут операции записи
  timeouts.WriteTotalTimeoutConstant = 0; //константа для общего таймаута операции записи
 
  //записать структуру таймаутов в порт
  if( !SetCommTimeouts( COMport1, &timeouts ) )
   { // если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
     MessageBox::Show( "Ошибка открытя порта", "", System::Windows::Forms::MessageBoxButtons::OK, System::Windows::Forms::MessageBoxIcon::Error);
     return false;
   }
 
  //установить размеры очередей приёма и передачи
  PurgeComm( COMport1,PURGE_TXCLEAR|PURGE_RXCLEAR );
  SetupComm( COMport1, 2000, 2000 );
 
 //сбрасываем счётчик байтов
  ulRxCounter = 0;
  ulTxCounter = 0;
 
  OverlappedRW.hEvent = CreateEvent(NULL, true, true, NULL);      //создать событие
  
  //установить маску события, прием символа
  SetCommMask( COMport1, EV_RXCHAR );  
 
  if ( ThreadRW->IsAlive == false )
  { // запустить поток чтения/записи
   ThreadRW->Start();
  }
return true;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//---------------------------------------------------------------------------------------
// поток приема передачи
void uComPort::ThreadWork( void )
{
COMSTAT comstat;    //структура текущего состояния порта используется для определения количества принятых в порт байтов
DWORD btr, temp, mask, signal;  //переменная temp используется в качестве заглушки
cli::pin_ptr<unsigned char> pW= &pBufWrite[0];
cli::pin_ptr<unsigned char> pR= &pBufRead[0];
 
  while ( true )
   {
     ResetEventWrite->WaitOne(); засыпаем и ждем сигнала
     //записать байты в порт
     if ( !WriteFile( COMport1, (LPCVOID *)pW, ulTxCounter, &temp, &OverlappedRW ) )
       { 
         signal = WaitForSingleObject( OverlappedRW.hEvent, INFINITE ); //приостановить поток до прихода байта
         if ( signal == WAIT_OBJECT_0 )
           {
              if ( GetOverlappedResult( COMport1, &OverlappedRW, &temp, true ) )
                eWriteData( TPort::ePort1 );     // генерим событие данные переданны
           } 
       }
     else 
       { // ошибка
       }
 
     //ожидать события приёма байта
     WaitCommEvent( COMport1, &mask, &OverlappedRW );
 
     //приостановить поток до прихода байта
     signal = WaitForSingleObject( OverlappedRW.hEvent, 100 );
     if (signal == WAIT_OBJECT_0)
      {    //если событие прихода байта произошло
         if ( GetOverlappedResult( COMport1, &OverlappedRW, &temp, true ) ) 
          { //проверяем, успешно ли завершилась
            if ( ( mask & EV_RXCHAR ) !=0 )
             { // если произошло именно событие прихода байта
                ClearCommError( COMport1, &temp, &comstat )
                btr = comstat.cbInQue;  // и получить из неё количество принятых байтов
                if(btr)
                 { // если действительно есть байты для чтения
                   ReadFile( COMport1, (LPCVOID *)pR, btr, &temp, &OverlappedRW );     //прочитать байты из порта в буфер программы
                   ulRxCounter = temp;
                   eDataRead( TPort::ePort1,  static_cast<unsigned char> (ulRxCounter) );   // генерим событие есть данные
                 }
             }
         }
     }
   else if ( signal == WAIT_TIMEOUT )
     { // вышел таймер нет ответа
        eDataRead( TPort::ePort1,  0 ); // генерим событие ошибка нет данных
     }
   }
}
C++
1
2
3
4
5
6
7
8
9
10
//---------------------------------------------------------------------------------------
// передать данные
bool uComPort::WriteData( unsigned long ulTxCounter1 )
{
   if ( !COMport1 )return false;
 
   ResetEventWrite->Set();
   ulTxCounter = ulTxCounter1;
return true;
}
Добавлено через 22 часа 29 минут 23 секунды
Спецы помогите!

Добавлено через 1 минуту 54 секунды
Спецы помогите
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.11.2008, 11:14
Ответы с готовыми решениями:

Работа с 60 портом
Тут Pascal кто нить помнит?? или знает? Program kyrsa4; uses crt_; var i,i1,i2:word;...

работа с com портом
Добрый день ув. форумчане , имею hex файл , его нужно отправить в ком порт , правда как это сделать...

Работа с COM портом
Доброго времени суток, уважаемые форумчане! Помогите разобраться с COM портом. Хотя бы с чего...

Работа с COM портом
Есть COM порт, там подцеплено оборудование. Как мне послать на него предположим #10 и считать все...

3
Гость2222
21.11.2008, 11:56 2
Это нормально.
Твой код должен готов собирать нужную последовательность из частями принятых данных.
Есть классы которые помогают выделять пакеты во входном потоке.
Здесь есть удобный класс TnrDataProcessor
http://www.deepsoftware.com/nrcomm
Комбайнёр
1597 / 695 / 77
Регистрация: 27.05.2008
Сообщений: 2,535
21.11.2008, 13:52 3
Подобную проблему решили с помощью таймаута, так как на передачу даных по загруженной сети проходит дольше
0
4 / 4 / 1
Регистрация: 11.11.2008
Сообщений: 66
23.11.2008, 17:50  [ТС] 4
Гость2222, спасибо за ссылку, как я понял это готовые классы работы с портом, но хочется раз и навсегда разобраться с этим геморроем, чтоб больше не выскакивал

Добавлено через 8 минут 42 секунды
WorkerM, о ком таймауте ты ведешь речь, ReadIntervalTimeout или таймаут функции WaitForSingleObject?
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.11.2008, 17:50

работа с com портом
добрый день ув. форумчане , у меня есть девайс который работает через com port , в девайсе хранится...

Работа с COM - портом
Не могу сделать чтобы, при работе с соm - портом возможно было выбирать как автоматические...

Работа с COM портом
Кто-нибудь делал это? В скором времени понадобится реализовать проект, в котором будет требоваться...

Работа с COM портом
Подскажите хорошую книгу или статью а еще бы исходник:) реализации работы с COM портом на C на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru