На работе пишу прогу которая общаеться с шкафом по COM-порту. На работе всё работает отлично, там 98 винда SE у меня на компе. Принёс её домой и она начала дико глючить: виснет ("не отвечает") при вызове CloseHandle хэндла порта и при вызове WriteFile в этот порт. При этом всякие открытия порта и настройка его проходит успешно (у меня на всё проверки стоят). Я в непонятках. Порт настраиваеться вот по такому ini-шнику: =============================================== ; Channel1=COMPort1 [CHAN1] ; Port number. Available values: (1, 2, 3, 4) PORT_NUMBER=2 ; ; Baud rate. Available values: (110, 300, 600, 1200, 2400, 4800, 9600, 14400, ; 19200, 38400, 56000, 57600, 115200) BAUD_RATE=115200 ; ; Data bits on controller. Available values: (7, 8) DATA_BITS=8 ; ; Parity check. Available values: (0-None, 1-Odd parity, 2-Even parity, ; 3-Mark parity, 4-Space parity) PARITY=2 ; ;Stop bits quantity. Available values: (0-1 Stop bit, 1-1.5 Stop bits, ; 2-2 Stop bits) STOP_BITS=0 ; ; DTR/DSR flow control. Available values: (0-Disable, 1-Enable, 2-Handshake) DTR_DSR=0 ; ; RTS/CTS flow control. Available values: (0-Disable, 1-Enable, ; 2-Handshake, 3-Toggle) RTS_CTS=0 ; ; XON/XOFF flow control. Available values: (0-Disable, 1-Enable) XON_XOFF=0 ; ; XON/XOFF characters. Actual only if XON_XOFF=1. Available values: (0..255) ; Default values: (XON_CHAR=17, XOFF_CHAR=19) XON_CHAR=17 XOFF_CHAR=19 ; ; Send address (for RS-485) SEND_ADDR=0x48 ; ; Receive address (for RS-485) RECV_ADDR=0x48 ===================================================================== Всё остальное по дефолту !. Может быть по каким-то причинам в разных виндах порт надо настраивать по разному ??? но почему он тогда успешно открываеться и почему всякие там SetCommState возаращают результат что типа всё нормально настроено ? помогите пожалуйста. прога должна в любой винде нормально пахать, а то мне конец 8).
Ну код настройки порта и его закрытия я наверное могу выложить ... но не более 8) ибо государственная тайна. Код (Text): typedef struct tagRsConfig { HANDLE RsDev; COMMTIMEOUTS RsTimeouts; DCB RsDcb; unsigned char SndAddr; unsigned char RecvAddr; BYTE RsID; DWORD NRecvPack; DWORD NSendPack; } /*RS_CONFIG, *LPRS_CONFIG,*/ RsConfigType; typedef struct tagRsParam { DWORD PortNum; /* COM-port number */ DWORD Baud; /* Baud rate */ DWORD DataBits; /* Quantity of data bits */ DWORD Parity; /* Parity check */ DWORD StopBits; /* Quantity of stop bits */ DWORD DtrDsr; /* DTR/DSR flow control */ DWORD RtsCts; /* RTS/CTS flow control */ DWORD XonXoff; /* XON/XOFF flow contol */ DWORD XonCh; /* XON character */ DWORD XoffCh; /* XOFF character */ DWORD SndAddr; DWORD RecvAddr; } /*RS_PARAM, *LPRS_PARAM,*/ RsParamType; Открытие: int RsSetup( RsParamType *SetupParam, RsConfigType *RsCfg ) { char PortName[16]; memset( RsCfg, 0, sizeof(RsConfigType) ); RsCfg->SndAddr = (unsigned char)SetupParam->SndAddr; RsCfg->RecvAddr = (unsigned char)SetupParam->RecvAddr; sprintf( PortName, "COM%d", SetupParam->PortNum ); RsCfg->RsDev = CreateFile( PortName, GENERIC_READ|GENERIC_WRITE, 0, /* Exclusive access */ NULL, /* No security attrs */ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL/*|*/ /* overlapped I/O */ /*FILE_FLAG_OVERLAPPED*/, NULL ); if ( RsCfg->RsDev == (INVALID_HANDLE_VALUE) ) { return RS_ERR_OFILE; } if ( SetCommMask(RsCfg->RsDev,EV_RXCHAR) == FALSE ) { return RS_ERR_COMM_MASK; } if ( SetupComm(RsCfg->RsDev,RS_RX_SIZE,RS_TX_SIZE) == FALSE ) { return RS_ERR_SETUP_COMM; } if ( PurgeComm(RsCfg->RsDev,PURGE_TXABORT|PURGE_RXABORT| PURGE_TXCLEAR|PURGE_RXCLEAR) == FALSE ) { return RS_ERR_PURGE_COMM; } RsCfg->RsTimeouts.ReadIntervalTimeout = 0;//MAXDWORD; RsCfg->RsTimeouts.ReadTotalTimeoutMultiplier = 0; RsCfg->RsTimeouts.ReadTotalTimeoutConstant = 0;//RS_RX_MAXTIME; RsCfg->RsTimeouts.WriteTotalTimeoutMultiplier = 10; RsCfg->RsTimeouts.WriteTotalTimeoutConstant = RS_TX_SIZE; if ( SetCommTimeouts(RsCfg->RsDev,&(RsCfg->RsTimeouts)) == FALSE ) { return RS_ERR_TIMEOUTS; } RsCfg->RsDcb.DCBlength = sizeof( DCB ); if ( GetCommState(RsCfg->RsDev,&(RsCfg->RsDcb)) == FALSE ) { return RS_ERR_GETCOMMSTATE; } // main parameters setup RsCfg->RsDcb.BaudRate = SetupParam->Baud; RsCfg->RsDcb.ByteSize = (BYTE)(SetupParam->DataBits); RsCfg->RsDcb.fParity = (SetupParam->Parity) ? (1) : (0); if ( RsCfg->RsDcb.fParity ) { RsCfg->RsDcb.Parity = SetupParam->Parity; } RsCfg->RsDcb.fBinary = TRUE; RsCfg->RsDcb.StopBits = (BYTE)(SetupParam->StopBits); // setup hardware flow control switch( SetupParam->DtrDsr ) { case 0 : RsCfg->RsDcb.fDtrControl = DTR_CONTROL_DISABLE; RsCfg->RsDcb.fDsrSensitivity = FALSE; break; case 1 : RsCfg->RsDcb.fDtrControl = DTR_CONTROL_ENABLE; RsCfg->RsDcb.fDsrSensitivity = TRUE; break; case 2 : RsCfg->RsDcb.fDtrControl = DTR_CONTROL_HANDSHAKE; RsCfg->RsDcb.fDsrSensitivity = TRUE; break; default: MessageBox( NULL, "Incorrect value of DTR/DSR parameter", "Parameters error", MB_OK|MB_ICONHAND ); } switch( SetupParam->RtsCts ) { case 0 : RsCfg->RsDcb.fRtsControl = RTS_CONTROL_DISABLE; break; case 1 : RsCfg->RsDcb.fRtsControl = RTS_CONTROL_ENABLE; break; case 2 : RsCfg->RsDcb.fRtsControl = RTS_CONTROL_HANDSHAKE; break; case 3 : RsCfg->RsDcb.fRtsControl = RTS_CONTROL_TOGGLE; break; default: MessageBox( NULL, "Incorrect value of RTS/CTS parameter", "Parameters error", MB_OK|MB_ICONHAND ); } switch( SetupParam->XonXoff ) { case 0 : RsCfg->RsDcb.fOutX = FALSE; RsCfg->RsDcb.fInX = FALSE; break; case 1 : RsCfg->RsDcb.fOutX = TRUE; RsCfg->RsDcb.fInX = TRUE; RsCfg->RsDcb.XonChar = (BYTE)SetupParam->XonCh; RsCfg->RsDcb.XoffChar = (BYTE)SetupParam->XoffCh; break; default: MessageBox( NULL, "Incorrect value of XON/XOFF parameter", "Parameters error", MB_OK|MB_ICONHAND ); } if ( SetCommState(RsCfg->RsDev,&(RsCfg->RsDcb)) == FALSE ) { return RS_ERR_SETCOMMSTATE; } RsCfg->NRecvPack = 0; RsCfg->NSendPack = 0; RsCfg->RsID = SetupParam->PortNum; Закрытие соответственно: int RsClose( RsConfigType *RsCfg ) { //ВОТ НА ЭТОМ САМОМ if И ВИСНЕТ if ( CloseHandle(RsCfg->RsDev) ) { memset( RsCfg, 0, sizeof(RsConfigType) ); return RS_OK; } }
ACF_muti1atoR Перед закрытием попробуйте очистить буфер: Код (Text): PurgeComm(RsCfg->RsDev,PURGE_TXCLEAR | PURGE_RXCLEAR); Вместо WriteFile, если вы пишете побайтно, лучше использовать TransmitCommChar. DCB желательно заполнить сначала через GetCommState. Настройка таймаутов тоже не самая стандартная. Лучше так: Код (Text): COMMTIMEOUTS timeouts = {MAXDWORD,0,0,512,512}; Через Гипертерминал с девайсом получается общаться?
верный ли хендл RsCfg->RsDev - проверял? Это из очевидного. Из менее очевидного - траблы с тем, что ты где-то чего-то портишьс в том же кренеле, и 98й прощает, а ХР - нет. самый просто способ найти ошибку - помести CloseHandle сразу за CreateFile. работает? тогда чуток пониже. и так найти место, когда начнутся глюки. При желании можно утилиткой от руссиновича посмотреть список открытых дескрипторов и их типов для процесса.
Quantum дык ведь общение идет нормально, виснет закрытие порта, насколько я понял. Кстати: RsCfg->RsTimeouts.ReadIntervalTimeout = 0;//MAXDWORD; разве 0 это MAXDWORD?
Спасибо попробую. Grenader нет. Общения никакого нет (в ХР) при WriteFile виснет намертво. у меня стоят проверки: если вдруг RsCfg->RsDev станет INVALID_HANDLE_VALUE, то об этом сразу же сообщиться. Это же касается и всех функции конфигурирования порта (если я чего-то не забыл). В 98 прога общаеться с железом или с TTY на пример или с прогой написанной специально для тестирования этой. Без каких либо глюков.
ACF_muti1atoR INVALID_HANDLE_VALUE == -1 Причём CloseHandle не виснет на попытке закрыть такой хендл. Grenader правильно советует проследить за значением RsDev. Если оно вдруг станет отличным от того, что вернула CreateFile (не обязательно -1), что легко увидеть в отладчике.
> помогите пожалуйста. прога должна в любой винде нормально пахать, а то мне конец 8). Если всё настолько плохо, почему бы не использовать уже готовое? Ридико Л.И., к примеру, для общения с одним устройством пользовался библиотекой, находящейся в отдельной dll. http://www.telesys.ru/projects/proj065/index.shtml Я сам пробовал в XP Pro - прога работает с этим устройством. Но это на крайний случай, если не найдете решения проблемы. Вам только заголовочник нужно будет написать и lib файл сделать по паскалевскому описанию в коде, а может и так найдете где нить.
Хендл порта не меняется во время выполнения программы. Quantum DCB заполняется через GetComState а потом уже из инишника.
NoName Глаза продрал - теперь вижу Откуда такая информация? У вас есть доступ к программе и вы её проверили под отладчиком?