Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Программирование COM порта
Форум разработчиков электроники ELECTRONIX.ru > Цифровая обработка сигналов - ЦОС (DSP) > Алгоритмы ЦОС (DSP)
Yuriy_Rus
Уважаемые, уже котрый день занимаюсь программированием GPRS модема по COM и не могу понять, что за фигня...
Загружаю комп втыкаю модем, запускаю прогу - всё виснет, соединения - нет.
Закрываю прогу. Запускаю гипертерминал. Ввожу любую команду - всё ништяк, устройство отвечает.

Закрываю гипертерминал. Запускаю прогу, и всё уже пашет без проблем, только установка настроек порта(SetCommState(Port, &dcb) странно работет (то работает, то не работает, но восновном не работает).
Так вроде в DCB всё указываю что надо для работы устройства.
Исходник открытия и настройки порта:

if(PortOpen == 1) return false;

DCB dcb;
COMMTIMEOUTS ct;
unsigned long int bc;

//dcb = (DCB*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
//BuildCommDCB("baud = 9600 parity = N data = 8 stop = 1", &dcb);

dcb.fBinary = TRUE;
dcb.BaudRate = 9600;
dcb.fParity = NOPARITY;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;


dcb.fNull = TRUE; //Èãíîðèðîâàíèå íóëåâûõ áàéò ïðè ïðè¸ìå
dcb.fOutX = FALSE;
dcb.fInX = FALSE;

ct.ReadIntervalTimeout = D_TimeOutValue;
ct.ReadTotalTimeoutMultiplier=ct.ReadTotalTimeoutConstant = D_TimeOutValue;
ct.WriteTotalTimeoutMultiplier=ct.WriteTotalTimeoutConstant = D_TimeOutValue;

Port = CreateFile(D_COM_Name, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

if(Port == INVALID_HANDLE_VALUE)
{
Application->MessageBox(D_ComOpenError, D_Error, MB_OK+MB_ICONERROR);
ComPortClose();
return FALSE;
}

if(!SetCommState(Port, &dcb))
{
// Application->MessageBox(D_ComOpenError, D_Error, MB_OK+MB_ICONERROR);
// ComPortClose();
// return false;
}

if (!SetCommTimeouts(Port, &ct))
{
Application->MessageBox(D_ComOpenError, D_Error, MB_OK+MB_ICONERROR);
ComPortClose();
return FALSE;
}
else PortOpen = 1;

PurgeComm(Port, PURGE_RXABORT);
PurgeComm(Port, PURGE_TXCLEAR|PURGE_RXCLEAR);

Подскажите, пожалуста, как решить эту проблему. help.gif
Yuriy_Rus
Предполагаю, что дело в настройках порта, но каких именно - чёрт его знает...
jorikdima
У меня была аналогичная проблемма. Только устройство (не GPRS модем) и прога не висли, а просто не работали как надо. При этом существовала прога от производителя девайса с которым я хотел соединиться. Так вот если загрузить комп, и включить мою прогу, то не работало. Если после этого (или после включения компа) загрузить прогу от производителя, то она работает. И самое интересное, что работает потом и моя, но только до перезагрузки.
Ситуация оказалась следущая. DCB имеет дочерта параметров (около 25). Так вот, моя прога настраивала некоорые параметры, а некоторые оставляла по-умолчанию, в частности количество стоповых битов. Эти настройки сохраняются, даже после завершения проги, вплоть до перезагрузки. И вышло следующее. Мой девайс использовал 8 бит данных и 2 стоповых. А Винда изначально (у меня по крайней мере) давала 7 бит данных и один стоповый. Проверить это можно после перезагрузки Винды, запуска проги и в отладчике просмотреть поля DCB. И я не изменял эти параметры в своей проге! Поэтому моя прога не работала с девайсом. Затем я запускад прогу производителя она конфигурировала порт как надо для этого девайса. После закрытия проги настройки сохранялись и их можно было просмотреть опять запустив в отладчике прогу. Поэтому моя прога тоже после этого работала.
Извиняюсь что так длинно. Короче, посмотри на поля структуры DCB после загрузки Винды и после запуска ГиперТерминала. И сравни.
Палыч
Ошибка имхо в том, что Вы не заполняете ВСЕ поля структуры dcb. Если Вы не желаете изменять их(эти поля), то вызовите функцию GetCommState - она их заполнит, а затем измените те, что Вам нужны на необходимые значения.
Alexsys
А на какой строчке прога подвисает??? Попробуйте её пошагово выполнить.

Я DCB заполняю следующим кодом:

Код
// настраиваем выбранный COM-порт
ZeroMemory(&dcb,sizeof(DCB));
dcb.DCBlength=sizeof(DCB);  // !!!!!!!!!
dcb.BaudRate=CBR_38400;
dcb.fBinary=TRUE;
dcb.fParity=FALSE;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb.fDtrControl=DTR_CONTROL_DISABLE;
dcb.ByteSize=8;
dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT;


Подобной проблемы у меня никогда небыло. Прога иногда подвисала при некорректном выключении прибора.
Yuriy_Rus
Цитата(Alexsys @ Aug 30 2006, 14:09) *
А на какой строчке прога подвисает??? Попробуйте её пошагово выполнить.

Я DCB заполняю следующим кодом:

Код
// настраиваем выбранный COM-порт
ZeroMemory(&dcb,sizeof(DCB));
dcb.DCBlength=sizeof(DCB);  // !!!!!!!!!
dcb.BaudRate=CBR_38400;
dcb.fBinary=TRUE;
dcb.fParity=FALSE;
dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb.fDtrControl=DTR_CONTROL_DISABLE;
dcb.ByteSize=8;
dcb.Parity=NOPARITY;
dcb.StopBits=ONESTOPBIT;


Подобной проблемы у меня никогда небыло. Прога иногда подвисала при некорректном выключении прибора.


Можете подробнее рассказать про эти поля:

dcb.fRtsControl=RTS_CONTROL_DISABLE;
dcb.fDtrControl=DTR_CONTROL_DISABLE;

Насколько я знаю, fRtsContro задает режим управления потоком для сигнала RTS, а fDtrControl задает режим управления обменом для сигнала DTR. Но что это за сигналы я "в душе" не знаю...
Yuriy_Rus
Цитата(Alexsys @ Aug 30 2006, 14:09) *
А на какой строчке прога подвисает??? Попробуйте её пошагово выполнить.



На отправке-приёме команды...
Alexsys
2 Yuriy_Rus

Я не совсем понял, прога виснет при попытке послать информацию в COM порт.

RTS - сигнал запроса передачи. Активен во все время передачи.
CTS - сигнал сброса (очистки) для передачи. Активен во все время передачи. Говорит о готовности приемника.
DTR - сигнал готовность к приему
DSR - сигнал готовности данных

Эти сигналы используются для аппаратного управления потоком (RTS-CTS or DTR-DSR handshake). Подробнее посмотри в книжке Гука "Интерфейсы ПК". Флаги RTS_CONTROL_DISABLE и DTR_CONTROL_DISABLE отключают использование аппаратного управления потоком.

Возможна проблема твоя в том, что ты не отчищаешь содержимое структуры DCB перед её заполнением. Я это делаю строкой ZeroMemory(&dcb,sizeof(DCB));
_Andu_
У меня вот такая процедура открытия порта для COM порта.
И все работает только не для GPRS модема а для своих целей.
BOOL CSerial::Open( LPVOID dr )
{
BYTE ByteSize = 8; // number of bits/byte, 4-8
BYTE Parity = 0; // 0-4=no,odd,even,mark,space
BYTE StopBits = 0; // 0,1,2 = 1, 1.5, 2

CDriver *driver = (CDriver *)dr;
m_driver = dr;
int nPort = driver->kanal.port;
DWORD nBaud = driver->kanal.speed;
ByteSize = driver->kanal.ByteSize;
Parity = driver->kanal.Parity;
StopBits = driver->kanal.StopBits;


int rw = 3;
if( m_bOpened ) return( TRUE );

char szPort[15];
char szComParams[50];
DCB dcb;

wsprintf( szPort, "COM%d", nPort);


m_hIDComDev = CreateFile(szPort,
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED | DDL_SYSTEM,
NULL);


if( m_hIDComDev == NULL ) return( FALSE );
DWORD yy = GetFileAttributes(szPort);

memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

DWORD b = driver->status.waitin + driver->status.waitout + driver->status.waitout_ + driver->status.timeout;// + 25;//driver->status.waitin;
DWORD c=driver->status.waitoutall;
DWORD a=driver->status.timeout;

COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0;//a;//0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;//10;
CommTimeOuts.ReadTotalTimeoutConstant = b;//100;
CommTimeOuts.WriteTotalTimeoutMultiplier = (15000/(nBaud));//c;//10;
CommTimeOuts.WriteTotalTimeoutConstant = 0xFFFFFFFF;//c;//50;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );

wsprintf( szComParams, "COM%d:%d,n,8,1", nPort, nBaud );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = ByteSize;
dcb.Parity = Parity;
dcb.StopBits = StopBits;
//dcb.fNull=true;

/////////////////////////
dcb.fRtsControl = RTS_CONTROL_ENABLE;

/////////////////////////
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );
if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 1000, 1000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL )
{
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
return( FALSE );
}
SetupComm(m_hIDComDev, 1024, 1024);

SetCommMask(m_hIDComDev,EV_ERR);
DWORD dwError;
ClearCommError( m_hIDComDev, &dwError, NULL);
m_bOpened = TRUE;

PurgeRx();
PurgeTx();
SetRTS(FALSE);

CString qqq;
qqq.Format("SHLPICR");
if(m_bOpened){qqq.Format("SHLPICR [COM%d]", driver->kanal.port);}
if(driver->mainWnd!=NULL)
((CWnd *)driver->mainWnd)->SetWindowText(LPCSTR(qqq));


return( m_bOpened );

}
Yuriy_Rus
Цитата(Alexsys @ Aug 31 2006, 11:38) *
2 Yuriy_Rus

Я не совсем понял, прога виснет при попытке послать информацию в COM порт.

RTS - сигнал запроса передачи. Активен во все время передачи.
CTS - сигнал сброса (очистки) для передачи. Активен во все время передачи. Говорит о готовности приемника.
DTR - сигнал готовность к приему
DSR - сигнал готовности данных

Эти сигналы используются для аппаратного управления потоком (RTS-CTS or DTR-DSR handshake). Подробнее посмотри в книжке Гука "Интерфейсы ПК". Флаги RTS_CONTROL_DISABLE и DTR_CONTROL_DISABLE отключают использование аппаратного управления потоком.

Возможна проблема твоя в том, что ты не отчищаешь содержимое структуры DCB перед её заполнением. Я это делаю строкой ZeroMemory(&dcb,sizeof(DCB));


Да, спасибо, скорее всего дело в том, что я не отключал использование аппаратного управления потоком. a14.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.