Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > COM порт не принимает 11h, 13h


Автор: ZPavel 1.4.2007, 18:53
Я пишу для микроконтроллеров. Но пришлось написать и программу для компьютера, хоть я почти и не понимаю в C++. Она должна передавать и принимать данный от микроконтроллера через COM порт. Вставил чужой код, который должен принимать данные с COM порта, а он не пропускает коды 11h и13h. Я понимаю, что это символы перевода каретки, но сам исправить положение не могу. Помогите, кто знает.

Код

//Функция таймера. По окончанию счета таймера производится считывание байтов из буфера
//порта до тех пор, пока число принятых байт не станет равным нулю.
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
unsigned char RecByte;  //Переменная для принятого байта
unsigned long int    NumByteRead;//Переменная для числа принятых байт. Заполняется функцией
                                 //ReadFile.
LPDWORD lpNumberOfBytesWritten=&NumByteRead;
LPVOID lpBuffer1=&RecByte;

NumByteRead=1;  //Записать какое-нибудь не нулевое значение


        while (NumByteRead)
        {//Считывать байты до тех пор, пока в буфере ничего не останется
ReadFile(hCom, lpBuffer1, 1, lpNumberOfBytesWritten, NULL);
         if (NumByteRead!=0)
            {
             if (RecByte == 255)    //проверить, может это пришеол ответ
                 Application->MessageBox("Передача завершена.", "Информация", MB_OK);
             else                   //нет, это не ответ
                 Memo1->Text = (Memo1->Text) + caserbyte(RecByte);
             }
        }
}

Автор: ZPavel 2.4.2007, 17:49
Помогите кто нибуть, пожалуйста.

Автор: pandrew 3.4.2007, 09:07
Вызов ReadFile можно записать проще:
Код

DWORD    NumByteRead;
ReadFile(hCom, (LPVOID)&RecByte, 1, &NumByteRead, NULL);

Цитата
а он не пропускает коды 11h и13h

Я не знаю, что делает функция caserbyte, возможно эти символы просто не отображаются в Memo.
Поставь breakpoint на ReadFile и смотри значение RecByte в отладчике.

Автор: ZPavel 3.4.2007, 19:34
Проверил 
Код

DWORD    NumByteRead;
ReadFile(hCom, (LPVOID)&RecByte, 1, &NumByteRead, NULL);


аналогично, RecByte значений 11h, 13h не получает.

Автор: pandrew 4.4.2007, 10:32
Цитата(ZPavel @  3.4.2007,  19:34 Найти цитируемый пост)
аналогично, RecByte значений 11h, 13h не получает. 
Может открыл файл как-то не так. Поверь на слово: спокойно можно гнать любые байты через RS232 в любом количестве.

Автор: _voron 5.4.2007, 12:45
Символы перевода каретки это 10 и 13, в шестнадцатеричном виде 0xA и 0xD, соответственно.

И вообще, читать данные лучше в асинхронном режиме.

Автор: Aline 5.4.2007, 12:57
А мы использовали компонент ApdComPort - просто и удобно работать с ним

Автор: Ivan. 7.4.2007, 12:44
Я пользуюсь компонентой TComPort. Визуальная компонента, событийная система, очень удобно.

Автор: ZPavel 7.4.2007, 21:13
Цитата(Aline @ 5.4.2007,  12:57)
А мы использовали компонент ApdComPort - просто и удобно работать с ним

а где его взять, этот Ваш ApdComPort

Автор: ZPavel 8.4.2007, 13:06
Цитата(Ivan. @ 7.4.2007,  12:44)
Я пользуюсь компонентой TComPort. Визуальная компонента, событийная система, очень удобно.

Поискал в интернете tcomport, и нашел только за деньги, что делать, где найти даром? И еще, есть ли, описание tcomport на русском?

Автор: pandrew 9.4.2007, 08:54
Цитата(ZPavel @  7.4.2007,  21:13 Найти цитируемый пост)
а где его взять, этот Ваш ApdComPort 

