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

Ваш аккаунт

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

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

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

как считать данные с ком-порта?

13K
04 февраля 2008 года
MXM
22 / / 16.08.2006
привет!
вот кусок текста(почти весь)
но не могу прочитать данные записанные с ком порта(
за этапе чтения прога выснет (

на этапе записи 100% работает.
компилил на VC++2005

Код:
...
 main()
{
   char szCom[10];
    memset(szCom,0,sizeof(szCom));
    strcpy(szCom,"COM1");

    //устанавливаем порт
    hPortCom =CreateFile(szCom,GENERIC_WRITE|GENERIC_READ,0
                           ,NULL,OPEN_EXISTING,0,NULL);

    if( INVALID_HANDLE_VALUE == hPortCom )   exit(1) ;
    else printf("go get\n");        
     //Получаем текущие  установки
    if ( FALSE == GetCommState(hPortCom,&dcb) )
         { CloseHandle(hPortCom);
            exit(1);
                   }
              else printf("go build\n");
    //ZeroMemory(&dcb,sizeof(dcb));
    _getch();

    //Изменяем установки
    dcb.BaudRate=CBR_9600;  //  скорость CBR_57600
    dcb.ByteSize=8;        //число  бит  данных
    dcb.Parity=NOPARITY;   // бит  паритета
    dcb.StopBits=1;// стоп -бит
   
             if ( FALSE == BuildCommDCB(szCom,&dcb) )
             { CloseHandle(hPortCom);
       exit(1);
     }
              else printf("go set\n");
              //Устанавливаем  новое  состояние  порта
    if ( FALSE == SetCommState(hPortCom,&dcb) )
         { CloseHandle(hPortCom);
           printError('4');// ошибка
         }
                       else printf("go write\n");
    _getch();

    DWORD nb;
             char Mem[20] ;
             memset(Mem,'+',sizeof(Mem));
             strcpy(Mem,"123456789098765432");
    printf(" memory : %s\n",Mem);
            if ( FALSE == WriteFile(hPortCom, Mem, sizeof(Mem), &nb, NULL))
     { CloseHandle(hPortCom);
                  exit(1);
               }  
               else printf("go read_  \n");

    //---2------- чтение данных из сом порта в память ---------------        
            char buff[19];
            memset(buff,'-',sizeof(buff));
    nb=0;  
    if ( FALSE == ReadFile(hPortCom,buff,1,&nb,NULL) )
       { CloseHandle(hPortCom);
          exit(1);
       }
    else {  
           printf(" In buffer [ %s ]\n",buff);
                          printf("\n Close Com_Port \n ");
                 CloseHandle(hPortCom);// закрываем порт
         }
...
}
2.9K
04 февраля 2008 года
Ation
96 / / 27.07.2004
Программа не виснет, она ждет когда ReadFile вернет управление. Т.к. ты читаешь в синхронном режиме, то управление вернется когда из порта придет 19 байт.
87
04 февраля 2008 года
Kogrom
2.7K / / 02.02.2008
Меня интересует вопрос, какой смысл в использовании команды BuildCommDCB(szCom,&dcb) в данной программе?
479
05 февраля 2008 года
Ухух
142 / / 05.05.2006
Нужно задать данные в структуре COMMTIMEOUTS например так:
//Ставим до первого WriteFile

COMMTIMEOUTS ct;
ct.ReadIntervalTimeout=2;//Для 9600 так - это тот зазор между байтами который можно потерпеть , если устройство может передавать не сплошным потоком а с небольшими перерывами (контроллер может какое прерывание обрабатывать), то тут надо побольше поставить

ct.ReadTotalTimeoutMultiplier=3;

ct.ReadTotalTimeoutConstant=Time_out;//Тут ставим время в мс в которое должен уложиться отвечающий прибор, скажем 10 сек будет так 10000


ct.WriteTotalTimeoutConstant=0;//Чтобы не зависла функция WriteFile
ct.WriteTotalTimeoutMultiplier=0;//если в dcb будет выставлено управление потоком (а это может быть запросто от предыдущего приложения)

SetCommTimeouts(port,&ct);//Собственно ставим тайм ауты


После этого ваша программа может упроститься:
ReadFile(hPortCom,buff,18,&nb,NULL) ;


CloseHandle(hPortCom);

и далее ваш print


Ваш кусочек зависает тут:

....
if ( FALSE == ReadFile(...

Я столкнулся с тем, что ReadFile возвращает ВСЕГДА false (уточню , что вижу это в синхронном режиме под ME). Почему, я не понимаю. Это явная лажа и похоже что тут функция не работает как описана. А на msdn уже пишут тока про 2000 XP и Vista :))))) Впрочем у меня ив описании для 98 написано что вроде должна возвращать и true и false.

