BOOL ConnPort::ClosePort() { g_iExitFlag=1; while(1) { static int iTimeoutCount=0; Sleep(10); if(40==iTimeoutCount) { TerminateThread(m_hThreadRead,0); TerminateThread(m_hThreadWrite,0); TerminateThread(m_hDataParse,0); break; } else if(1==g_rExitFlag && 1==g_wExitFlag && 1==g_pExitFlag) { break; } else { iTimeoutCount++; } } EscapeCommFunction(m_hPort,CLRRTS); EscapeCommFunction(m_hPort,CLRDTR); SetCommMask(m_hPort,0); if(NULL==m_hPort)return FALSE; if(NULL==m_hThreadRead)return FALSE; if(NULL==m_hThreadWrite)return FALSE; if(NULL==m_hDataParse)return FALSE; if(!CloseHandle(m_hPort))return FALSE; if(!CloseHandle(m_hThreadRead))return FALSE; if(!CloseHandle(m_hThreadWrite))return FALSE; if(!CloseHandle(m_hDataParse))return FALSE; m_bIsConnect=FALSE; return TRUE; }
// 关闭串口 _XBool _XSerialPort::close() { if(!m_bOpened || m_hIDComDev == NULL) return XTrue; if(m_overlappedRead.hEvent != NULL) CloseHandle(m_overlappedRead.hEvent); if(m_overlappedWrite.hEvent != NULL) CloseHandle(m_overlappedWrite.hEvent); if(m_mode == SP_MODE_AUTO) //自动模式的时候开启线程 { m_threadState = STATE_SET_TO_END; SetCommMask(m_hIDComDev,0); while(1) {//等待线程结束 if(m_threadState == STATE_END) break; Sleep(1); } } CloseHandle(m_hIDComDev); m_bOpened = XFalse; m_hIDComDev = NULL; return XTrue; }
void ConnPort::ResetComStatues() { m_rCount=0; m_wCount=0; m_bHexShow=FALSE; TerminateThread(m_hThreadRead,0); TerminateThread(m_hThreadWrite,0); TerminateThread(m_hDataParse,0); EscapeCommFunction(m_hPort,CLRRTS); EscapeCommFunction(m_hPort,CLRDTR); SetCommMask(m_hPort,0); CloseHandle(m_hPort); CloseHandle(m_hThreadRead); CloseHandle(m_hThreadWrite); CloseHandle(m_hDataParse); m_bIsConnect=FALSE; }
/******************************************************************************* ** Author: Bill Theisen ** Purpose: Closes the serial port by setting flag to stop ReadThread and signaling ** the EXIT_EVENT to cause WaitCommEvent to stop pending. Then waits for ** ReadThread to exit. ** Comments: *******************************************************************************/ void DOIrisSerialPort::ClosePort( void ) { if( m_bReadThreadIsRunning ){ // Set flag for exit and signal exit event so // that WaitCommEvent() stops pending m_bStopReadThread = TRUE; SetCommMask(m_hPort, EXIT_EVENT); while( m_bReadThreadIsRunning ) { Sleep(200); } } //m_critSecWritePort.Lock(); if(m_hPort != INVALID_HANDLE_VALUE) CloseHandle( m_hPort ); m_hPort = INVALID_HANDLE_VALUE; //m_critSecWritePort.Unlock(); }
// Habilitacion y programacion del puerto serie int CComm32::OpenComm() { if (m_OnOpen) return ERROR_ALREADY_INITIALIZED; m_HPort=CreateFile(m_Name,GENERIC_READ+GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0); if (m_HPort==INVALID_HANDLE_VALUE) return GetLastError(); m_OnOpen=true; if (GetFileType(m_HPort)!=FILE_TYPE_CHAR) { CloseHandle(m_HPort); return ERROR_OPEN_FAILED; } m_Read_Overlapped.hEvent=CreateEvent(NULL,true,true,NULL); if (m_Read_Overlapped.hEvent==0) { CloseAll(); return GetLastError(); } m_Write_Overlapped.hEvent=CreateEvent(NULL,true,true,NULL); if (m_Write_Overlapped.hEvent==0) { CloseAll(); return GetLastError(); } GetCommProperties(m_HPort,&m_CommProp); SetCommMask(m_HPort,m_EvtMask); SetCommTimeouts(m_HPort,&m_CommTimeOuts); GetCommModemStatus(m_HPort,&m_ModemStat); DWORD size=sizeof(COMMCONFIG); GetCommConfig(m_HPort,&m_CommConfig,&size); return 0; }
BOOL CSerialPort::Open(LPCTSTR PortName, DWORD BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits, DWORD DesiredAccess) { Close(); m_PortHandle = CreateFile(PortName, DesiredAccess, 0, NULL, OPEN_EXISTING, 0, 0); if (m_PortHandle != INVALID_HANDLE_VALUE) { DCB dcb; CString s; dcb.DCBlength = sizeof(dcb); GetCommState(m_PortHandle, &dcb); dcb.BaudRate = BaudRate; dcb.ByteSize = ByteSize; dcb.StopBits = StopBits; dcb.Parity = Parity; dcb.fDsrSensitivity = 0; dcb.fOutxCtsFlow = 0; dcb.fOutxDsrFlow = 0; dcb.fInX = 0; dcb.fOutX = 0; dcb.fDtrControl = DTR_CONTROL_DISABLE; //DTR and RTS 0 dcb.fRtsControl = RTS_CONTROL_DISABLE; SetCommState(m_PortHandle, &dcb); COMMTIMEOUTS touts; touts.ReadIntervalTimeout = 0; touts.ReadTotalTimeoutMultiplier = 0; touts.ReadTotalTimeoutConstant = 10; touts.WriteTotalTimeoutConstant = 10; touts.WriteTotalTimeoutMultiplier = 0; SetCommTimeouts(m_PortHandle, &touts); SetCommMask (m_PortHandle, EV_CTS | EV_DSR | EV_RING | EV_RLSD); PurgeComm(m_PortHandle, PURGE_TXCLEAR | PURGE_RXCLEAR); return TRUE; } else { return FALSE; // Use GetLastError() to know the reason } }
void EIO_Set(uv_work_t* req) { SetBaton* data = static_cast<SetBaton*>(req->data); if (data->rts) { EscapeCommFunction((HANDLE)data->fd, SETRTS); } else { EscapeCommFunction((HANDLE)data->fd, CLRRTS); } if (data->dtr) { EscapeCommFunction((HANDLE)data->fd, SETDTR); } else { EscapeCommFunction((HANDLE)data->fd, CLRDTR); } if (data->brk) { EscapeCommFunction((HANDLE)data->fd, SETBREAK); } else { EscapeCommFunction((HANDLE)data->fd, CLRBREAK); } DWORD bits = 0; GetCommMask((HANDLE)data->fd, &bits); bits &= ~(EV_CTS | EV_DSR); if (data->cts) { bits |= EV_CTS; } if (data->dsr) { bits |= EV_DSR; } if (!SetCommMask((HANDLE)data->fd, bits)) { ErrorCodeToString("Setting options on COM port (SetCommMask)", GetLastError(), data->errorString); return; } }
/*------------------------------------------------------------------------------------------------------------------ -- FUNCTION: Transfer_Packet -- -- DATE: November 25, 2015 -- -- REVISIONS: (Date and Description) -- -- DESIGNER: Ruoqi Jia -- -- PROGRAMMER: Ruoqi Jia -- -- INTERFACE: Transfer_Packet(LPVOID packet) -- -LPVOID packet : the packet to be sent -- -- RETURNS: 0 upon successful thread finish -- -- NOTES: -- Represents the sending state of the wireless protocol design. This thread is called whenever a user chooses a -- file to send and presses the Send button. We confirm the line to make sure the line is available. If confirm line -- times out, we bring the protocol back to the Wait state to wait for an ENQ, and re-initialize the read thread. If -- confirm line succeeds, we send our packet using SendPacket. When SendPacket succeeds or times out, we do a check -- on the priority states of the sender and receiver. If we don't have priority and the sender has priority, we enter -- the wait state again to wait for an ENQ, otherwise we will just go directly to the read idle state. Finally, we -- reinitialize the read thread and return from this write thread. ----------------------------------------------------------------------------------------------------------------------*/ DWORD WINAPI Transfer_Packet(LPVOID packet) { ResetEvent(Ev_Read_Thread_Finish); SetCommMask(hComm, RETURN_COMM_EVENT); WaitForSingleObject(hWrite_Lock, 2000); char* s = (char*)packet; OutputDebugString("Starting confirm line loop\n"); if (!ConfirmLine()) { OutputDebugString("exceeded confirm line max tries\n"); //WAIT STATE: wait for an enq, for a specified amount of time. If we get one, set //the receivedENQinWait boolean flag to skip directly to acknowledging line in read thread receivedENQinWait = WaitForEnq(); ReleaseMutex(hWrite_Lock); Initialize_Read(); SetEvent(Ev_Send_Thread_Finish); delete[]s; return 0; } OutputDebugString("Sending packet\n"); SendPacket(s); //Check Priorities //only when we want priority and sender doesn't want priority, we go directly to read idle. every other priority combo, //we go to wait state if ((!weHavePriority && senderHasPriority) || (weHavePriority && senderHasPriority) || (!weHavePriority && !senderHasPriority)) { //WAIT STATE: wait for an enq, for a specified amount of time. If we get one, set //the receivedENQinWait boolean flag to skip directly to acknowledging line in read thread OutputDebugString("Going to wait state\n"); receivedENQinWait = WaitForEnq(); }else SetEvent(Ev_Send_Thread_Finish); //going back to wait/idle state ReleaseMutex(hWrite_Lock); Initialize_Read(); delete[]s; return 0; }
void openXBee(char * device, HANDLE * fd) { DCB dcb; COMMTIMEOUTS cto = { 0, 0, 0, 0, 0 }; memset(&dcb,NULL,sizeof(dcb)); dcb.DCBlength = sizeof(dcb); dcb.BaudRate = 9600; dcb.Parity = NOPARITY; dcb.fParity = 0; dcb.StopBits = ONESTOPBIT; dcb.ByteSize = 8; dcb.fOutxCtsFlow = 0; dcb.fOutxDsrFlow = 0; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fDsrSensitivity = 0; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fOutX = 0; dcb.fInX = 0; dcb.fErrorChar = 0; dcb.fBinary = 1; dcb.fNull = 0; dcb.fAbortOnError = 0; dcb.wReserved = 0; dcb.XonLim = 2; dcb.XoffLim = 4; dcb.XonChar = 0x13; dcb.XoffChar = 0x19; dcb.EvtChar = 0; *fd = CreateFile(device, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,NULL,NULL); if (fd == INVALID_HANDLE_VALUE) { printf("OPENCOMM Failed\n"); COMMERR(-1, "CreateFile"); } COMMERR((!SetCommMask(*fd, 0)?-1:0), "SetCommMask"); COMMERR((!SetCommTimeouts(*fd,&cto)?-1:0), "SetCommTimeouts"); //Met en bloquant pour le passage en mode API COMMERR((!SetCommState(*fd,&dcb)?-1:0), "SetCommState");; }
int NcrComPort::ReadByte() { DCB dcb; int retVal; BYTE Byte; DWORD dwBytesTransferred; DWORD dwCommModemStatus; HANDLE hPort = CreateFileA( this->Port, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL ); if (!GetCommState(hPort, &dcb)) return 0x100; FillDcb(dcb); if (!SetCommState(hPort,&dcb)) return 0x100; SetCommMask (hPort, EV_RXCHAR | EV_ERR); //receive character event WaitCommEvent (hPort, &dwCommModemStatus, 0); //wait for character if (dwCommModemStatus & EV_RXCHAR) { ReadFile (hPort, &Byte, 1, &dwBytesTransferred, 0); //read 1 retVal = Byte; } else if (dwCommModemStatus & EV_ERR) retVal = 0x101; CloseHandle(hPort); return retVal; }
/*DWORD ReadThread(HWND hwnd) *Purpose: Reads characters coming in from the port and calls *the PaintRead function to print them. *Arg 1 - Handle to the window procedure. */ DWORD ReadThread(HWND hwnd) { char message2[] = {0x01, 0x09, 0x00, 0x03, 0x01, 0x41, 0x0A, 0x41, 0xBE}; char *inbuff = ""; DWORD nBytesRead, dwEvent; COMSTAT comstat; COMMTIMEOUTS timeOuts; OVERLAPPED osRead = {0}; osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //Set the total timeout interval memset(&timeOuts, 0, sizeof(timeOuts)); timeOuts.ReadTotalTimeoutMultiplier = 5; timeOuts.ReadTotalTimeoutConstant = 50; SetCommTimeouts(hComm, &timeOuts); SetCommMask(hComm, EV_RXCHAR); //Initialize packet packet.found = 0; packet.total = -1; packet.lrc = 0; while(mode == CONNECT) { if(WaitCommEvent(hComm, &dwEvent, NULL)) { ClearCommError(hComm, NULL, &comstat); if((dwEvent & EV_RXCHAR) && comstat.cbInQue) { if(!ReadFile(hComm, &inbuff, comstat.cbInQue, &nBytesRead, &osRead)) { break; } else { if(nBytesRead) PaintRead(hwnd, inbuff, nBytesRead); } } } ResetEvent(osRead.hEvent); } PurgeComm(hComm, PURGE_RXCLEAR); return 0L; }
// Thread that continuously checks for characters comming in on the serial port. DWORD WINAPI commReadThread() { char *charBuff; // holds character found on serial port. DWORD evtMask; COMSTAT comstat; // stores serial status information DWORD numBytesRead; COMMTIMEOUTS timeOuts; int i, read; gOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // create overlap event to prevent simultanious access to serial port // Timeouts in milliseconds memset(&timeOuts, 0, sizeof(timeOuts)); timeOuts.ReadIntervalTimeout = 0; timeOuts.ReadTotalTimeoutMultiplier = 5; timeOuts.ReadTotalTimeoutConstant = 50; SetCommTimeouts(TTYInfo.hCommPort, &timeOuts); SetCommMask(TTYInfo.hCommPort, EV_RXCHAR); while (TTYInfo.fConnected) { // only loops while serial port is connected. if (WaitCommEvent(TTYInfo.hCommPort, &evtMask, NULL)) { charBuff = '\0'; // stores character from serial port ClearCommError(TTYInfo.hCommPort, NULL, &comstat); // get status information from serial port charBuff = malloc(comstat.cbInQue); if ((evtMask & EV_RXCHAR) && comstat.cbInQue) { // check if queue is empty ReadFile(TTYInfo.hCommPort, charBuff, comstat.cbInQue, &numBytesRead, &gOverlapped); // read a single character from the serial port } for (i = 0; i < (int)numBytesRead; i++) { if (charBuff[i] > 0) { // don't know why, I just had to interpretChar(charBuff[i]); } } } } return 0; }
int ConnPort::OpenPort(TCHAR *szPort,int iBaudrate,int iParity,int iDataBits,int iStopBits) { DWORD dwThreadID=0; g_iExitFlag=0; m_hPort=NULL; m_hPort=CreateFile(szPort, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if(!m_hPort) { m_hPort=NULL; wprintf(TEXT("open port failed!!!\r\n")); return FALSE; } //指定端口检测的事件集 SetCommMask(m_hPort,EV_RXCHAR); //设置缓冲区,内部输入、输出缓冲区大小 SetupComm(m_hPort,1024,1024); //刷新缓冲区信息->输入、输出缓冲区 PurgeComm(m_hPort,PURGE_TXCLEAR|PURGE_RXCLEAR); if(!ConfigPort(iBaudrate,iParity,iDataBits,iStopBits)) return FALSE; if(!CommTimeouts())return FALSE; //创建读写线程 m_hThreadRead = CreateThread(0,0,(LPTHREAD_START_ROUTINE)ReadThreadProc, (void*)this,0,&dwThreadID); m_hThreadWrite = CreateThread(0,0,(LPTHREAD_START_ROUTINE)WriteThreadProc, (void*)this,0,&dwThreadID); m_hDataParse = CreateThread(0,0,(LPTHREAD_START_ROUTINE)PareDataProc, (void*)this,0,&dwThreadID); m_bIsConnect=TRUE; return TRUE; }
////////////////////////////////////////////////////////////////////// // CloseConnection // return: 0 always // int CAsyncPort::CloseConnection() { // not connected m_isConnected = FALSE; // disable event notification and wait for thread to halt SetCommMask(m_hCommDev, 0); // block until thread has been halted while (m_dwThreadID != 0) { Sleep(10); } // drop DTR EscapeCommFunction(m_hCommDev, CLRDTR); // purge any outstanding reads/writes and close device handle PurgeComm ( m_hCommDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); // close device CloseHandle(m_hCommDev); // reset instance variables m_hCommDev = INVALID_HANDLE_VALUE; memset(m_szCommDevName, 0, sizeof (m_szCommDevName)); memset(& m_commConfig, 0, sizeof (COMMCONFIG));; m_commConfig.dwSize = sizeof (COMMCONFIG); memset(& m_commProp, 0, sizeof (COMMPROP)); memset(& m_commTimeOuts, 0, sizeof (COMMTIMEOUTS)); memset(m_baInBuf, 0, sizeof (m_baInBuf)); m_nInBufIndex = 0; m_nInBufSize = 0; return (0); }
// 포트를 닫는다. void CCommThread::ClosePort() { //--> 연결되지 않았음. // sflag = FALSE; m_bConnected = FALSE; ::SendMessage(hStartWnd, WM_COMM_OPEN, 0, 0); //DCB dcb; //SetCommState( m_hComm, &dcb); //--> 마스크 해제.. SetCommMask( m_hComm, 0); Sleep(60); //--> 포트 비우기. PurgeComm( m_hComm, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); //Sleep(60); CloseHandle(m_hComm); //--> 핸들 닫기 }
void EIO_Set(uv_work_t* req) { SetBaton* data = static_cast<SetBaton*>(req->data); if (data->rts) { EscapeCommFunction((HANDLE)data->fd, SETRTS); } else { EscapeCommFunction((HANDLE)data->fd, CLRRTS); } if (data->dtr) { EscapeCommFunction((HANDLE)data->fd, SETDTR); } else { EscapeCommFunction((HANDLE)data->fd, CLRDTR); } if (data->brk) { EscapeCommFunction((HANDLE)data->fd, SETBREAK); } else { EscapeCommFunction((HANDLE)data->fd, CLRBREAK); } DWORD bits = 0; GetCommMask((HANDLE)data->fd, &bits); bits &= ~(EV_CTS | EV_DSR); if (data->cts) { bits |= EV_CTS; } if (data->dsr) { bits |= EV_DSR; } // TODO check for error data->result = SetCommMask((HANDLE)data->fd, bits); }
bool SerialWrapper::Init(const CString& port) { DCB dcb; COMMTIMEOUTS timeout; _port = port; _hport = CreateFile( _port, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (!GetCommState(_hport, &dcb)) return false; dcb.BaudRate = CBR_115200; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(_hport, &dcb)) return false; timeout.ReadIntervalTimeout = MAXDWORD; timeout.ReadTotalTimeoutMultiplier = 0; timeout.ReadTotalTimeoutConstant = 0; timeout.WriteTotalTimeoutMultiplier = 0; timeout.WriteTotalTimeoutConstant = 0; if (!SetCommTimeouts(_hport, &timeout)) return false; SetCommMask(_hport, EV_RXCHAR | EV_ERR); _readBuffer = new(std::nothrow) BYTE[BUFF_SIZE]; if (!_readBuffer) return false; return true; }
CommDevice::CommDevice(char* commName, char HFlags, unsigned long baud, unsigned int ReadSize, char EventChar) { m_Read.m_Size = ReadSize; m_Read.m_Buffer = new char[ReadSize]; memset(m_Read.m_Buffer, 0, m_Read.m_Size); // Open the Comm Port hComm = CreateFile(commName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // Check for errors opening if (hComm == INVALID_HANDLE_VALUE) { DWORD errnum = GetLastError(); cerr << "CreateFile Error: " << errnum << ": Unable to open " << commName << endl; } // Set up the Configuration m_dcb.DCBlength = sizeof(m_dcb); if (!GetCommState(hComm, &m_dcb)) { DWORD errnum = GetLastError(); cerr << "GetCommState Error " << errnum << ": Unable to extract current state for " << commName << endl; } m_dcb.BaudRate = baud; m_dcb.ByteSize = 8; m_dcb.Parity = 0; m_dcb.StopBits = ONESTOPBIT; m_dcb.fNull = TRUE; m_dcb.EvtChar = EventChar; m_dcb.fOutxCtsFlow = (HFlags & H_CTS) ? TRUE : FALSE; m_dcb.fRtsControl = (HFlags & H_RTS) ? RTS_CONTROL_ENABLE : RTS_CONTROL_DISABLE; // Set the Configuration if (!SetCommState(hComm, &m_dcb)) { DWORD errnum = GetLastError(); cerr << "SetCommState Error " << errnum << ": Unable to configure " << commName << endl;// << "Error code: " << itoa(Error) << endl; } SetCommMask(hComm, EV_RXFLAG | EV_TXEMPTY); }
// unsigned int WINAPI DOIrisSerialPort::ReadThread( LPVOID pArg ) DWORD __stdcall DOIrisSerialPort::ReadThread( LPVOID pArg ) // DWORD __stdcall ReadThread(LPVOID hwnd) { unsigned long fdwCommMask; unsigned long CharsInBuffer = 0; unsigned long NonPacketCharsInBuffer; unsigned long packetlength; char * pEndChar; LPSerial pCaller = reinterpret_cast<LPSerial>(pArg); //DO_ASSERT( pCaller != NULL ); pCaller->m_bReadThreadIsRunning = TRUE; /* if ( pCaller->m_msgReceiver ) { pCaller->m_msgReceiver->InitializeThread(); } */ // Enable logging from this thread via pCaller->m_pRnDLog. //HRESULT hRes = E_FAIL; //pCaller->m_pRnDLog->AddThread( hRes ); //DO_ASSERT( SUCCEEDED(hRes) ); // Setup the input and packet buffers char *cBuffer = new char[pCaller->m_iInBufferLength]; //DO_ASSERT( cBuffer != NULL ); char *cPacketBuffer = new char[pCaller->m_iPacketBufferLength]; //DO_ASSERT( cPacketBuffer != NULL ); if( !SetCommMask( pCaller->m_hPort, EV_RXCHAR | EXIT_EVENT ) ) { //pCaller->m_pRnDLog->LogRnDEvent( IDS_IRISCOMMON_SETCOMMMASK_FAILED ); } // Main loop of read thread. while( !pCaller->m_bStopReadThread ) { if( !WaitCommEvent(pCaller->m_hPort, &fdwCommMask, 0)) { //pCaller->m_pRnDLog->LogRnDEvent( IDS_IRISCOMMON_WAITCOMMEVENT_FAILED, // static_cast<int>(GetLastError()) ); break; // Get out of read thread while loop } // Reset the comm Mask. if( !SetCommMask(pCaller->m_hPort, EV_RXCHAR | EXIT_EVENT)) { //pCaller->m_pRnDLog->LogRnDEvent( IDS_IRISCOMMON_SETCOMMMASK_FAILED, // static_cast<int>(GetLastError())); } if( fdwCommMask & EV_RXCHAR ) { unsigned long num; #ifdef _WIN32_WCE // Read all bytes received into cBuffer. ReadFile(pCaller->m_hPort, &cBuffer[CharsInBuffer], pCaller->m_iInBufferLength-CharsInBuffer, &num, 0); #else ReadFile(pCaller->m_hPort, &cBuffer[CharsInBuffer], pCaller->m_iInBufferLength-CharsInBuffer, &num, &(pCaller->m_overlapped)); #endif // _WIN32_WCE CharsInBuffer += num; GenRecBytes = GenRecBytes+num; // Check for a packet in the buffer while( CharsInBuffer && (pEndChar = FindChr( cBuffer, IRIS_PACKET_END_FLAG, CharsInBuffer )) != NULL ) { packetlength = static_cast<unsigned long>((pEndChar - cBuffer) + 1); // Includes IRIS_PACKET_END_FLAG char // Make sure IRIS_PACKET_END_FLAG is in new message area of buffer if ( packetlength <= CharsInBuffer && packetlength <= pCaller->m_iPacketBufferLength ) { // Move packet to buffer and send memcpy( cPacketBuffer, cBuffer, packetlength); // PC-Lint warning 688 expected pCaller->PktCallRelay( cPacketBuffer, packetlength ); } // Move remaining chars in buffer to beginning of buffer and adjust char counts NonPacketCharsInBuffer = CharsInBuffer - packetlength; if( NonPacketCharsInBuffer > 0 ) { // PC-Lint warning 688 expected memcpy( cBuffer, &cBuffer[CharsInBuffer-NonPacketCharsInBuffer], NonPacketCharsInBuffer); } else { NonPacketCharsInBuffer = 0; } CharsInBuffer = NonPacketCharsInBuffer; } // Handle the case were the buffer is full but no packet is found if( CharsInBuffer >= pCaller->m_iInBufferLength ) { CharsInBuffer = 0; //pCaller->m_pRnDLog->LogRnDEvent( IDS_IRISCOMMON_BUFFER_OVERFLOW ); } } // Clear buffers to prevent problem when exiting thread if( fdwCommMask & EXIT_EVENT ) { PurgeComm(pCaller->m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT ); } } delete [] cBuffer; delete [] cPacketBuffer; //pCaller->m_pRnDLog->RemoveThread(); /* if ( pCaller->m_msgReceiver ) { pCaller->m_msgReceiver->ShutdownThread(); } */ pCaller->m_bReadThreadIsRunning = FALSE; return 0; }
// 포트 sPortName을 dwBaud 속도로 연다. // ThreadWatchComm 함수에서 포트에 무언가 읽혔을 때 MainWnd에 알리기 // 위해 WM_COMM_READ메시지를 보낼때 같이 보낼 wPortID값을 전달 받는다. BOOL CCommThread::OpenPort(CString strPortName, DWORD dwBaud, BYTE byData, BYTE byStop, BYTE byParity ) { // Local 변수. COMMTIMEOUTS timeouts; DCB dcb; DWORD dwThreadID; // overlapped structure 변수 초기화. m_osRead.Offset = 0; m_osRead.OffsetHigh = 0; //--> Read 이벤트 생성에 실패.. if ( !(m_osRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) ) { return FALSE; } m_osWrite.Offset = 0; m_osWrite.OffsetHigh = 0; //--> Write 이벤트 생성에 실패.. if (! (m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) { return FALSE; } //--> 포트명 저장.. m_sPortName = strPortName; //--> 실제적인...RS 232 포트 열기.. m_hComm = CreateFile( m_sPortName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); //--> 포트 열기에 실해하면.. if (m_hComm == (HANDLE) -1) { //AfxMessageBox("fail Port ofen"); return FALSE; } //===== 포트 상태 설정. ===== // EV_RXCHAR event 설정...데이터가 들어오면.. 수신 이벤트가 발생하게끔.. SetCommMask( m_hComm, EV_RXCHAR); // InQueue, OutQueue 크기 설정. SetupComm( m_hComm, BUFF_SIZE, BUFF_SIZE); // 포트 비우기. PurgeComm( m_hComm, PURGE_TXABORT | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR); // timeout 설정. timeouts.ReadIntervalTimeout = 0xFFFFFFFF; timeouts.ReadTotalTimeoutMultiplier = 0; timeouts.ReadTotalTimeoutConstant = 0; timeouts.WriteTotalTimeoutMultiplier = 2*CBR_9600 / dwBaud;; timeouts.WriteTotalTimeoutConstant = 0; SetCommTimeouts( m_hComm, &timeouts); // dcb 설정.... 포트의 실제적인..제어를 담당하는 DCB 구조체값 셋팅.. dcb.DCBlength = sizeof(DCB); //--> 현재 설정된 값 중에서.. GetCommState( m_hComm, &dcb); //--> 보드레이트를 바꾸고.. dcb.BaudRate = dwBaud; //--> Data 8 Bit dcb.ByteSize = byData; //--> Noparity dcb.Parity = byParity; //--> 1 Stop Bit dcb.StopBits = byStop; //--> 포트를 재..설정값으로.. 설정해보고.. if( !SetCommState( m_hComm, &dcb) ) { return FALSE; } //Sleep(60); // 포트 감시 쓰레드 생성. m_bConnected = TRUE; ::SendMessage(hStartWnd, WM_COMM_OPEN, 1, 0); //--> 포트 감시 쓰레드 생성. m_hThreadWatchComm = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)ThreadWatchComm, this, 0, &dwThreadID); //--> 쓰레드 생성에 실패하면.. if (! m_hThreadWatchComm) { //--> 열린 포트를 닫고.. ClosePort(); return FALSE; } check = FALSE; return TRUE; }
DWORD ThreadWatchComm(CCommThread* pComm) { DWORD dwEvent; OVERLAPPED os; BOOL bOk = TRUE; BYTE buff[2048]; // 읽기 버퍼 DWORD dwRead; // 읽은 바이트수. // Event, OS 설정. memset( &os, 0, sizeof(OVERLAPPED)); //--> 이벤트 설정.. if( !(os.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL)) ) { bOk = FALSE; } //--> 이벤트 마스크.. if( !SetCommMask( pComm->m_hComm, EV_RXCHAR) ) { bOk = FALSE; } //--> 이벤트나..마스크 설정에 실패함.. if( !bOk ) { //AfxMessageBox("Error while creating ThreadWatchComm, " + pComm->m_sPortName); return FALSE; } while (pComm ->m_bConnected) { dwEvent = 0; // 포트에 읽을 거리가 올때까지 기다린다. WaitCommEvent( pComm->m_hComm, &dwEvent, NULL); //--> 데이터가 수신되었다는 메세지가 발생하면.. if( (dwEvent & EV_RXFLAG || dwEvent & EV_RXCHAR) == (EV_RXFLAG || EV_RXCHAR) ) //if ((dwEvent & EV_RXCHAR) == EV_RXCHAR) { // 포트에서 읽을 수 있는 만큼 읽는다. //--> buff 에 받아놓고.. memset(buff, 0, sizeof(BYTE)*2048); dwRead = pComm->ReadComm( buff, 512); //if(dwRead == 66) { pComm->SetReadData(buff, dwRead); } } } CloseHandle( os.hEvent); //--> 쓰레드 종료가 되겠죠? pComm->m_hThreadWatchComm = NULL; return TRUE; }
bool CIRDriver::InitPort(CIRConfig *cfg, bool daemonize) { struct ir_remote *tmp; if(cfg==NULL) return false; DEBUG("Initializing port...\n"); KillThread(&IRThreadHandle,&IRThreadEvent); KillThread(&DaemonThreadHandle,&DaemonThreadEvent); cbuf_start=cbuf_end=0; if(ov.hEvent) { SetEvent(ov.hEvent); // singal it Sleep(100); // wait a tiny bit CloseHandle(ov.hEvent); // and close it ov.hEvent=NULL; } if(hPort) { SetCommMask(hPort,0); // stop any waiting on the port Sleep(100); // wait a tiny bit CloseHandle(hPort); // and close it hPort=NULL; } if((hPort=CreateFile( cfg->port,GENERIC_READ | GENERIC_WRITE, 0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0))==INVALID_HANDLE_VALUE) { hPort=NULL; return false; } DCB dcb; if(!GetCommState(hPort,&dcb)) { CloseHandle(hPort); hPort=NULL; return false; } if (cfg->animax) dcb.fDtrControl=DTR_CONTROL_ENABLE; //set DTR high, the animax receiver needs this for power else dcb.fDtrControl=DTR_CONTROL_DISABLE; // set the transmit LED to off initially. dcb.fRtsControl=RTS_CONTROL_ENABLE; dcb.BaudRate = cfg->speed; devicetype = cfg->devicetype; virtpulse = cfg->virtpulse; if(!SetCommState(hPort,&dcb)) { CloseHandle(hPort); hPort=NULL; DEBUG("SetCommState failed.\n"); return false; } tmp=global_remotes; while (tmp!=NULL) { if (!(tmp->flags&SPECIAL_TRANSMITTER)) tmp->transmitter=cfg->transmittertype; tmp=tmp->next; } SetTransmitPort(hPort,cfg->transmittertype); if(cfg->sense==-1) { /* Wait for receiver to settle (since we just powered it on) */ Sleep(1000); DWORD state; if(!GetCommModemStatus(hPort,&state)) { CloseHandle(hPort); hPort=NULL; return false; } sense=(state & MS_RLSD_ON) ? 1 : 0; DEBUG("Sense set to %d\n",sense); } else sense=cfg->sense; if((ov.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL))==NULL) { CloseHandle(hPort); hPort=NULL; return false; } /* Start the thread */ /* THREAD_PRIORITY_TIME_CRITICAL combined with the REALTIME_PRIORITY_CLASS */ /* of this program results in the highest priority (26 out of 31) */ if((IRThreadHandle= AfxBeginThread(IRThread,(void *)this,THREAD_PRIORITY_TIME_CRITICAL))==NULL) { CloseHandle(hPort); CloseHandle(ov.hEvent); hPort=ov.hEvent=NULL; return false; } if(daemonize) { /* Start the thread */ /* THREAD_PRIORITY_IDLE combined with the REALTIME_PRIORITY_CLASS */ /* of this program still results in a really high priority. (16 out of 31) */ if((DaemonThreadHandle= AfxBeginThread(DaemonThread,(void *)this,THREAD_PRIORITY_IDLE))==NULL) { KillThread(&IRThreadHandle,&IRThreadEvent); CloseHandle(hPort); CloseHandle(ov.hEvent); hPort=ov.hEvent=NULL; return false; } } DEBUG("Port initialized.\n"); return true; }
void CIRDriver::ThreadProc(void) { /* Virtually no error checking is done here, because */ /* it's pretty safe to assume that everything works, */ /* and we have nowhere to report errors anyway. */ /* We use two timers in case the high resolution doesn't */ /* last too long before wrapping around (is that true? */ /* is it really only a 32 bit timer or a true 64 bit one?) */ __int64 hr_time, hr_lasttime, hr_freq; // high-resolution time_t lr_time, lr_lasttime; // low-resolution DWORD status; GetCommModemStatus(hPort, &status); int prev=(status & MS_RLSD_ON) ? 1 : 0; /* Initialize timer stuff */ QueryPerformanceFrequency((LARGE_INTEGER *)&hr_freq); /* Get time (both LR and HR) */ time(&lr_lasttime); QueryPerformanceCounter((LARGE_INTEGER *)&hr_lasttime); HANDLE events[2]={ov.hEvent,IRThreadEvent}; for(;;) { /* We want to be notified of DCD or RX changes */ if(SetCommMask(hPort, devicetype ? EV_RLSD : EV_RXCHAR)==0) { DEBUG("SetCommMask returned zero, error=%d\n",GetLastError()); } /* Reset the event */ ResetEvent(ov.hEvent); /* Start waiting for the event */ DWORD event; if(WaitCommEvent(hPort,&event,&ov)==0 && GetLastError()!=997) { DEBUG("WaitCommEvent error: %d\n",GetLastError()); } /* Wait for the event to get triggered */ int res=WaitForMultipleObjects(2,events,FALSE,INFINITE); /* Get time (both LR and HR) */ QueryPerformanceCounter((LARGE_INTEGER *)&hr_time); time(&lr_time); if(res==WAIT_FAILED) { DEBUG("Wait failed.\n"); continue; } if(res==(WAIT_OBJECT_0+1)) { DEBUG("IRThread terminating\n"); AfxEndThread(0); return; } if(res!=WAIT_OBJECT_0) { DEBUG("Wrong object\n"); continue; } int dcd; if (devicetype) { GetCommModemStatus(hPort,&status); dcd = (status & MS_RLSD_ON) ? 1 : 0; if(dcd==prev) { /* Nothing changed?! */ /* Continue without changing time */ continue; } prev=dcd; } int deltv=lr_time-lr_lasttime; if (devicetype && (deltv>15)) { /* More than 15 seconds passed */ deltv=0xFFFFFF; if(!(dcd^sense)) { /* sense had to be wrong */ sense=sense?0:1; DEBUG("sense was wrong!\n"); } } else deltv=(int)(((hr_time-hr_lasttime)*1000000) / hr_freq); lr_lasttime=lr_time; hr_lasttime=hr_time; int data; if (devicetype) { data = (dcd^sense) ? (deltv) : (deltv | 0x1000000); if(SetData(data)) SetEvent(hDataReadyEvent); } else { data = deltv; SetData(data-100); if(SetData(virtpulse | 0x1000000)) SetEvent(hDataReadyEvent); PurgeComm(hPort,PURGE_RXCLEAR); } } }
void irtiny::CIRDriver::threadProc() { Event overlappedEvent = Event::manualResetEvent(); OVERLAPPED ov = { 0 }; ov.hEvent = overlappedEvent.get(); HANDLE const events[2] = { ov.hEvent, finishEvent_.get() }; // Send a byte to force RTS ::WriteFile(serialPort_.get(), "x", 1, nullptr, &ov); ::Sleep(100); for (;;) { overlappedEvent.resetEvent(); // We want to be notified of RX changes if (SetCommMask(serialPort_.get(), EV_RXCHAR) == 0) { //DEBUG("SetCommMask returned zero, error=%d\n",GetLastError()); } // Start waiting for the event DWORD event; if (WaitCommEvent(serialPort_.get(), &event, &ov) == 0 && GetLastError() != 997) { //DEBUG("WaitCommEvent error: %d\n",GetLastError()); } switch (WaitForMultipleObjects(2, events, FALSE, INFINITE)) { default: continue; case WAIT_OBJECT_0: while (true) { uint8_t buf[2]; DWORD bytesRead = 0; auto const readSuccessful = ReadFile(serialPort_.get(), buf, 2, &bytesRead, &ov); if (bytesRead == 2) { uint16_t const val = MAKEWORD(buf[1], buf[0]) & 0x7FFF; bool const level = (buf[0] & 0x80) != 0; double const unit = 1.0 / 115200.0; DWORD const deltv = static_cast<DWORD>(1.0e+6 * unit * double(val)); DWORD const data = level ? (deltv | 0x1000000) : deltv; setData(data); } else { ::ClearCommError(serialPort_.get(), nullptr, nullptr); ::PurgeComm(serialPort_.get(), PURGE_RXABORT | PURGE_RXCLEAR); break; } } break; case WAIT_OBJECT_0 + 1: return; } } }
// // Initialize the port. This can be port 1 to MaxSerialPortNum. ///初始化串口。只能是1-MaxSerialPortNum // //parity: // n=none // e=even // o=odd // m=mark // s=space //data: // 5,6,7,8 //stop: // 1,1.5,2 // BOOL CSerialPort::InitPort(HWND pPortOwner, // the owner (CWnd) of the port (receives message) UINT portnr, // portnumber (1..MaxSerialPortNum) UINT baud, // baudrate char parity, // parity UINT databits, // databits UINT stopbits, // stopbits DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc UINT writebuffersize,// size to the writebuffer DWORD ReadIntervalTimeout, DWORD ReadTotalTimeoutMultiplier, DWORD ReadTotalTimeoutConstant, DWORD WriteTotalTimeoutMultiplier, DWORD WriteTotalTimeoutConstant ) { assert(portnr > 0 && portnr < 200); assert(pPortOwner != NULL); // if the thread is alive: Kill if (m_bThreadAlive) { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); //TRACE("Thread ended\n"); } // create events if (m_ov.hEvent != NULL) ResetEvent(m_ov.hEvent); else m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hWriteEvent != NULL) ResetEvent(m_hWriteEvent); else m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hShutdownEvent != NULL) ResetEvent(m_hShutdownEvent); else m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // initialize the event objects ///事件数组初始化,设定优先级别 m_hEventArray[0] = m_hShutdownEvent; // highest priority m_hEventArray[1] = m_ov.hEvent; m_hEventArray[2] = m_hWriteEvent; // initialize critical section ///初始化临界资源 InitializeCriticalSection(&m_csCommunicationSync); // set buffersize for writing and save the owner m_pOwner = pPortOwner; if (m_szWriteBuffer != NULL) delete [] m_szWriteBuffer; m_szWriteBuffer = new char[writebuffersize]; m_nPortNr = portnr; m_nWriteBufferSize = writebuffersize; m_dwCommEvents = dwCommEvents; BOOL bResult = FALSE; CString szPort; //char *szBaud = new char[50]; /* 多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱, 无法控制数据,变成随机变量。为解决这个问题,就需要引入互斥变量,让每 个线程都按顺序地访问变量。这样就需要使用EnterCriticalSection和 LeaveCriticalSection函数。 */ // now it critical! EnterCriticalSection(&m_csCommunicationSync); // if the port is already opened: close it ///串口已打开就关掉 if (m_hComm != NULL) { CloseHandle(m_hComm); m_hComm = NULL; } // prepare port strings szPort.Format("\\\\.\\COM%d", portnr);///可以显示COM10以上端口//add by itas109 2014-01-09 // stop is index 0 = 1 1=1.5 2=2 int mystop; int myparity; switch(stopbits) { case 0: mystop = ONESTOPBIT; break; case 1: mystop = ONE5STOPBITS; break; case 2: mystop = TWOSTOPBITS; break; } myparity = 0; parity = toupper(parity); switch(parity) { case 'N': myparity = 0; break; case 'O': myparity = 1; break; case 'E': myparity = 2; break; case 'M': myparity = 3; break; case 'S': myparity = 4; break; } //sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, mystop); // get a handle to the port /* 通信程序在CreateFile处指定串口设备及相关的操作属性,再返回一个句柄, 该句柄将被用于后续的通信操作,并贯穿整个通信过程串口打开后,其属性 被设置为默认值,根据具体需要,通过调用GetCommState(hComm,&&dcb)读取 当前串口设备控制块DCB设置,修改后通过SetCommState(hComm,&&dcb)将其写 入。运用ReadFile()与WriteFile()这两个API函数实现串口读写操作,若为异 步通信方式,两函数中最后一个参数为指向OVERLAPPED结构的非空指针,在读 写函数返回值为FALSE的情况下,调用GetLastError()函数,返回值为ERROR_IO_PENDING, 表明I/O操作悬挂,即操作转入后台继续执行。此时,可以用WaitForSingleObject() 来等待结束信号并设置最长等待时间 */ m_hComm = CreateFile(szPort, // communication port string (COMX) GENERIC_READ | GENERIC_WRITE, // read/write types 0, // comm devices must be opened with exclusive access NULL, // no security attributes OPEN_EXISTING, // comm devices must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // Async I/O 0); // template must be 0 for comm devices ///创建失败 if (m_hComm == INVALID_HANDLE_VALUE) { // port not found //delete [] szBaud; return FALSE; } // set the timeout values ///设置超时 m_CommTimeouts.ReadIntervalTimeout = ReadIntervalTimeout * 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = ReadTotalTimeoutMultiplier * 1000; m_CommTimeouts.ReadTotalTimeoutConstant = ReadTotalTimeoutConstant * 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier * 1000; m_CommTimeouts.WriteTotalTimeoutConstant = WriteTotalTimeoutConstant * 1000; // configure ///配置 ///分别调用Windows API设置串口参数 if (SetCommTimeouts(m_hComm, &m_CommTimeouts))///设置超时 { /* 若对端口数据的响应时间要求较严格,可采用事件驱动方式。 事件驱动方式通过设置事件通知,当所希望的事件发生时,Windows 发出该事件已发生的通知,这与DOS环境下的中断方式很相似。Windows 定义了9种串口通信事件,较常用的有以下三种: EV_RXCHAR:接收到一个字节,并放入输入缓冲区; EV_TXEMPTY:输出缓冲区中的最后一个字符,发送出去; EV_RXFLAG:接收到事件字符(DCB结构中EvtChar成员),放入输入缓冲区 在用SetCommMask()指定了有用的事件后,应用程序可调用WaitCommEvent()来等待事 件的发生。SetCommMask(hComm,0)可使WaitCommEvent()中止 */ if (SetCommMask(m_hComm, dwCommEvents))///设置通信事件 { if (GetCommState(m_hComm, &m_dcb))///获取当前DCB参数 { //m_dcb.EvtChar = 'q'; //m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high! m_dcb.BaudRate = baud; // add by mrlong m_dcb.Parity = myparity; m_dcb.ByteSize = databits; m_dcb.StopBits = mystop; m_dcb.fBinary = TRUE;// 指定是否允许二进制模式 m_dcb.fParity = TRUE;// 指定是否允许奇偶校验 //m_dcb.EvtChar = 'q'; //if (BuildCommDCB(szBaud, &m_dcb))///填写DCB结构 //{ if (SetCommState(m_hComm, &m_dcb))///配置DCB ; // normal operation... continue else ProcessErrorMessage("SetCommState()"); //} //else // ProcessErrorMessage("BuildCommDCB()"); } else ProcessErrorMessage("GetCommState()"); } else ProcessErrorMessage("SetCommMask()"); } else ProcessErrorMessage("SetCommTimeouts()"); //delete [] szBaud; // flush the port ///终止读写并清空接收和发送 PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // release critical section ///释放临界资源 LeaveCriticalSection(&m_csCommunicationSync); //TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr); return TRUE; }
// COMx for windows, returns NULL on error tUartHandle UartOpen(char* szPortName) { HANDLE serial_handle; DCB dcb; memset(&dcb,0,sizeof(dcb)); /* -------------------------------------------------------------------- */ // set DCB to configure the serial port dcb.DCBlength = sizeof(dcb); dcb.fOutxCtsFlow = 0; dcb.fOutxDsrFlow = 0; dcb.fDtrControl = DTR_CONTROL_ENABLE; // enable for power dcb.fDsrSensitivity = 0; dcb.fRtsControl = RTS_CONTROL_ENABLE; // enable for power dcb.fOutX = 0; dcb.fInX = 0; /* ----------------- misc parameters ----- */ dcb.fErrorChar = 0; dcb.fBinary = 1; dcb.fNull = 0; dcb.fAbortOnError = 0; dcb.wReserved = 0; dcb.XonLim = 2; dcb.XoffLim = 4; dcb.XonChar = 0x13; dcb.XoffChar = 0x19; dcb.EvtChar = 0; /* ----------------- defaults ----- */ dcb.BaudRate = 4800; dcb.Parity = NOPARITY; dcb.fParity = 0; dcb.StopBits = ONESTOPBIT; dcb.ByteSize = 8; /* -------------------------------------------------------------------- */ // opening serial port serial_handle = CreateFile(szPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL); if (serial_handle == INVALID_HANDLE_VALUE) { //printf("Cannot open port \n"); return NULL; } SetCommMask(serial_handle, 0); if(!SetCommState(serial_handle, &dcb)) { //printf("Error setting up COM params\n"); CloseHandle(serial_handle); return NULL; } return serial_handle; }
// // Initialize the port. This can be port 1 to 4. // BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message) UINT portnr, // portnumber (1..4) UINT baud, // baudrate char parity, // parity UINT databits, // databits UINT stopbits, // stopbits DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc UINT writebuffersize) // size to the writebuffer { //assert(portnr > 0 && portnr < 5); assert(pPortOwner != NULL); // if the thread is alive: Kill if (m_bThreadAlive) { do { SetEvent(m_hShutdownEvent); } while (m_bThreadAlive); TRACE("Thread ended\n"); } // create events if (m_ov.hEvent != NULL) ResetEvent(m_ov.hEvent); m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hWriteEvent != NULL) ResetEvent(m_hWriteEvent); m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (m_hShutdownEvent != NULL) ResetEvent(m_hShutdownEvent); m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // initialize the event objects m_hEventArray[0] = m_hShutdownEvent; // highest priority m_hEventArray[1] = m_ov.hEvent; m_hEventArray[2] = m_hWriteEvent; // initialize critical section InitializeCriticalSection(&m_csCommunicationSync); // set buffersize for writing and save the owner m_pOwner = pPortOwner; if (m_szWriteBuffer != NULL) delete [] m_szWriteBuffer; m_szWriteBuffer = new char[writebuffersize]; m_nPortNr = portnr; m_nWriteBufferSize = writebuffersize; m_dwCommEvents = dwCommEvents; BOOL bResult = FALSE; char *szPort = new char[50]; char *szBaud = new char[50]; // now it critical! EnterCriticalSection(&m_csCommunicationSync); // if the port is already opened: close it if (m_hComm != NULL) { CloseHandle(m_hComm); m_hComm = NULL; } // prepare port strings sprintf(szPort, "COM%d", portnr); sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits); // get a handle to the port m_hComm = CreateFile(szPort, // communication port string (COMX) GENERIC_READ | GENERIC_WRITE, // read/write types 0, // comm devices must be opened with exclusive access NULL, // no security attributes OPEN_EXISTING, // comm devices must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // Async I/O 0); // template must be 0 for comm devices if (m_hComm == INVALID_HANDLE_VALUE) { // port not found delete [] szPort; delete [] szBaud; return FALSE; } // set the timeout values m_CommTimeouts.ReadIntervalTimeout = 1000; m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; m_CommTimeouts.ReadTotalTimeoutConstant = 1000; m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; m_CommTimeouts.WriteTotalTimeoutConstant = 1000; // configure if (SetCommTimeouts(m_hComm, &m_CommTimeouts)) { if (SetCommMask(m_hComm, dwCommEvents)) { if (GetCommState(m_hComm, &m_dcb)) { m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high! if (BuildCommDCB(szBaud, &m_dcb)) { if (SetCommState(m_hComm, &m_dcb)) ; // normal operation... continue else ProcessErrorMessage("SetCommState()"); } else ProcessErrorMessage("BuildCommDCB()"); } else ProcessErrorMessage("GetCommState()"); } else ProcessErrorMessage("SetCommMask()"); } else ProcessErrorMessage("SetCommTimeouts()"); delete [] szPort; delete [] szBaud; // flush the port PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); // release critical section LeaveCriticalSection(&m_csCommunicationSync); TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr); return TRUE; }
/*----------------------------------------------------------------------------- FUNCTION: SetupCommPort( int Port ) PURPOSE: Setup Communication Port with our settings -----------------------------------------------------------------------------*/ BOOL SetupCommPort(int port) { DWORD dwReadStatId; DWORD dwWriteStatId; int sav_port,sav_pause; DCB dcb = {0}; char PORTNAME[10]; if (!port) return(false); sav_port=TTY.PORT; sav_pause=TTY.read_pause; TTY.read_pause=1; BreakDownCommPort(); TTY.PORT = port ; // set tty structure for the specified port sprintf(PORTNAME,"\\\\.\\COM%d",port); PACKET.readstate=0; PACKET.number=0; PACKET.old_number=0; PACKET.info=0; // open communication port handle // TTY.COMDEV = CreateFile( PORTNAME,GENERIC_READ | GENERIC_WRITE, // 0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,0); TTY.COMDEV = CreateFile( PORTNAME,GENERIC_READ | GENERIC_WRITE, 0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if (TTY.COMDEV == INVALID_HANDLE_VALUE) goto failed; if (!GetCommState(TTY.COMDEV, &dcb)) // get current DCB settings { report_error("GetCommState");goto failed; } // update DCB rate, byte size, parity, and stop bits size dcb.DCBlength = sizeof(dcb); dcb.BaudRate = TTY.BAUDRATE; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.EvtChar = '\0'; // update flow control settings dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE; if (TTY.FLOW_CONTROL) { dcb.fOutxCtsFlow = TRUE; dcb.fOutxDsrFlow = TRUE; } else { dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; } dcb.fDsrSensitivity = FALSE;; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fTXContinueOnXoff = FALSE; dcb.XonChar = 0; dcb.XoffChar = 0; dcb.XonLim = 0; dcb.XoffLim = 0; dcb.fParity = FALSE; //TRUE; if (!SetCommState(TTY.COMDEV, &dcb)) // set new state { report_error("SetCommState failed"); goto failed;} // set comm buffer sizes if (!SetupComm(TTY.COMDEV, 1024, 1024)) { report_error("SetupComm failed");goto failed;} if (!EscapeCommFunction(TTY.COMDEV, SETDTR)) // raise DTR { report_error("EscapeCommFunction failed");goto failed;} SetCommMask (TTY.COMDEV, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING); // start the reader and writer threads fThreadDone = FALSE; TTY.READERTHREAD = CreateThread( NULL, 1000, (LPTHREAD_START_ROUTINE) ReaderProc, 0, 0, &dwReadStatId); if (TTY.READERTHREAD == NULL) { report_error("CreateThread failed"); goto failed;} TTY.WRITERTHREAD = CreateThread( NULL, 1000, (LPTHREAD_START_ROUTINE) WriterProc, 0, 0, &dwWriteStatId); if (TTY.WRITERTHREAD == NULL) { report_error("CreateWriterThread failed"); goto failed;} write_logfile("COMPORT opened: %s", PORTNAME); TTY.amount_to_write=0; TTY.read_pause=sav_pause; return TRUE; failed: { char sztemp[100]; write_logfile("COMPORT open failed"); sprintf(sztemp, "The Port COM%d is not available. Please select another Com-Port.",TTY.PORT); report_error(sztemp); TTY.read_pause=sav_pause; TTY.PORT=sav_port; TTY.COMDEV=INVALID_HANDLE_VALUE; TTY.CONNECTED=FALSE; TTY.amount_to_write=0; return FALSE; } }
//--------------------------------------------------------------------------- // Attempt to open a com port. Keep the handle in ComID. // Set the starting baud rate to 115200. // // 'portnum' - number 0 to MAX_PORTNUM-1. This number provided will // be used to indicate the port number desired when calling // all other functions in this library. // // 'port_zstr' - zero terminate port name. For this platform // use format COMX where X is the port number. // // // Returns: TRUE(1) - success, COM port opened // FALSE(0) - failure, could not open specified port // bool OpenCOM(int portnum, char *port_zstr) { char tempstr[80]; short fRetVal; COMMTIMEOUTS CommTimeOuts; DCB dcb; // open COM device if ((ComID[portnum] = CreateFile( port_zstr, GENERIC_READ | GENERIC_WRITE, 0, NULL, // no security attrs OPEN_EXISTING, FILE_FLAG_OVERLAPPED, // overlapped I/O NULL )) == (HANDLE) -1 ) { ComID[portnum] = 0; return (FALSE) ; } else { // create events for detection of reading and write to com port osRead[portnum].hEvent = CreateEvent(NULL,TRUE,FALSE,tempstr); osWrite[portnum].hEvent = CreateEvent(NULL,TRUE,FALSE,tempstr); // get any early notifications SetCommMask(ComID[portnum], EV_RXCHAR | EV_TXEMPTY | EV_ERR | EV_BREAK); // setup device buffers SetupComm(ComID[portnum], 2048, 2048); // purge any information in the buffer PurgeComm(ComID[portnum], PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); // set up for overlapped non-blocking I/O CommTimeOuts.ReadIntervalTimeout = 0; CommTimeOuts.ReadTotalTimeoutMultiplier = 20; CommTimeOuts.ReadTotalTimeoutConstant = 40; CommTimeOuts.WriteTotalTimeoutMultiplier = 20; CommTimeOuts.WriteTotalTimeoutConstant = 40; SetCommTimeouts(ComID[portnum], &CommTimeOuts); // setup the com port GetCommState(ComID[portnum], &dcb); dcb.BaudRate = CBR_115200; // current baud rate dcb.fBinary = TRUE; // binary mode, no EOF check dcb.fParity = FALSE; // enable parity checking dcb.fOutxCtsFlow = FALSE; // CTS output flow control dcb.fOutxDsrFlow = FALSE; // DSR output flow control dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type dcb.fDsrSensitivity = FALSE; // DSR sensitivity dcb.fTXContinueOnXoff = TRUE; // XOFF continues Tx dcb.fOutX = FALSE; // XON/XOFF out flow control dcb.fInX = FALSE; // XON/XOFF in flow control dcb.fErrorChar = FALSE; // enable error replacement dcb.fNull = FALSE; // enable null stripping dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control dcb.fAbortOnError = FALSE; // abort reads/writes on error dcb.XonLim = 0; // transmit XON threshold dcb.XoffLim = 0; // transmit XOFF threshold dcb.ByteSize = 8; // number of bits/byte, 4-8 dcb.Parity = NOPARITY; // 0-4=no,odd,even,mark,space dcb.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2 dcb.XonChar = 0; // Tx and Rx XON character dcb.XoffChar = 1; // Tx and Rx XOFF character dcb.ErrorChar = 0; // error replacement character dcb.EofChar = 0; // end of input character dcb.EvtChar = 0; // received event character fRetVal = SetCommState(ComID[portnum], &dcb); } // check if successfull if (!fRetVal) { CloseHandle(ComID[portnum]); ComID[portnum] = 0; return false; } return true; }
BOOL ARRAY3600OBJ::SetupComPort(int port) { connected=FALSE; int sav_port; DCB dcb = {0}; char PORTNAME[10]; sav_port=comport; BreakDownComPort(); comport= port ; // set tty structure for the specified port if (!port) goto failed; sprintf(PORTNAME,"\\\\.\\COM%d",port); comdev = CreateFile( PORTNAME,GENERIC_READ | GENERIC_WRITE, 0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if (comdev == INVALID_HANDLE_VALUE) goto failed; if (!GetCommState(comdev, &dcb)) // get current DCB settings { report_error("GetCommState");goto failed; } // update DCB rate, byte size, parity, and stop bits size dcb.DCBlength = sizeof(dcb); dcb.BaudRate = baudrate; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.EvtChar = '\0'; // update flow control settings dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fDsrSensitivity = FALSE;; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fTXContinueOnXoff = FALSE; dcb.XonChar = 0; dcb.XoffChar = 0; dcb.XonLim = 0; dcb.XoffLim = 0; dcb.fParity = FALSE; //TRUE; if (!SetCommState(comdev, &dcb)) // set new state { report_error("SetCommState failed"); goto failed;} if (!SetupComm(comdev, 1024, 1024)) // set comm buffer sizes { report_error("SetupComm failed");goto failed;} if (!EscapeCommFunction(comdev, SETDTR)) // raise DTR { report_error("EscapeCommFunction failed");goto failed;} SetCommMask (comdev, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_RING); return(TRUE); failed: { char sztemp[100]; sprintf(sztemp, "The Port COM%d is not available. Please select another Com-Port.",port); write_logfile("COMPORT %d open failed.",port); report_error(sztemp); comport=sav_port; comdev=INVALID_HANDLE_VALUE; connected=FALSE; return FALSE; } }