Как ищем: http://sourceforge.net/projects/tpapro/

Автор: ZPavel 11.4.2007, 18:26
Вот пример реботы с ком портом, можете посмотреть, маленький, говый проект. Я брал его за основу. И он не принимает эти коды, почему. Может кто-то поймет по реальному примеру.

Автор: ZPavel 13.4.2007, 19:02
Что, никто не в состоянии понять куда деваются 11h, 13h, в примере?

Автор: Usper 13.4.2007, 19:42
Если ты ничего не получаешь на ком порт, может быть туда ничего и не приходит?  smile А если серьёзно, что означет, что эти байты не приходят? Что ты ожидаешь от своего куска кода (в первом посте)?
Для тестирования подобного рода программ рекомендую связку программ Virtual Serial Ports Driver XP от Eltima Software (эмулирует пару или даже больше, если требуется ком портов, соединных нуль модемным кабелем) и какую нибудь терминальную прогу (я юзаю Com watcher Дмитрия Васильева) которая просто принимает и отсылает на ком порт байты.

Автор: ZPavel 14.4.2007, 07:01
Да я так и делаю, на 1 сом порт свою прогу, на 2 сом порт терминальную, и нуль-модемный кабель. Это именно моя прога не принимает 11н, 13н. Тот пример, что я выложил, я брал за основу его, он  на функциях api, ведет себя аналогично. Я думаю, что наверно никто раньше не обращал внимание на то, что функция API ReadFile, не пропускае парочку кодов. Или тогда дайте кто нибуть готовый пример, где пропускает все коды.

Автор: Usper 14.4.2007, 09:16
Еще раз: что ты ожидаешь, когда прийдут эти самые коды? Что делает функция caserbyte? TMemo не может отобразить 11h и 13h. ReadFile читает все, что приходит на ком порт.

Автор: black_priest 14.4.2007, 10:02
Пиши в файл все что ловишь, и там смотри, если по-другому у тебя не получается. Стопудова там увидишь, если передаешь. Файл естественно смотри в двоичном режиме, а не в текстовом. Или еще лучше редактором шестнадцатиричным. Не первый год занимаюсь подобными вещами и смею тебя уверить, что ком-порт передает и принимает любые коды. Просто не туда куда-то смотришь. 
Если хочешь, выложи именно свой исходник и расскажи как конкретно ты не видишь свои заколдованные символы, попробую помочь.

ЗЫ: Интересно, как люди с модемами в нет лазят, когда 
Цитата
функция API ReadFile, не пропускае парочку кодов
  smile 

Автор: Usper 14.4.2007, 11:38
Вот тебе простейший искуственный пример:

Код

HANDLE PortInit (char *PortName)
//функция инициализации порта, возвращает хэндл порта или INVALID_HANDLE_VALUE
//в случае ошибки
//в функцию пердать: номер порта (COM1 или COM2 или др, если есть др)
{
  HANDLE port;
  DCB dcb;
  BOOL fSuccess;
  COMMTIMEOUTS TimeOuts;
  TimeOuts.ReadIntervalTimeout = 1;
  TimeOuts.ReadTotalTimeoutMultiplier = 1;
  TimeOuts.ReadTotalTimeoutConstant = 1000;
  TimeOuts.WriteTotalTimeoutMultiplier = 2;
  TimeOuts.WriteTotalTimeoutConstant = 1000;
  port=CreateFile(PortName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
  if (port==INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
  fSuccess=GetCommState(port,&dcb);
  if (!fSuccess) return INVALID_HANDLE_VALUE;
  dcb.BaudRate=CBR_9600;
  dcb.ByteSize=8;
  dcb.Parity=EVENPARITY;
  dcb.StopBits=ONESTOPBIT;
  fSuccess=SetCommState(port,&dcb);
  if (!fSuccess) return INVALID_HANDLE_VALUE;
  SetCommTimeouts(port,&TimeOuts);
  PurgeComm(port, PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_RXCLEAR);
  return port;
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  HANDLE port;
  unsigned long BR;
  char buf_in;
  port=PortInit("COM5"); //открываем порт 5 (имя порта писать заглавными буквами)
  while (1==1) //бесконечный цикл !!!
  {
     ReadFile(port,&buf_in,1,&BR,NULL);
     if(BR!=0)  //если приняли не ноль байтов
     {
       if((unsigned char)(buf_in)==255) break;  //выходим из цикла если приняли 255
       Memo1->Lines->Add(IntToHex((unsigned char)(buf_in),2));
     }
     Application->ProcessMessages();
  }
}  



На форме кнопка и TMemo. Функцию PortInit() взял из своего проекта, что не нужно из нее выкинуть, что нужно - добавить. Пример рабочий - проверял.

Автор: Ivan. 15.4.2007, 12:14
Цитата(ZPavel @  8.4.2007,  13:06 Найти цитируемый пост)
Поискал в интернете tcomport, и нашел только за деньги, что делать, где найти даром? И еще, есть ли, описание tcomport на русском?

Пока искал наткнулся на новую версию:
http://kent.dl.sourceforge.net/sourceforge/comport/cport-3.10.zip
Возможны проблемы с компиляцией, Пишите объясню.
Библиотека с открытым кодом, в прошлых версиях нужно было немного подправить, в этой незнаю.

Автор: ZPavel 15.4.2007, 15:28
Все, ничего не понимаю. Выкладываю свой проект. только сильно не смейтесь, это моя первая программа на си++. В ней все работает, что мне нужно, только вот нет приема 11н и 13н. Кодировка для передачи символов у меня своя, мне так удобней. Под кодами 11 и 13 у меня находятся символы 'г' и 'д'. Чтобы включить прием текста, нужно нажать кнопку - читать текст, программа пошлет число 252 микроконтроллеру, а он в ответ передаст текст, во время приема, программа его перекодируети выводит в мемо. те для проверки нажимаете - перадать текст - и можете посылать коды на ком порт.

Автор: Usper 15.4.2007, 18:05
Да, сорри. Мой пример тоже не принимает 11h и 13h :( Перепутал системы счисления.

Автор: ZPavel 15.4.2007, 20:17
Вывод, функция API ReadFile, не пропускает коды 11h и 13h, грусно.

Автор: Usper 15.4.2007, 21:02
Погоди паниковать, возможно еще не все потеряно. Порой справку на предмет DCB. К сожалению мои знания английского не позволяют разобраться :(. 

Автор: Usper 16.4.2007, 19:14
У меня или глюки, или одно из двух  smile Сегодня мой пример работает  smile (то есть принимает 11h и 13h).

Автор: Anikmar 16.4.2007, 19:49
А может глюки? 11Н и 13Н принимает, а 0DH и 0AH нет?  smile 

Автор: Usper 16.4.2007, 20:31
Спокуха, все принимает. 11 в десятичной с.с. = 0Bh  smile 

Автор: Anikmar 16.4.2007, 21:02
Цитата(Usper @  16.4.2007,  20:31 Найти цитируемый пост)
Спокуха, все принимает. 11 в десятичной с.с. = 0Bh   

Да я прикололся - просто символы конца строки 0d и 0A  smile 
очень рад за вас, что мучения закончились.

Автор: korotkov 20.4.2007, 16:36
первое что пришло в голову: в структуре DCB установи fBinary = TRUE; а ты все-таки установи smile

что-то похожее было лет 8 назад ;) попытаюсь посмотреть архивы своих трудов ;)

Автор: korotkov 20.4.2007, 17:04
Код


// настройка и открытие COM порта
...
    FComControl = ccRS_485;
...
    SetComControl(FComControl);
    SetBaudRate(FBaudRate); //!!!!!! //SetBaud(FBaud);
    SetParity(FParity);
    SetStopBits(FStopBits);
    SetDataBits(FDataBits);

    SetFNull(false);

    FOpen = true;
...

void CACOMPort::SetComControl(TComControl Value)
{
  FComControl = Value;
  if( IsEnabled() ){
    GetCommState( FCommHandle, &FDCB );
    DWORD flags = DCB_BINARY;
    switch( FComControl ){
      case ccSoft: flags |= SOFT_FLOW;  break;
      case ccHard: flags |= HARD_FLOW;  break;
      case ccRS_485: flags |= RS485_FLOW;  break;
    }
    DWORD *tmp = (DWORD *)(&FDCB);
    tmp[2] = flags;
    SetCommState(FCommHandle, &FDCB);
  }
}


уже не помню почему было сделано так черех tmp ;) но ключевое тут DCB_BINARY.

а вообще есть подозрение что ихнеправильно смотришь или они не приходят, смотри отладчиком ...


Автор: Usper 20.4.2007, 21:07
fBinary и так по умолчнаию равно true.
Цитата

  FBinary - Режим двоичного обмена. Win32 не поддерживает недвоичный режим, поэтому данное поле всегда должно быть равно TRUE.

Взято здесь: http://www.firststeps.ru/

Автор: ZPavel 20.4.2007, 22:50
Так что делать? Я слежу за советами.

Автор: korotkov 21.4.2007, 12:48
>fBinary и так по умолчнаию равно true

поэтому я и написал: а ты всеравно поставь!

>Так что делать?

Работать!

Все пропускается, я вообще данные гонял в двоичном режиме, т.е. передавал float с контроллера как четыре байта на компе их выворачивал и склеивал. Данных было огромное количество, заполнялась база данных - и ничего все работает!

1. проверь а отправляются ли они с контроллера, влоть до того что шли только этих два символа в цикле, а осцилом смотри что уходит ...
2. принимаемые данные смотри в своем массиве или что там у тебя, смотри в двоичном режиме, а не текстовом ...
3. проверь соответствие количества отправленных и принятых байт, может ты просто их не видишь ;) т.е. смотришь средствами, которые не отображают символы ...

Автор: Ivan. 23.4.2007, 06:31
Смотрите о я нашел:
В структуре DCB есть поля XonChar и XoffChar равные по умолчанию соответственно 0x11 и 0x13 это не символы перевода каретки (10[0x0A] и 13[0x0D]) их то вы и не можите принять. эти поля связаны с флагами fOutX и fInX.

Сейчас буду разбираться дальше (зачем они нужны).

Автор: black_priest 23.4.2007, 11:44
2ZPavel: убери из строки LPCTSTR lpDef="2400,n,8,1,x" символ "x" в конце и будет тебе счастье, если только в этом причина. Действительно, как заметил Ivan, при установленных битах  fOutX и fInX символы  XonChar и XoffChar используются для программного управления потока, и поэтому не могут быть приняты. Если параметр fInX true, сигнал XoffChar посылается , когда входной буфер находится в пределах XoffLim байтов, а сигнал XonChar посылается в случае, если входной буфер находится в пределах XonLim байтов или является пустым. Параметр fOutX
определяет, используется ли управление потоком XON/XOFF  в течение передачи потока порту. Если параметр true, передача останавливается, когда получен сигнал XoffChar и возобновляется в случае если получен сигнал XonChar. Насчет твоего "x' в mode-строке читаем MSDN:
Цитата

For a string that ends with an x: 
fInX and fOutX are both set to TRUE
fOutXDsrFlow and fOutXCtsFlow are both set to FALSE
fDtrControl is set to DTR_CONTROL_ENABLE
fRtsControl is set to RTS_CONTROL_ENABLE

т. е. таким образом ты инициализирушь порт с ненужным тебе программным управлением потоком со всеми вытекающими последствиями. smile 

Автор: ZPavel 23.4.2007, 20:34
Ура, получилось. Убрал "x", и заработало. Большое, огромное спасибо. Пошел праздновать. smile 

Автор: black_priest 24.4.2007, 08:44
Слава Богу.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)