Лучше всего за ReadFile следите по значению nb, если там 0 - ничего не было. И если ваш цикл организовать с контролем nb - все будет работать. Только надо будет все же время считать а то ежели ничего и не прийдет - то и так тоже зависним. Время в таком случае можно считать по GetLocalTime или просто по инкременту переменной , но тут уж получится просто для страховки а не для точного измерения тайм аута.
87
05 февраля 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Ухух
Ваш кусочек зависает тут:
....
if ( FALSE == ReadFile(...


Если б тут ReadFile вернул FALSE, то программа бы закончила работу, а не зависла. Разве нет?
эх...стиль кода в этом месте мне не нравится. Я привык писать что-то типа if (!ReadFile(...

479
05 февраля 2008 года
Ухух
142 / / 05.05.2006
Точно. Значит программа вообще остается внутри функции. Тогда все равно нужно определить тайм ауты и вообще-то пройтись по всем полям dcb.
87
05 февраля 2008 года
Kogrom
2.7K / / 02.02.2008
Могу тут предположить, что автор темы командой memset(buff,'-',sizeof(buff)); уничножил нулевой байт, а затем командой printf(" In buffer [ %s ]\n",buff); сильно озадачил систему. Хотя точно не знаю - не силен я в c-строках, по возможности использую string...
479
05 февраля 2008 года
Ухух
142 / / 05.05.2006
Цитата: Kogrom
Могу тут предположить, что автор темы командой memset(buff,'-',sizeof(buff)); уничножил нулевой байт, а затем командой printf(" In buffer [ %s ]\n",buff); сильно озадачил систему. Хотя точно не знаю - не силен я в c-строках, по возможности использую string...


Там вроде в порядке.

Там целые дела до вызова CreateFile получаются. И все из-за того чтобы строчку "COM1" прописать в параметрах функции. Я просто в этом месте у себя делаю несколько if-ов на каждый номер порта и честно пишу в параметрах функции "COM1" и т.п. Думаю что по объему кода почти одинаково получается а приключений точно меньше.

и я бы еще в инициализацию dcb добавил бы вот такие строчки:


dcb.fNull=FALSE;//Нулевые байты не отбрасываем при передаче
dcb.fOutxCtsFlow=FALSE;//Не следим за CTS
dcb.fOutxDsrFlow=FALSE;//Не следим за DSR
dcb.fDtrControl=DTR_CONTROL_DISABLE;//Не управляем линией DTR
dcb.fDsrSensitivity=FALSE;//Не следим за DSR
dcb.fOutX=FALSE;//Не управляем потоком
dcb.fInX=FALSE;//Не управляем потоком
dcb.fRtsControl=RTS_CONTROL_DISABLE;//Не управляем линией RTS
dcb.fAbortOnError=FALSE;//Не выходим их функции при возникновении ошибки

87
06 февраля 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Ухух
Там целые дела до вызова CreateFile получаются.


Стал проверять своё предыдущее утверждение на опыте и обнаружил, что хоть команда printf(" In buffer [ %s ]\n",buff); выводит крокозябры из-за того что в строке buff затерт нулевой байт - к зависанию программы в большинстве случаев это не приводит.

Остается согласиться, что неправильно используется команда CreateFile. Только ошибка в установлении предпоследнего параметра. Вместо
CreateFile(szCom,GENERIC_WRITE|GENERIC_R,NULL,OPEN_EXISTING,0,NULL);
при синхронном доступе к порту надо б написать
CreateFile(szCom,GENERIC_WRITE|GENERIC_R,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

479
06 февраля 2008 года
Ухух
142 / / 05.05.2006
Я вот так пишу всегда:
port=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);

поскольку по "или" к предпоследнему аргументу ничего не пристегнуто это одинаковые записи.
87
06 февраля 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Ухух
Я вот так пишу всегда:
port=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
поскольку по "или" к предпоследнему аргументу ничего не пристегнуто это одинаковые записи.


Не понял, при чем тут "или", но, хотя в литературе (книга П.Агурова) пишут делать как я написал, вроде можно действительно 0 поставить ибо
http://msdn2.microsoft.com/en-us/library/aa363201(VS.85).aspx

Всё. Устал я тут копать теоретически, а нужного железа под рукой нет...

479
06 февраля 2008 года
Ухух
142 / / 05.05.2006
"или" потому что"
FILE_ATTRIBUTE_NORMAL
128
0x80
The file does not have other attributes set. This attribute is valid only if used alone.


Почитать лучше статью Олега Титова - там все расписано про порт.
13K
05 марта 2008 года
MXM
22 / / 16.08.2006
так и не работает программа :
записываю в ком порт 1 символ - все нормально
а читает 0 байт (
компилю в VS2005
479
05 марта 2008 года
Ухух
142 / / 05.05.2006
А попробуйте перед передачей вот такие строчки вставить (их вообще то всегда вставлять надо :) ):

SetupComm(port,1024,1024);//это когда порт настраиваете
PurgeComm(port,PURGE_TXCLEAR|PURGE_RXCLEAR);//а эту всегда перед передачей
13K
05 марта 2008 года
MXM
22 / / 16.08.2006
#include <windows.h>
#include <iostream>
#include <conio.h>
#include <winbase.h>
#include <winError.h>
#include <string.h>

using namespace std;

HANDLE hPortCom;
DCB dcb;//структура DCB для настройки ком-порта

int main()
{ cout<<"Start work ... \n";
_getch();

//устанавливаем порт
hPortCom =CreateFile("COM1",GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL);

if( INVALID_HANDLE_VALUE == hPortCom )
{ cout<<"Error : 1\n";
_getch();
return 1;
}
else cout<<"1 get\n";

//Получаем текущие установки
if ( !GetCommState(hPortCom,&dcb) )
{ CloseHandle(hPortCom);
cout<<"Error : 2\n";
_getch();
return 2;
}
else cout<<"2 build\n";

_getch();

//Изменяем установки

dcb.DCBlength=sizeof(DCB);
dcb.BaudRate=CBR_9600;
dcb.Parity=NOPARITY;
dcb.ByteSize=8;
dcb.StopBits=ONESTOPBIT;
dcb.EvtChar=EV_RXCHAR;
dcb.fParity=true;
dcb.fDtrControl=DTR_CONTROL_ENABLE;
dcb.fRtsControl=RTS_CONTROL_ENABLE;
dcb.XonChar=11;
dcb.XoffChar=13;
dcb.XonLim=0;
dcb.XoffLim=0;
dcb.fBinary=true;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SetupComm(hPortCom,1024,1024);//это когда порт настраиваете

//Устанавливаем новое состояние порта
if ( !SetCommState(hPortCom,&dcb) )
{ CloseHandle(hPortCom);
cout<<"Error : 3\n";
_getch();
return 3;// ошибка
}
else cout<<"3 write\n";
_getch();

COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout=2;
timeout.ReadTotalTimeoutConstant=1000;
timeout.ReadTotalTimeoutMultiplier=3;

timeout.WriteTotalTimeoutConstant=0;
timeout.WriteTotalTimeoutMultiplier=0;

SetCommTimeouts(hPortCom,&timeout);

DWORD wnb=0,rnb=0;
char Mem='S' ;

cout<<"4 Mem : "<<Mem<<'\n';

PurgeComm(hPortCom,PURGE_TXCLEAR|PURGE_RXCLEAR);//а эту всегда перед передачей

if ( ! WriteFile(hPortCom, &Mem, 1, &wnb, NULL))
{ CloseHandle(hPortCom);
cout<<"Error : 4\n";
_getch();
return 4;// ошибка записи!
}
else cout<<"5 read port \n";

PurgeComm(hPortCom,PURGE_TXCLEAR|PURGE_RXCLEAR);//а эту всегда перед передачей
char Buff='_';
if ( ! ReadFile(hPortCom,&Buff,18,&rnb,NULL))
{ CloseHandle(hPortCom);
cout<<"Error : 5\n";
_getch();
return 5;// ошибка чтения!
}
else {
cout<<"6 Buff : "<<Buff<<" bate= "<<rnb<<'\n';
cout<<"7 Close Com_Port \n ";
_getch();
CloseHandle(hPortCom);// закрываем порт
}

_getch();
return 0;
}
вот что написал но все равно не работает (
479
05 марта 2008 года
Ухух
142 / / 05.05.2006
PurgeComm(hPortCom,PURGE_TXCLEAR|PURGE_RXCLEAR);//а эту всегда перед передачей

- эту строчку перед передачей а не перед приемом!!!

И отключить на всякий случай управление потоком которое в dcb включено:
dcb.fDtrControl=DTR_CONTROL_ENABLE;
dcb.fRtsControl=RTS_CONTROL_ENABLE;

в заремаренном правильно было.

Удачи!
87
06 марта 2008 года
Kogrom
2.7K / / 02.02.2008
Так долго автор бьется над проблемой, что давно уж можно было работающий пример найти. Может быть, тут дело не в программе, а в железе. Вы уверены, что у вас есть какое-то устройство, отвечающее на запрос, подключенное к COM-порту? Ну, или хотя б закоротка между выводами передачи и приема?
479
06 марта 2008 года
Ухух
142 / / 05.05.2006
Посмотрел еще. Уберите все вокруг ReadFile. Чтобы там никаких if не было. Не работает у ReadFile возвращаемое значение , это функция всегда false возвращает , пользуйтесь только числом принятых байтов.

Вот чтобы правильно ее использовать напишу уточнение:
В синхронном режиме , когда мы в нее попадаем , то если нет ничего принятого , мы остаемся в этой функции до исчерпания времени timeout.ReadTotalTimeoutConstant

Дальше рассматриваем условия исходя из того что время timeout.ReadTotalTimeoutConstant еще не вышло:

Если пришел хотя бы один символ, то начинается счет времени между каждыми символами. Если с момента прихода очередного символа прошло времени более чем timeout.ReadIntervalTimeout, мы выходим из функции.

Если с начала появления первого символа прошло время более чем timeout.ReadTotalTimeoutMultiplier*(число запрошенных на прием символов ) или общее число пришедших символов превышает запрошенное для приема - выходим из функции.

Поэтому вокруг самой функции ничего лепить не надо - просто задав все времена аккуратно, мы практически весь прием организуем одной строчкой!
Если очень хочется не использовать такую организацию функции (она ориентирована на запрос-ответ) ,а хочется честный терминал сделать который бы все время бы показывал что в порту твориться, то эту функцию действительно можно зациклись с if , но смотреть приэтом число принятых символов. Как не ноль - читаем и добавляем в конец специально организованного массива (или строки , это как удобнее оперировать)Добавили - и опять крутимся дальше, при этом уже не надо буфер чистить . Если ноль - ничего не делаем - продолжаем крутиться.
87
06 марта 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Ухух
Посмотрел еще. Уберите все вокруг ReadFile. Чтобы там никаких if не было. Не работает у ReadFile возвращаемое значение , это функция всегда false возвращает , пользуйтесь только числом принятых байтов.



Можете дать ссылку на источник информации о том, что ReadFile всегда возвращает false? Или это утверждение основывается на личном неудачном опыте?

Тут прежде чем копать дальше, требуется уточнить с чем работает программа. Она может работать с:
1. Другим компьютером, где работает аналогичная программа.
2. Прибором, в котором записано ПО, которого мы не знаем.
3. Работа производится с дуплексным портом (например, RS-232, т.е. стандартным COM-портом) на который установлена закоротка с выхода на вход.

В последнем случае, можно для начала перестать колдовать с настройками и использовать только CreateFile, WriteFile, ReadFile. При этом в диспетчере устройств лучше убрать всякий аппаратный контроль.

479
07 марта 2008 года
Ухух
142 / / 05.05.2006
Цитата: Kogrom
Можете дать ссылку на источник информации о том, что ReadFile всегда возвращает false? Или это утверждение основывается на личном неудачном опыте?



Да, мне ни разу не удалось получить от ReadFile true. Осторожно уточню что в синхронном режиме. И это, кстатит, не единственный фокус в работе функции.

Если удалось получить true, напишите в каких условиях.

479
07 марта 2008 года
Ухух
142 / / 05.05.2006
Цитата: Kogrom

В последнем случае, можно для начала перестать колдовать с настройками и использовать только CreateFile, WriteFile, ReadFile. При этом в диспетчере устройств лучше убрать всякий аппаратный контроль.



Абсолютно согласен - все лишнее убрать надо и добиться работы.

87
08 марта 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: Ухух
Да, мне ни разу не удалось получить от ReadFile true. Осторожно уточню что в синхронном режиме. И это, кстатит, не единственный фокус в работе функции.

Если удалось получить true, напишите в каких условиях.



Я свою программу делал не для консоли. Но если написать для для консоли, то наверно будет что-то типа того (не проверял, так как нет нужного железа):

Код:
COMSTAT comStat;
DWORD codeError;
BYTE B = 0;
DWORD realRead;

while(B == 0)
{
    ClearCommError(comHandle, &codeError, &comStat);
    if (comStat.cbInQue) // есть полученные,
                                          // но не прочитанные данные
    {
        if (ReadFile(comHandle, &B, 1, &realRead, NULL))
        {
            cout << "ReadFile return true" << endl;
        }
        else
        {
            cout << "ReadFile return false" << endl;
        }
        cout << "codeError: " << codeError << endl;
        break;
    }
    cout << "Data not received" << endl;
    Sleep(1000);
}
13K
10 марта 2008 года
MXM
22 / / 16.08.2006
Цитата: Kogrom
Так долго автор бьется над проблемой, что давно уж можно было работающий пример найти. Может быть, тут дело не в программе, а в железе. Вы уверены, что у вас есть какое-то устройство, отвечающее на запрос, подключенное к COM-порту? Ну, или хотя б закоротка между выводами передачи и приема?



я старую сом-мышь (рабочию) подключаю.но ничего не работает - на чтение виснет.
может закоротку между выводами передачи и приема сделать ?

весь код
компилю в VS2005

Код:
#include <windows.h>
#include <iostream>
#include <conio.h>
#include <string.h>

using namespace std;

HANDLE port;
DCB dcb={0};//структура DCB для настройки ком-порта

int main()
{   cout<<"Start work ... \n";
    _getch();
    cout<<" go!\n ";
   DCB           *dcb;
   COMMTIMEOUTS  ct;
   HANDLE        port;
   DWORD         bc=0,  mask;

   char          buf_out[50]="_Test_string";
   char          buf_in[50]="\0" ;

   //с помощью функции HeapAlloc, выделяется и заполняется нулями область памяти для DCB
   dcb=(DCB*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DCB));
   dcb->DCBlength=sizeof(DCB);
   BuildCommDCB("baud=9600 parity=N data=8 stop=1",dcb);
   dcb->fNull=TRUE;

   ct.ReadIntervalTimeout=10;
   ct.ReadTotalTimeoutMultiplier=ct.ReadTotalTimeoutConstant=0;
   ct.WriteTotalTimeoutMultiplier=ct.WriteTotalTimeoutConstant=0;

   port=CreateFile("COM1",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
   
   SetCommState(port,dcb);
   SetCommTimeouts(port,&ct);
   PurgeComm(port,PURGE_TXCLEAR|PURGE_RXCLEAR);
   SetupComm(port,256,256);
   
   WriteFile(port,buf_out,(DWORD)strlen(buf_out),&bc,NULL);
   
   ReadFile(port,buf_in,(DWORD)strlen(buf_out),&bc,NULL);
   
   cout<<"buf_in="<<buf_in<<"\nbuf_out="<<buf_out<<"\n  "<<bc<<'\n';

   HeapFree(GetProcessHeap(),0,buf_in);
   
   HeapFree(GetProcessHeap(),0,dcb);//освобождение памяти из кучи
   CloseHandle(port);
   cout<<"end work.\n";
   _getch();
 return 0;
}
87
10 марта 2008 года
Kogrom
2.7K / / 02.02.2008
Цитата: MXM
я старую сом-мышь (рабочию) подключаю.но ничего не работает - на чтение виснет.


1. Вы не знаете, какое ПО зашито в мышь и на какой сигнал она должна ответить.
2. Скорее всего Windows сам захочет поуправлять мышью и не даст это делать вашей программе (хотя тут лучше уточнить у более опытных форумчан).
3. Насколько я помню, мышь типа Microsoft Mouse (и скорее всего других типов тоже) обменивается со скоростью 1200 бит/с. И это только один параметр, который не совпадает с вашими настройками.

Цитата: MXM
может закоротку между выводами передачи и приема сделать ?



Это было бы правильно для начала, но тут надо подходить с умом. В сравнительно новых компах наверно есть защита от коротких замыканих, но лучше сто раз подумать. Естественно, паять провод прямо к компу не следует - надо купить в магазине электроники разъем DB9 (мама, если не ошибаюсь) и паяться к нему.

479
10 марта 2008 года
Ухух
142 / / 05.05.2006
Работать с мышью несерьезно. Она берет питание с ножек порта и работает на передачу, т. е. вы должны от нее получать посылки при изменении ее состояния. Хотя на какие то команды она должна отвечать , но они используются машиной при включении для опознания кто воткнут в порт.
Если хотитите с мышью работать как с источником смгналов то она должна быть воткнута в порт только после старта операционной системы. При этом на нее должны быть правильно поданы напряжения питания.

А по хорошему если хотите разбираться с портом то подключите терминальную программу с другой стороны.
Как начальный шаг действительно можно 23 контакты перемкнуть. Но если начинаете с портом работать - работайте серьезно.
Я со многими программистами работал которые брались за общение с устройствами и как только начинают без паяльника и осциллографа работать - бесполезная трата времени - фигня получается. Поэтому все в чем есть обмен - только сам пишу.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог