/*! \brief Open a communication channel to the given port info.
	\details If the baudrate in \a portInfo is set to XBR_Invalid, the baud rate is automatically
				detected if possible.
	\param portInfo The details of the port that should be opened. Depending on the type of interface,
				parts of this parameter may be ignored.
	\param readBufSize The size of the read buffer in bytes (if appliccable to the device)
	\param writeBufSize The size of the write buffer in bytes (if appliccable to the device)
	\param options The options to enable (flow control, stop bits)
	\returns XRV_OK if the device was opened successfully
*/
XsResultValue SerialInterface::open(const XsPortInfo& portInfo,
						uint32_t readBufSize,
						uint32_t writeBufSize,
						PortOptions options)
{
	m_endTime = 0;

	JLDEBUG(gJournal, portInfo);

	if (isOpen())
	{
		JLALERT(gJournal, "Port " << portInfo.portName() << " is already open");
		return (m_lastResult = XRV_ALREADYOPEN);
	}
	m_baudrate = portInfo.baudrate();

	if (options&PO_RtsCtsFlowControl)
		JLTRACE(gJournal, "Requested RTS/CTS flow control");
	if (options&PO_DtrDsrFlowControl)
		JLTRACE(gJournal, "Requested DTR/DSR flow control");
	if (options&PO_XonXoffFlowControl)
		JLTRACE(gJournal, "Requested Xon/Xoff flow control");

#ifdef _WIN32
	XsResultValue fail = XRV_OK;
	char winPortName[256];

	// Open port
	sprintf(winPortName, "\\\\.\\%s", portInfo.portName().c_str());
	m_handle = CreateFileA(winPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
									OPEN_EXISTING, 0, NULL);
	if (m_handle == INVALID_HANDLE_VALUE)
	{
		JLDEBUG(gJournal, "Port " << portInfo.portName() << " cannot be opened");
		return (m_lastResult = XRV_INPUTCANNOTBEOPENED);
	}

	DCB commState;		//!< Stored settings about the serial port

	commState.DCBlength = sizeof(DCB);

	//Get the current state & then change it
	if (!GetCommState(m_handle, &commState))	// Get current state
		fail = XRV_ERROR;

	commState.BaudRate = (int) portInfo.baudrate();		// Setup the baud rate
	commState.Parity = NOPARITY;				// Setup the Parity
	commState.ByteSize = 8;					// Setup the data bits
	commState.StopBits = (options&PO_TwoStopBits)?TWOSTOPBITS:ONESTOPBIT;

	// Setup flow control
	commState.fDsrSensitivity = (options&PO_DtrDsrFlowControl)?TRUE:FALSE;
	commState.fOutxDsrFlow = (options&PO_DtrDsrFlowControl)?DTR_CONTROL_HANDSHAKE:DTR_CONTROL_DISABLE;

	commState.fOutxCtsFlow = (options&PO_RtsCtsFlowControl)?TRUE:FALSE;
	commState.fRtsControl = (options&PO_RtsCtsFlowControl)?RTS_CONTROL_HANDSHAKE:RTS_CONTROL_ENABLE;

	commState.fOutX = (options&PO_XonXoffFlowControl)?TRUE:FALSE;
	commState.fInX = commState.fOutX;

	if (!SetCommState(m_handle, (LPDCB)&commState)) // Set new state
	{
		// Bluetooth ports cannot always be opened with 2 stopbits
		// Now try to open port with 1 stopbit.
		commState.StopBits = ONESTOPBIT;
		if (!SetCommState(m_handle, (LPDCB)&commState))
			fail = XRV_INPUTCANNOTBEOPENED;
	}
	std::string tmp = portInfo.portName().toStdString();
	m_port = atoi(&tmp.c_str()[3]);
	sprintf(m_portname, "%s", tmp.c_str());

	if (setTimeout(20))
		fail = m_lastResult;

	// Other initialization functions
	if ((options&PO_DtrDsrFlowControl) == 0)
	{
		if (!EscapeCommFunction(m_handle, SETDTR))			// Set DTR (Calibration sensors need DTR to startup, won't hurt otherwise
			fail = XRV_ERROR;
	}
	if (!SetupComm(m_handle,readBufSize,writeBufSize))	// Set queue size
		fail = XRV_ERROR;

	// Remove any 'old' data in buffer
	//PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
	if (!PurgeComm(m_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
		fail = XRV_ERROR;

	if (fail != XRV_OK)
	{
		CloseHandle(m_handle);		//lint !e534
		m_handle = INVALID_HANDLE_VALUE;
		return (m_lastResult = fail);
	}

#else // !_WIN32
	(void)readBufSize;
	(void)writeBufSize;
	// Open port
	std::string pn = portInfo.portName().toStdString();
	m_handle = ::open(pn.c_str(), O_RDWR | O_NOCTTY);

	// O_RDWR: Read+Write
	// O_NOCTTY: Raw input, no "controlling terminal"
	// O_NDELAY: Don't care about DCD signal

	if (m_handle < 0) {
		// Port not open
		return m_lastResult = XRV_INPUTCANNOTBEOPENED;
	}

	// Check if the file is already opened by someome else (other thread/process)
	if (flock(m_handle, LOCK_EX | LOCK_NB))
	{
		closeLive();
		return m_lastResult = XRV_INPUTCANNOTBEOPENED;
	}

	/* Start configuring of port for non-canonical transfer mode */
	// Get current options for the port
	if (tcgetattr(m_handle, &m_commState) != 0)
		return XRV_ERROR;

	// Set baudrate.
	if (cfsetispeed(&m_commState, portInfo.baudrate()) != 0)
		return XRV_ERROR;

	if (cfsetospeed(&m_commState, portInfo.baudrate()) != 0)
		return XRV_ERROR;

	// Enable the receiver and set local mode
	m_commState.c_cflag |= (CLOCAL | CREAD);
	// Set character size to data bits and set no parity Mask the characte size bits
	m_commState.c_cflag &= ~(CSIZE|PARENB|PARODD);
	m_commState.c_cflag |= CS8;		// Select 8 data bits

	m_commState.c_cflag = setBitsEnabled(m_commState.c_cflag, (tcflag_t)CSTOPB, (options&PO_TwoStopBits) == PO_TwoStopBits);

	// Hardware flow control
	m_commState.c_cflag = setBitsEnabled(m_commState.c_cflag, (tcflag_t)CRTSCTS, (options&PO_RtsCtsFlowControl) == PO_RtsCtsFlowControl);
#ifdef CDTRDSR
	m_commState.c_cflag = setBitsEnabled(m_commState.c_cflag, (tcflag_t)CDTRDSR, (options&PO_DtrDsrFlowControl) == PO_DtrDsrFlowControl);
#endif

	m_commState.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN);
	// Software flow control
	m_commState.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL);
	m_commState.c_iflag = setBitsEnabled(m_commState.c_iflag, (tcflag_t)(IXON|IXOFF), options&PO_XonXoffFlowControl);
	// Set Raw output
	m_commState.c_oflag &= ~OPOST;
	// Timeout 0.001 sec for first byte, read minimum of 0 bytes
	m_commState.c_cc[VMIN]     = 0;
	m_commState.c_cc[VTIME]    = (m_timeout+99)/100;	// 1

	// Set the new options for the port
	if (tcsetattr(m_handle,TCSANOW, &m_commState) != 0)
		return XRV_INPUTCANNOTBEOPENED;

#if defined(JLLOGLEVEL) && JLLOGLEVEL <= JLL_ALERT
	termios checkCommState;
	if (tcgetattr(m_handle, &checkCommState) != 0)
		return XRV_ERROR;

	if (cfgetispeed(&checkCommState) != portInfo.baudrate())
		JLALERT(gJournal, "Set baudrate doesn't match requested baudrate");

	if (cfgetospeed(&checkCommState) != portInfo.baudrate())
		JLALERT(gJournal, "Set baudrate doesn't match requested baudrate");

	if (options&PO_RtsCtsFlowControl && !(checkCommState.c_cflag&CRTSCTS))
		JLALERT(gJournal, "Requested RTS/CTS flow control, but could not be set.");

	if (options&PO_DtrDsrFlowControl &&
#ifdef CDTRDSR
		!(checkCommState.c_cflag&CDTRDSR)
#else
		false
#endif
		)
		JLALERT(gJournal, "Requested DTR/DSR flow control, but could not be set.");

	if (options&PO_XonXoffFlowControl && !((checkCommState.c_iflag&(IXON|IXOFF)) == (IXON|IXOFF)))
		JLALERT(gJournal, "Requested Xon/Xoff flow control, but could not be set.");
#endif // JLLOGLEVEL < JLL_ALERT

#if defined(JLLOGLEVEL) && JLLOGLEVEL <= JLL_DEBUG
#define CHECK_COMMSTATE(req, res, field)\
	if (req.field != res.field) \
	{\
		JLDEBUG(gJournal, "field " << #field << " does not match");\
		JLDEBUG(gJournal, "actual  : " << std::oct << (uint64_t)res.field);\
		JLDEBUG(gJournal, "expected: " << std::oct << (uint64_t)req.field);\
	}
#else
#define CHECK_COMMSTATE(req, res, field)
#endif
	CHECK_COMMSTATE(m_commState, checkCommState, c_cflag);
	CHECK_COMMSTATE(m_commState, checkCommState, c_iflag);
	CHECK_COMMSTATE(m_commState, checkCommState, c_oflag);
	CHECK_COMMSTATE(m_commState, checkCommState, c_cc[VMIN]);
	CHECK_COMMSTATE(m_commState, checkCommState, c_cc[VTIME]);

	m_port = 1;
	sprintf(m_portname, "%s", pn.c_str());

	tcflush(m_handle, TCIOFLUSH);

	// setting RTS and DTR; RTS for Xbus Master, DTR for calibration sensors
	int cmbits;
	if (ioctl(m_handle, TIOCMGET, &cmbits) < 0)
	{
		JLDEBUG(gJournal, "TIOCMGET failed, which is OK for USB connected MkIV devices");
	}

	if ((options&PO_RtsCtsFlowControl) == 0)
		cmbits = setBitsEnabled(cmbits, TIOCM_RTS, true);
	// else don't touch them

	cmbits = setBitsEnabled(cmbits, TIOCM_DTR, !(options&PO_DtrDsrFlowControl));

	if (ioctl(m_handle, TIOCMSET, &cmbits) < 0)
	{
		JLDEBUG(gJournal, "TIOCMSET failed, which is OK for USB connected MkIV devices");
	}
#endif // !_WIN32

	JLDEBUG(gJournal, "Port " << portInfo.portName().toStdString() << " opened");
	return (m_lastResult = XRV_OK);
}
Beispiel #2
0
void serialFlushOutput(SerialPort *SP) {
   PurgeComm(SP->comPort, PURGE_TXCLEAR);
}
Beispiel #3
0
//
//  The CommThread Function.
///线程函数
///监视线程的大致流程:
///检查串口-->进入循环{WaitCommEvent(不阻塞询问)询问事件-->如果有事件来到-->到相应处理(关闭\读\写)}
//
DWORD WINAPI CSerialPort::CommThread(LPVOID pParam)
{
	// Cast the void pointer passed to the thread back to
	// a pointer of CSerialPort class
	CSerialPort *port = (CSerialPort*)pParam;
	
	// Set the status variable in the dialog class to
	// TRUE to indicate the thread is running.
	///TRUE表示线程正在运行
	port->m_bThreadAlive = TRUE;	
		
	// Misc. variables
	DWORD BytesTransfered = 0; 
	DWORD Event = 0;
	DWORD CommEvent = 0;
	DWORD dwError = 0;
	COMSTAT comstat;
	BOOL  bResult = TRUE;
		
	// Clear comm buffers at startup
	///开始时清除串口缓冲
	if (port->m_hComm)		// check if the port is opened
		PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

	// begin forever loop.  This loop will run as long as the thread is alive.
	///只要线程存在就不断读取数据
	for (;;) 
	{ 

		// Make a call to WaitCommEvent().  This call will return immediatly
		// because our port was created as an async port (FILE_FLAG_OVERLAPPED
		// and an m_OverlappedStructerlapped structure specified).  This call will cause the 
		// m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to 
		// be placed in a non-signeled state if there are no bytes available to be read,
		// or to a signeled state if there are bytes available.  If this event handle 
		// is set to the non-signeled state, it will be set to signeled when a 
		// character arrives at the port.

		// we do this for each port!

		/*
		WaitCommEvent函数第3个参数1pOverlapped可以是一个OVERLAPPED结构的变量指针
		,也可以是NULL,当用NULL时,表示该函数是同步的,否则表示该函数是异步的。
		调用WaitCommEvent时,如果异步操作不能立即完成,会立即返回FALSE,系统在
		WaitCommEvent返回前将OVERLAPPED结构成员hEvent设为无信号状态,等到产生通信
		事件时,系统将其置有信号
		*/

		bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);///表示该函数是异步的
		
		if (!bResult)  
		{ 
			// If WaitCommEvent() returns FALSE, process the last error to determin
			// the reason..
			///如果WaitCommEvent返回Error为FALSE,则查询错误信息
			switch (dwError = GetLastError()) 
			{ 
			case ERROR_IO_PENDING: 	///正常情况,没有字符可读
				{ 
					// This is a normal return value if there are no bytes
					// to read at the port.
					// Do nothing and continue
					break;
				}
			case 87:///系统错误
				{
					// Under Windows NT, this value is returned for some reason.
					// I have not investigated why, but it is also a valid reply
					// Also do nothing and continue.
					break;
				}
			default:///发生其他错误,其中有串口读写中断开串口连接的错误
				{
					// All other error codes indicate a serious error has
					// occured.  Process this error.
					port->ProcessErrorMessage("WaitCommEvent()");
					break;
				}
			}
		}
		else	///WaitCommEvent()能正确返回
		{
			// If WaitCommEvent() returns TRUE, check to be sure there are
			// actually bytes in the buffer to read.  
			//
			// If you are reading more than one byte at a time from the buffer 
			// (which this program does not do) you will have the situation occur 
			// where the first byte to arrive will cause the WaitForMultipleObjects() 
			// function to stop waiting.  The WaitForMultipleObjects() function 
			// resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
			// as it returns.  
			//
			// If in the time between the reset of this event and the call to 
			// ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
			// to the signeled state. When the call to ReadFile() occurs, it will 
			// read all of the bytes from the buffer, and the program will
			// loop back around to WaitCommEvent().
			// 
			// At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
			// but there are no bytes available to read.  If you proceed and call
			// ReadFile(), it will return immediatly due to the async port setup, but
			// GetOverlappedResults() will not return until the next character arrives.
			//
			// It is not desirable for the GetOverlappedResults() function to be in 
			// this state.  The thread shutdown event (event 0) and the WriteFile()
			// event (Event2) will not work if the thread is blocked by GetOverlappedResults().
			//
			// The solution to this is to check the buffer with a call to ClearCommError().
			// This call will reset the event handle, and if there are no bytes to read
			// we can loop back through WaitCommEvent() again, then proceed.
			// If there are really bytes to read, do nothing and proceed.
		
			bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

			if (comstat.cbInQue == 0)
				continue;
		}	// end if bResult

		///主等待函数,会阻塞线程
		// Main wait function.  This function will normally block the thread
		// until one of nine events occur that require action.
		///等待3个事件:关断/读/写,有一个事件发生就返回
		Event = WaitForMultipleObjects(3, ///3个事件
			port->m_hEventArray, ///事件数组
			FALSE, ///有一个事件发生就返回
			INFINITE);///超时时间

		switch (Event)
		{
		case 0:
			{
				// Shutdown event.  This is event zero so it will be
				// the higest priority and be serviced first.
				///关断事件,关闭串口
				CloseHandle(port->m_hComm);
				port->m_hComm=NULL;
			 	port->m_bThreadAlive = FALSE;
				
				// Kill this thread.  break is not needed, but makes me feel better.
				//AfxEndThread(100);
				::ExitThread(100);

				break;
			}
		case 1:	// read event 将定义的各种消息发送出去
			{
				GetCommMask(port->m_hComm, &CommEvent);
				if (CommEvent & EV_RXCHAR) //接收到字符,并置于输入缓冲区中 
					ReceiveChar(port);
				
				if (CommEvent & EV_CTS) //CTS信号状态发生变化
					::SendMessage(port->m_pOwner, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_RXFLAG) //接收到事件字符,并置于输入缓冲区中 
					::SendMessage(port->m_pOwner, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_BREAK)  //输入中发生中断
					::SendMessage(port->m_pOwner, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_ERR) //发生线路状态错误,线路状态错误包括CE_FRAME,CE_OVERRUN和CE_RXPARITY 
					::SendMessage(port->m_pOwner, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_RING) //检测到振铃指示
					::SendMessage(port->m_pOwner, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
					
				break;
			}  
		case 2: // write event 发送数据
			{
				// Write character event from port
				WriteChar(port);
				break;
			}
		default:
			{
				AfxMessageBox("接收有问题!");
				break;
			}

		} // end switch

	} // close forever loop

	return 0;
}
Beispiel #4
0
//
// 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;
	char *szPort = new char[50];
	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
	sprintf(szPort, "\\\\.\\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 [] szPort;
		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;
						
				//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 [] 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;
}
Beispiel #5
0
int ComRWTool::OpenCom(const char* pPort, int nBaudRate, int nParity, int nByteSize, int nStopBits)
{
    if (m_bOpen)
    {
        return COMMUN_ERROR_OK;
    }
    if (pPort == NULL)
    {
        return COMMUN_ERROR_BAD_PARARM;
    }
    string strCom = pPort;
    if (strCom.find("\\\\.\\") == strCom.npos)
    {
        strCom = "\\\\.\\" + strCom;
    }
    if(m_hComm != NULL)
    {
        CloseHandle(m_hComm);
        m_hComm = NULL;
    }
    DCB dcb;		// 串口控制块
    COMMTIMEOUTS timeouts = {	// 串口超时控制参数
        100,				// 读字符间隔超时时间: 100 ms
        1,					// 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
        500,				// 基本的(额外的)读超时时间: 500 ms
        1,					// 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
        100};				// 基本的(额外的)写超时时间: 100 ms

        m_hComm = CreateFileA(strCom.c_str(),	// 串口名称或设备路径
            GENERIC_READ | GENERIC_WRITE,	// 读写方式
            0,				// 共享方式:独占
            NULL,			// 默认的安全描述符
            OPEN_EXISTING,	// 创建方式
            0,				// 不需设置文件属性
            NULL);			// 不需参照模板文件

        if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) 
        {
            CK_OutputDebugString("打开串口失败 err:%d",GetLastError());
            return COMMUN_ERROR_FAIL;		// 打开串口失败
        }

        GetCommState(m_hComm, &dcb);		// 取DCB

        dcb.BaudRate = nBaudRate;
        dcb.ByteSize = nByteSize;
        dcb.Parity = nParity;
        dcb.StopBits = nStopBits;

        SetCommState(m_hComm, &dcb);		// 设置DCB

        SetupComm(m_hComm, 4096, 1024);	// 设置输入输出缓冲区大小

        SetCommTimeouts(m_hComm, &timeouts);	// 设置超时

        PurgeComm(m_hComm ,PURGE_TXCLEAR|PURGE_RXCLEAR);

        m_strPort = pPort;
        GetCommState(m_hComm, &dcb);
        m_hQuitEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
        if (NULL == m_hQuitEvent)
        {
            CK_OutputDebugString("COM:Create m_hEventQuit failed!err:%d",GetLastError());
            CloseCom();
            return COMMUN_ERROR_HANDLE_FAILED;
        }


        m_bOpen = true;
        return COMMUN_ERROR_OK;
}
Beispiel #6
0
void CKerrControl::InitControllers()
{
	// Kerr controller require the ID of each Servo sub-controller to be initialized at startup
	// All controllers start with ID=0, but only the first will respond.
	// So we change first one to 1, and the second to 2.

	/* 
	From the Kerr "Arduino-Servo SC" user's manual: PicSrvSC.pdf (page 6):
	1. On power-up, all modules assume a default address of 0x00, and each will set its ADDR_OUT
	signal HIGH. Furthermore, a module’s communications will be disabled completely until its
	ADDR_IN signal goes LOW. If the ADDR_OUT and ADDR_IN signals are daisy-chained as
	described above, all modules will be disabled except for the module furthest from the host.
	2. The host starts by sending a Set Address command to module 0, changing its address to a value of
	1. A side affect of the Set Address command is that the module will lower the its ADDR_OUT
	signal.
	3. At this point, the next module in line is enabled with an address of 0. The host then sends a
	command to module 0 to change its address to a value of 2.
	4. This process is continued until all modules have been assigned unique addresses.
	*/

	if( m_ControllerIDsInitialized )
	{
		return; // only do once!
	}
	m_ControllerIDsInitialized = TRUE;

	// Send a bunch of zeros to get the Kerr control synchronized
	m_KerrCmd.ID = 0;			// Address of Servo to access use 0 for initial start-up
	m_KerrCmd.Command = 0;			
	m_KerrCmd.Data[0] = 0;
	m_KerrCmd.Data[1] = 0;
	m_KerrCmd.Data[2] = 0;
	m_KerrCmd.Data[3] = 0;
	m_KerrCmd.Data[4] = 0;
	m_KerrCmd.Data[5] = 0;
	m_KerrCmd.Data[6] = 0;
	m_KerrCmd.Data[7] = 0;
	m_KerrCmd.Data[8] = 0;
	m_KerrCmd.Data[9] = 0;
	m_KerrCmd.Data[10] = 0;
	m_KerrCmd.Data[11] = 0;
	m_KerrCmd.Data[12] = 0;
	m_KerrCmd.Data[13] = 0;
	m_KerrCmd.Data[14] = 0;
	m_KerrCmd.Data[15] = 0;
	SendCmd(16,0, FALSE);	// no response expected, just flushing the port


	m_KerrCmd.ID = 0;			// Address of Servo to access use 0 for initial start-up
	m_KerrCmd.Command = 0x0E;	// Send NOP to just get a status back (which is ignored)		
	SendCmd(0, 0, FALSE);


	m_KerrCmd.ID = 0xFF;			// Address of Servo - FF = all servos (default group)
	m_KerrCmd.Command = KERR_CMD_HARD_RESET;	// High Nibble contains number of Data Bytes		
	SendCmd(0,0, FALSE);	// No response to Reset command

	Sleep(100);

	// Purge the comm port input and output of junk
	if( (INVALID_HANDLE_VALUE != g_hKerrServoCommPort)  && (SIMULATED_SIO_HANDLE != g_hKerrServoCommPort) )
	{
		if( !PurgeComm(g_hKerrServoCommPort, (PURGE_TXCLEAR | PURGE_RXCLEAR)) )
		{
			ROBOT_ASSERT(0);	// Purge failed.  Need to call GetLastError().
		}
	}

	// Set the first servo controller ID
	m_KerrCmd.ID = 0;			// Address of Servo to access use 0 for initial start-up
	m_KerrCmd.Command = KERR_CMD_SET_ADDRESS + 0x20;	// High Nibble contains number of Data Bytes		
	m_KerrCmd.Data[0] = KERR_ARM_MOTOR_ID_RIGHT;		// Individual Address = 1
	m_KerrCmd.Data[1] = 0xFF;	// No Group Address
	SendCmd(2);

	Sleep(100);
	
	// Set the second servo controller ID
	m_KerrCmd.ID = 0;			// Address of Servo to access use 0 for initial start-up
	m_KerrCmd.Command = KERR_CMD_SET_ADDRESS + 0x20;	// High Nibble contains number of Data Bytes		
	m_KerrCmd.Data[0] = KERR_ARM_MOTOR_ID_LEFT;		// Individual Address = 2
	m_KerrCmd.Data[1] = 0xFF;	// No Group Address
	SendCmd(2);

	
// Set the Amplifier Gain

	m_KerrCmd.ID = KERR_ARM_MOTOR_ID_RIGHT;			// Address of Servo
	m_KerrCmd.Command  = 0xF6;			
	m_KerrCmd.Data[0]  = 0x64;
	m_KerrCmd.Data[1]  = 0x00;
	m_KerrCmd.Data[2]  = 0xE8;
	m_KerrCmd.Data[3]  = 0x03;
	m_KerrCmd.Data[4]  = 0x00;
	m_KerrCmd.Data[5]  = 0x00;
	m_KerrCmd.Data[6]  = 0x00;
	m_KerrCmd.Data[7]  = 0x00;
	m_KerrCmd.Data[8]  = 0xFF;
	m_KerrCmd.Data[9]  = 0x00;
	m_KerrCmd.Data[10] = 0xA0;
	m_KerrCmd.Data[11] = 0x0F;
	m_KerrCmd.Data[12] = 0x01;
	m_KerrCmd.Data[13] = 0x01;
	m_KerrCmd.Data[14] = 0x01;
	SendCmd(15);

	m_KerrCmd.ID = KERR_ARM_MOTOR_ID_LEFT;			// Address of Servo
	m_KerrCmd.Command  = 0xF6;			
	m_KerrCmd.Data[0]  = 0x64;
	m_KerrCmd.Data[1]  = 0x00;
	m_KerrCmd.Data[2]  = 0xE8;
	m_KerrCmd.Data[3]  = 0x03;
	m_KerrCmd.Data[4]  = 0x00;
	m_KerrCmd.Data[5]  = 0x00;
	m_KerrCmd.Data[6]  = 0x00;
	m_KerrCmd.Data[7]  = 0x00;
	m_KerrCmd.Data[8]  = 0xFF;
	m_KerrCmd.Data[9]  = 0x00;
	m_KerrCmd.Data[10] = 0xA0;
	m_KerrCmd.Data[11] = 0x0F;
	m_KerrCmd.Data[12] = 0x01;
	m_KerrCmd.Data[13] = 0x01;
	m_KerrCmd.Data[14] = 0x01;
	SendCmd(15);


	// In case the arm was up when reset, the counter is now not at zero
	// so, reset it to get it close enough to allow home calibration to work right
	m_KerrCmd.ID = KERR_ARM_MOTOR_ID_RIGHT;	// First Arm
	m_KerrCmd.Command = KERR_CMD_RESET_POS;	// High Nibble contains number of Data Bytes (none)		
	SendCmd(0);

	m_KerrCmd.ID = KERR_ARM_MOTOR_ID_LEFT;	// Second Arm
	m_KerrCmd.Command = KERR_CMD_RESET_POS;	// High Nibble contains number of Data Bytes (none)		
	SendCmd(0);

}
Beispiel #7
0
/**
 * シリアルポートをオープンする.
 *
 * @param devfile シリアルポートのデバイスファイル名.
 * @param baud ボーレート.
 *
 * @retval !NULL ハンドラ。
 * @retval NULL 失敗。
 */
SERIAL *serial_open(const char *devfile, const enum SerialBaud baud)
{
    DCB param;
    int baudrate = 0;

    /*
     * シリアルデスクリプタの管理領域を確保する.
     */
    SERIAL *s = (SERIAL *) malloc(sizeof(SERIAL));
    if (s == NULL) {
        return NULL;
    }

    /*
     * ポート名を決定する.
     */
    if (strstr(devfile, "\\\\.\\") == NULL) {
        strcpy(s->devfile, "\\\\.\\");
    } else {
        strcpy(s->devfile, "");
    }
    strcat(s->devfile, devfile);

    /*
     * ポートを開く.
     */
    s->handle = CreateFile(
            s->devfile,
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);
    if (s->handle == INVALID_HANDLE_VALUE) {
        free(s);
        return NULL;
    }

    /*
     * ポートの設定を行う。
     */
    if (!GetCommState(s->handle, &param)) {
        free(s);
        return NULL;
    }
    switch (baud) {
    case SerialBaud2400:
        param.BaudRate = CBR_2400;
        break;
    case SerialBaud4800:
        param.BaudRate = CBR_4800;
        break;
    case SerialBaud9600:
        param.BaudRate = CBR_9600;
        break;
    case SerialBaud19200:
        param.BaudRate = CBR_19200;
        break;
    case SerialBaud38400:
        param.BaudRate = CBR_38400;
        break;
    default:
        param.BaudRate = CBR_9600;
        break;
    }
    param.ByteSize = 8;
    param.StopBits = ONESTOPBIT;
    param.Parity = NOPARITY;
    if(!SetCommState(s->handle, &param)){
        free(s);
        return NULL;
    }

    /*
     * バッファの内容を捨てる.
     */
    PurgeComm(s->handle, PURGE_RXCLEAR);
    PurgeComm(s->handle, PURGE_TXCLEAR);
    PurgeComm(s->handle, PURGE_RXABORT);
    PurgeComm(s->handle, PURGE_TXABORT);

    return s;
}
Beispiel #8
0
int open_comport()
{
#ifdef ALLEGRO_WINDOWS
   DCB dcb;
   COMMTIMEOUTS timeouts;
   DWORD bytes_written;
   char temp_str[16];
#endif
   
   if (comport.status == READY)    // if the comport is open,
      close_comport();    // close it
   
#ifdef ALLEGRO_WINDOWS
   // Naming of serial ports 10 and higher: See
   // http://www.connecttech.com/KnowledgeDatabase/kdb227.htm
   // http://support.microsoft.com/?id=115831
   sprintf(temp_str, "\\\\.\\COM%i", comport.number + 1);
   com_port = CreateFile(temp_str, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
   if (com_port == INVALID_HANDLE_VALUE)
   {
      comport.status = NOT_OPEN; //port was not open
      return -1; // return error
   }
   
   // Setup comport
   GetCommState(com_port, &dcb);
   dcb.BaudRate = comport.baud_rate;
   dcb.ByteSize = 8;
   dcb.StopBits = ONESTOPBIT;
   dcb.fParity = FALSE;
   dcb.Parity = NOPARITY;
   dcb.fOutxCtsFlow = FALSE;
   dcb.fOutxDsrFlow = FALSE;
   dcb.fOutX = FALSE;
   dcb.fInX = FALSE;
   dcb.fDtrControl = DTR_CONTROL_ENABLE;
   dcb.fRtsControl = RTS_CONTROL_ENABLE;
   dcb.fDsrSensitivity = FALSE;
   dcb.fErrorChar = FALSE;
   dcb.fAbortOnError = FALSE;
   SetCommState(com_port, &dcb);
   
   // Setup comm timeouts
   timeouts.ReadIntervalTimeout = MAXWORD;
   timeouts.ReadTotalTimeoutMultiplier = 0;
   timeouts.ReadTotalTimeoutConstant = 0;
   timeouts.WriteTotalTimeoutMultiplier = TX_TIMEOUT_MULTIPLIER;
   timeouts.WriteTotalTimeoutConstant = TX_TIMEOUT_CONSTANT;
   SetCommTimeouts(com_port, &timeouts);
   // Hack to get around Windows 2000 multiplying timeout values by 15
   GetCommTimeouts(com_port, &timeouts);
   if (TX_TIMEOUT_MULTIPLIER > 0)
      timeouts.WriteTotalTimeoutMultiplier = TX_TIMEOUT_MULTIPLIER * TX_TIMEOUT_MULTIPLIER / timeouts.WriteTotalTimeoutMultiplier;
   if (TX_TIMEOUT_CONSTANT > 0)
      timeouts.WriteTotalTimeoutConstant = TX_TIMEOUT_CONSTANT * TX_TIMEOUT_CONSTANT / timeouts.WriteTotalTimeoutConstant;
   SetCommTimeouts(com_port, &timeouts);
   
   // If the port is Bluetooth, make sure device is active
   PurgeComm(com_port, PURGE_TXCLEAR|PURGE_RXCLEAR);
   WriteFile(com_port, "?\r", 2, &bytes_written, 0);
   if (bytes_written != 2)  // If Tx timeout occured
   {
      PurgeComm(com_port, PURGE_TXCLEAR|PURGE_RXCLEAR);
      CloseHandle(com_port);
      comport.status = NOT_OPEN; //port was not open
      return -1;
   }
#else
   com_port = comm_port_init(comport.number);
   comm_port_set_baud_rate(com_port, comport.baud_rate);
   comm_port_set_parity(com_port, NO_PARITY);
   comm_port_set_data_bits(com_port, BITS_8);
   comm_port_set_stop_bits(com_port, STOP_1);
   comm_port_set_flow_control(com_port, NO_CONTROL);
   if (comm_port_install_handler(com_port) != 1)
   {
      comport.status = NOT_OPEN; //port was not open
      return -1; // return error
   }
#endif
   
   serial_time_out = FALSE;
   comport.status = READY;
   
   return 0; // everything is okay
}
Beispiel #9
0
DWORD WINAPI CommMonitor( LPSTR lpData)
{
	CommData
	SYSTEMTIME SystemTime;
	int	 i,nItemCount,nPackLen=0;
	BYTE  PackFun ;
	BOOL	OddFlag=FALSE;
	LPSTR lpPointer,lptemp1,lptemp2,hRXBuffer=(LPSTR)RxBuffer;
	char *p_ACK1="\x10\x31";
	char *p_ACK0="\x10\x30";

	Init()
	ResetOpPointer()				

	
	ResetRxPointer()


 	nItemCount =0;
	FillDevName()					
	SetCommWaitMask(EV_RXFLAG)
	PurgeComm( hComm, PURGE_RXCLEAR );	
	while (TRUE)
	{



		WaitEvent(EV_RXFLAG)


		GetInQueueLength(dwReadLength)
		ReadCommBlock(dwReadLength)
 

 

		lptemp1=strbchrnb(lpRxPointer,'[',1,(int)dwReadLength+5);
		PackFun= *(lptemp1+c_FuncNumOff);
		{
			case '0':	
			case 'D':
				ResetRxPointer()		
				ResetOpPointer()
				continue;
			case '1':	
				if (lptemp1!=lpOpPointer)	
				{
					for (i=0;*hRXBuffer!='[';hRXBuffer++,i++); 
					memmove(lpOpPointer ,hRXBuffer , (int)(lpRxPointer-hRXBuffer));
					lpRxPointer=lpRxPointer-i;
					hRXBuffer=(LPSTR)RxBuffer;
				}
				continue;
			case '5':	

				if ((*lpOpPointer)!='[')
				{
					for (i=0;*hRXBuffer!='[';hRXBuffer++,i++); 
					memmove(lpOpPointer ,hRXBuffer , (int)(lpRxPointer-hRXBuffer));
					lpRxPointer=lpRxPointer-i;
					hRXBuffer=(LPSTR)RxBuffer;
				continue;
			case '9':	
				
				break;			

			default :	

				continue;

		}


		wSampleID =(int)StrToInt(lpOpPointer+7,5);
		GetLocalTime(&SystemTime);
				

		lpPointer=strchrnb(lpOpPointer+1,'[',2,70);				
		while(*(lpPointer+2)=='2')	
		{

			FillSampleID(nItemCount, wSampleID)	

			lptemp1=strchrnb(lpPointer,',',1,4)+1;
			lptemp2=strchrnb(lptemp1,',',1,5);
			FillItemName(nItemCount, lptemp1,(lptemp2-lptemp1))	

			lptemp1=strchrnb(lptemp2+1,',',2,20)+1;
			for (;*lptemp1==' ';lptemp1++);
			lptemp2=strchrnb(lptemp1,',',1,10);
			FillResult(nItemCount,lptemp1,(int)(lptemp2-lptemp1))

			FillDate(nItemCount, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour)

			lpPointer=strchrnb(lptemp2+1,'[',1,40);				
			nItemCount++;
		}	


		if(nItemCount>0)
		{
			(*lpResultProcessRoutine)(lpDevice->nDevNO, OutResult, nItemCount);
			lpDevice->dwRecordCount+=nItemCount;
		}

		
		nItemCount=0;	
//		nPackLen=0;
		ResetRxPointer()		
		ResetOpPointer()
		hRXBuffer=(LPSTR)RxBuffer;

	}
	return TRUE;
} // end of CommWatchProc()

void WINAPI BeforeSetCommState(DCB *pComDcb)
{
	pComDcb->EvtChar ='[';
}
int xbee_ser_open( xbee_serial_t *serial, uint32_t baudrate)
{
	char				buffer[sizeof("\\\\.\\COM9999")];
	HANDLE			hCom;
	COMMTIMEOUTS	timeouts;
	int				err;

	if (serial == NULL || serial->comport > 9999)
	{
		#ifdef XBEE_SERIAL_VERBOSE
			printf( "%s: -EINVAL (serial=%p)\n", __FUNCTION__, serial);
		#endif
		return -EINVAL;
	}

	// if XBee's existing hCom handle is not null, need to close it
	// (unless we're just changing the baud rate?)

	// Assume serial port has not changed if port is already open, and skip the
	// CreateFile step.

	if (serial->hCom)
	{
		// serial port is already open
		hCom = serial->hCom;
		serial->hCom = NULL;
		#ifdef XBEE_SERIAL_VERBOSE
			printf( "%s: port already open (hCom=%p)\n",
				__FUNCTION__, hCom);
		#endif
	}
	else
	{
		snprintf( buffer, sizeof buffer, "\\\\.\\COM%u", serial->comport);
		hCom = CreateFile( buffer, GENERIC_READ | GENERIC_WRITE,
			0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hCom == INVALID_HANDLE_VALUE)
		{
			#ifdef XBEE_SERIAL_VERBOSE
				printf( "%s: error %lu opening handle to %s\n", __FUNCTION__,
					GetLastError(), buffer);
			#endif
			return -EIO;
		}
	}

	// set up a transmit and receive buffers
	SetupComm( hCom, XBEE_SER_RX_BUFSIZE, XBEE_SER_TX_BUFSIZE);

	/*	Set the COMMTIMEOUTS structure.  Per MSDN documentation for
		ReadIntervalTimeout, "A value of MAXDWORD, combined with zero values
		for both the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier
		members, specifies that the read operation is to return immediately
		with the bytes that have already been received, even if no bytes have
		been received."
	*/
	if (!GetCommTimeouts( hCom, &timeouts))
	{
		#ifdef XBEE_SERIAL_VERBOSE
			printf( "%s: %s failed (%lu initializing COM%u)\n",
				__FUNCTION__, "GetCommTimeouts", GetLastError(), serial->comport);
		#endif
		CloseHandle( hCom);
		return -EIO;
	}
	timeouts.ReadIntervalTimeout = MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier = 0;
	timeouts.ReadTotalTimeoutConstant = 0;
	if (!SetCommTimeouts( hCom, &timeouts))
	{
		#ifdef XBEE_SERIAL_VERBOSE
			printf( "%s: %s failed (%lu initializing COM%u)\n",
				__FUNCTION__, "SetCommTimeouts", GetLastError(), serial->comport);
		#endif
		CloseHandle( hCom);
		return -EIO;
	}

	PurgeComm( hCom, PURGE_TXCLEAR | PURGE_TXABORT |
							PURGE_RXCLEAR | PURGE_RXABORT);

	serial->hCom = hCom;

	err = xbee_ser_baudrate( serial, baudrate);

	if (err)
	{
		serial->hCom = NULL;
		return err;
	}

	#ifdef XBEE_SERIAL_VERBOSE
		printf( "%s: SUCCESS COM%u opened (hCom=%p, baud=%u)\n",
			__FUNCTION__, serial->comport, hCom, baudrate);
	#endif

	return 0;
}
Beispiel #11
0
//
// 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;
}
Beispiel #12
0
/******************************************************************************
* Name: ProcessCommRequests
*
* Purpose: worker thread function that communicates with the com port
******************************************************************************/
UINT AFX_CDECL ProcessCommRequests( LPVOID lParam)
{
    if( !lParam) return 2;

    DWORD dwWait;

    // loop ends by returning on error or when the terminate flag is set
    while( TRUE) {
        dwWait = WaitForSingleObject( COMMEVENT, TIMEOUT);
        while( dwWait!=WAIT_OBJECT_0)	{
            // check for error
            if( dwWait==WAIT_ABANDONED_0 || dwWait == WAIT_FAILED) {
                ResetEvent( COMMEVENT);
                PurgeComm( HPORT, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
                return 1;
            }

            // check for termination
            if( TERMINATE_FLAG) {
                ResetEvent( COMMEVENT);
                PurgeComm( HPORT, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
                return 0;
            }

            dwWait = WaitForSingleObject( COMMEVENT, TIMEOUT);
        }

        CCommRequest* pRequest = (((CCommDevice*)lParam)->m_pRequest);

        switch( pRequest->m_dwRequestType) {
        case REQUEST_READ:
        {
            // clear request error field
            pRequest->m_dwRequestError = ERR_NOERROR;

            DWORD dwBytesRead = READFILE( pRequest->m_lpszResult,
                                          pRequest->m_dwResultLength,
                                          pRequest->m_dwMaxTries,
                                          pRequest->m_dwTimeout);
            pRequest->m_dwResultLength = dwBytesRead;
            pRequest->m_dwRequestError = COMMSTATE;
            COMMSTATE = ERR_NOERROR;

            ((CCommDevice*)lParam)->m_pRequest = NULL;
            ResetEvent( COMMEVENT);

            if( !dwBytesRead) {
                switch( pRequest->m_dwRequestError) {
                case ERR_PORTERROR:
                case ERR_NOPORTLOCK:
                case ERR_NODATALOCK:
                {
                    if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                        pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                    else if( pRequest->m_pCompleteFunction)
                        (*pRequest->m_pCompleteFunction)( pRequest);
                    return 1;
                }
                case ERR_TERMINATED:
                {
                    if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                        pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                    else if( pRequest->m_pCompleteFunction)
                        (*pRequest->m_pCompleteFunction)( pRequest);
                    return 0;
                }
                }
            }

            if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
            else if( pRequest->m_pCompleteFunction)
                (*pRequest->m_pCompleteFunction)( pRequest);
            break;
        }
        case REQUEST_WRITE:
        {
            // clear request error field
            pRequest->m_dwRequestError = ERR_NOERROR;

            DWORD dwBytesWritten = WRITEFILE( pRequest->m_lpszData,
                                              pRequest->m_dwDataLength);
            pRequest->m_dwDataLength = dwBytesWritten;
            pRequest->m_dwRequestError = COMMSTATE;
            COMMSTATE = ERR_NOERROR;

            ((CCommDevice*)lParam)->m_pRequest = NULL;
            ResetEvent( COMMEVENT);

            if( !dwBytesWritten) {
                switch( pRequest->m_dwRequestError) {
                case ERR_PORTERROR:
                case ERR_NOPORTLOCK:
                {
                    if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                        pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                    else if( pRequest->m_pCompleteFunction)
                        (*pRequest->m_pCompleteFunction)( pRequest);
                    return 1;
                }
                case ERR_TERMINATED:
                {
                    if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                        pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                    else if( pRequest->m_pCompleteFunction)
                        (*pRequest->m_pCompleteFunction)( pRequest);
                    return 0;
                }
                }
            }

            if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
            else if( pRequest->m_pCompleteFunction)
                (*pRequest->m_pCompleteFunction)( pRequest);
            break;
        }
        case REQUEST_COMMAND:
        {
            // clear request error field
            pRequest->m_dwRequestError = ERR_NOERROR;

            DWORD dwBytesRead = COMMAND( pRequest->m_lpszData,
                                         pRequest->m_dwDataLength,
                                         pRequest->m_lpszResult,
                                         pRequest->m_dwResultLength,
                                         pRequest->m_dwMaxTries,
                                         pRequest->m_dwTimeout);
            pRequest->m_dwResultLength = dwBytesRead;
            pRequest->m_dwRequestError = COMMSTATE;
            COMMSTATE = ERR_NOERROR;

            ((CCommDevice*)lParam)->m_pRequest = NULL;
            ResetEvent( COMMEVENT);

            if( !dwBytesRead) {
                switch( pRequest->m_dwRequestError) {
                case ERR_PORTERROR:
                case ERR_NOPORTLOCK:
                case ERR_NODATALOCK:
                {
                    if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                        pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                    else if( pRequest->m_pCompleteFunction)
                        (*pRequest->m_pCompleteFunction)( pRequest);
                    return 1;
                }
                case ERR_TERMINATED:
                {
                    if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                        pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                    else if( pRequest->m_pCompleteFunction)
                        (*pRequest->m_pCompleteFunction)( pRequest);
                    return 0;
                }
                }
            }

            if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
            else if( pRequest->m_pCompleteFunction)
                (*pRequest->m_pCompleteFunction)( pRequest);
            break;
        }
        case REQUEST_SPECIAL:
        {
            // clear request error field
            pRequest->m_dwRequestError = ERR_NOERROR;

            HANDLESPECIALREQUEST( pRequest);
            COMMSTATE = ERR_NOERROR;

            ((CCommDevice*)lParam)->m_pRequest = NULL;
            ResetEvent( COMMEVENT);

            switch( pRequest->m_dwRequestError) {
            case ERR_PORTERROR:
            case ERR_NOPORTLOCK:
            case ERR_NODATALOCK:
            {
                if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                    pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                else if( pRequest->m_pCompleteFunction)
                    (*pRequest->m_pCompleteFunction)( pRequest);
                return 1;
            }
            case ERR_TERMINATED:
            {
                if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                    pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
                else if( pRequest->m_pCompleteFunction)
                    (*pRequest->m_pCompleteFunction)( pRequest);
                return 0;
            }
            }

            if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
            else if( pRequest->m_pCompleteFunction)
                (*pRequest->m_pCompleteFunction)( pRequest);
            break;
        }
        case REQUEST_CALLBACK:
        default:
        {
            // clear any previous request errors
            pRequest->m_dwRequestError = ERR_NOERROR;

            ((CCommDevice*)lParam)->m_pRequest = NULL;
            ResetEvent( COMMEVENT);

            if( pRequest->m_pWindow && ::IsWindow( pRequest->m_pWindow->m_hWnd))
                pRequest->m_pWindow->PostMessage( WM_COMM_REQUEST_COMPLETE, 0, (long)pRequest);
            else if( pRequest->m_pCompleteFunction)
                (*pRequest->m_pCompleteFunction)( pRequest);
            break;
        }
        }
    }
}
Beispiel #13
0
/******************************************************************************
* Name: CCommDevice::Read (poll driven)
*
* Purpose: read data directly from the port
******************************************************************************/
DWORD CCommDevice::Read( LPTSTR data, DWORD dataLength, DWORD dwMaxTries, DWORD dwTimeout)
{
    DWORD dwBytesRead;
    DWORD dwTries = 1;
    LPTSTR pByte = data;

    // clear any previous error
    m_dwCommState = ERR_NOERROR;

    // initialize the data buffer
    memset( data, 0, dataLength);

    // make sure the port is not in use
    DWORD dwWait = WaitForSingleObject( m_hPortMutex, INFINITE);
    if( dwWait!=WAIT_OBJECT_0) {
        m_dwCommState = ERR_NOPORTLOCK;
        ReleaseMutex( m_hPortMutex);
        return 0;
    }

    //P	added to purge the port before read & write
    PurgeComm( m_hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

    // check for termination
    if( m_bCancel) {
        m_bCancel = FALSE;
        m_dwCommState = ERR_CANCELLED;
        PurgeComm( m_hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
        ReleaseMutex( m_hPortMutex);
        return 0;
    }
    if( m_bTerminate) {
        m_dwCommState = ERR_TERMINATED;
        PurgeComm( m_hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
        ReleaseMutex( m_hPortMutex);
        return 0;
    }

    // clear any previous errors
    DWORD errors;
    if( !ClearCommError( m_hPort, &errors, NULL)) {
        m_dwCommState = ERR_PORTERROR;
        ReleaseMutex( m_hPortMutex);
        return 0;
    }
    ASSERT( errors == NULL);

RetryRead:

    // get the data
    do
    {
        if( !ReadFile( m_hPort, pByte, 1, &dwBytesRead, NULL)) {
            m_dwCommState = ERR_PORTERROR;
            ReleaseMutex( m_hPortMutex);
            return (DWORD)(pByte - data);
        }

        // if we timed out and haven't read anything check terminate
        // and cancel operation flags otherwise just stay in the loop
        // until we receive something
        if( !dwBytesRead && !(pByte - data)) {
            if( m_bCancel) {
                m_bCancel = FALSE;
                m_dwCommState = ERR_CANCELLED;
                PurgeComm( m_hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
                ReleaseMutex( m_hPortMutex);
                return 0;
            }
            if( m_bTerminate) {
                m_dwCommState = ERR_TERMINATED;
                PurgeComm( m_hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
                ReleaseMutex( m_hPortMutex);
                return 0;
            }

            if( !dwMaxTries || dwTries < dwMaxTries) {
                dwTries++;
                dwBytesRead = 1; // don't let loop terminate
                Sleep( dwTimeout);
            }
            else m_dwCommState = ERR_MAXTRIES;
        }
        else if (dwBytesRead) { // We got a character
            if (m_bParseCRLF) {

                if (*pByte==m_EOLChar) // Use EOL's to terminate event
                    break;
                else if (*pByte!= m_LFChar)
                    pByte++;
            }
            else
                pByte++;
        }

    } while( (dwBytesRead == 1) &&
             (dataLength ? ((DWORD)(pByte - data) < dataLength) : TRUE));

    if (m_bParseCRLF) {
        *pByte = '\0';
        for(; pByte>data; pByte--) {
            if (*(pByte-1)=='\r' || *(pByte-1)=='\n')
                *(pByte-1) = '\0';
            else
                break;
        }
    }

    DWORD len = (pByte - data);

    if (m_bParseCRLF && len==0 && (!dwMaxTries || dwTries<dwMaxTries))
        goto RetryRead;

    TRACE( "Received %ld bytes: %s\n", len, data);

    ReleaseMutex( m_hPortMutex);
    return len;
}
Beispiel #14
0
bool COMPort::Purge(DWORD dwFlags) {
  return PurgeComm((HANDLE(portHandle)), dwFlags);
}
Beispiel #15
0
//
//  The CommThread Calculator.
//
UINT CSerialPort::CommThread(LPVOID pParam)
{
	// Cast the void pointer passed to the thread back to
	// a pointer of CSerialPort class
	CSerialPort *port = (CSerialPort*)pParam;

	// Set the status variable in the dialog class to
	// TRUE to indicate the thread is running.
	port->m_bThreadAlive = TRUE;	

	// Misc. variables
	DWORD BytesTransfered = 0; 
	DWORD Event = 0;
	DWORD CommEvent = 0;
	DWORD dwError = 0;
	COMSTAT comstat = {0};
	BOOL  bResult = TRUE;

	// Clear comm buffers at startup
	if (port->m_hComm)		// check if the port is opened
		PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

	// begin forever loop.  This loop will run as long as the thread is alive.
	for (;;) 
	{ 

		// Make a call to WaitCommEvent().  This call will return immediatly
		// because our port was created as an async port (FILE_FLAG_OVERLAPPED
		// and an m_OverlappedStructerlapped structure specified).  This call will cause the 
		// m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to 
		// be placed in a non-signeled state if there are no bytes available to be read,
		// or to a signeled state if there are bytes available.  If this event handle 
		// is set to the non-signeled state, it will be set to signeled when a 
		// character arrives at the port.

		// we do this for each port!

		bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);

		if (!bResult)  
		{ 
			// If WaitCommEvent() returns FALSE, process the last error to determin
			// the reason..
			switch (dwError = GetLastError()) 
			{ 
			case ERROR_IO_PENDING: 	
				{ 
					// This is a normal return value if there are no bytes
					// to read at the port.
					// Do nothing and continue
					break;
				}
			case 87:
				{
					// Under Windows NT, this value is returned for some reason.
					// I have not investigated why, but it is also a valid reply
					// Also do nothing and continue.
					break;
				}
			default:
				{
					// All other error codes indicate a serious error has
					// occured.  Process this error.
					port->ProcessErrorMessage("WaitCommEvent()");
					break;
				}
			}
		}
		else
		{
			// If WaitCommEvent() returns TRUE, check to be sure there are
			// actually bytes in the buffer to read.  
			//
			// If you are reading more than one byte at a time from the buffer 
			// (which this program does not do) you will have the situation occur 
			// where the first byte to arrive will cause the WaitForMultipleObjects() 
			// Calculator to stop waiting.  The WaitForMultipleObjects() Calculator 
			// resets the event handle in m_OverlappedStruct.hEvent to the non-signelead state
			// as it returns.  
			//
			// If in the time between the reset of this event and the call to 
			// ReadFile() more bytes arrive, the m_OverlappedStruct.hEvent handle will be set again
			// to the signeled state. When the call to ReadFile() occurs, it will 
			// read all of the bytes from the buffer, and the program will
			// loop back around to WaitCommEvent().
			// 
			// At this point you will be in the situation where m_OverlappedStruct.hEvent is set,
			// but there are no bytes available to read.  If you proceed and call
			// ReadFile(), it will return immediatly due to the async port setup, but
			// GetOverlappedResults() will not return until the next character arrives.
			//
			// It is not desirable for the GetOverlappedResults() Calculator to be in 
			// this state.  The thread shutdown event (event 0) and the WriteFile()
			// event (Event2) will not work if the thread is blocked by GetOverlappedResults().
			//
			// The solution to this is to check the buffer with a call to ClearCommError().
			// This call will reset the event handle, and if there are no bytes to read
			// we can loop back through WaitCommEvent() again, then proceed.
			// If there are really bytes to read, do nothing and proceed.

			bResult = ClearCommError(port->m_hComm, &dwError, &comstat);

			if (comstat.cbInQue == 0)
				continue;
		}	// end if bResult

		// Main wait Calculator.  This Calculator will normally block the thread
		// until one of nine events occur that require action.
		Event = WaitForMultipleObjects(3, port->m_hEventArray, FALSE, INFINITE);

		switch (Event)
		{
		case 0:
			{
				// Shutdown event.  This is event zero so it will be
				// the higest priority and be serviced first.

				port->m_bThreadAlive = FALSE;

				// Kill this thread.  break is not needed, but makes me feel better.
				AfxEndThread(100);
				break;
			}
		case 1:	// read event
			{
				GetCommMask(port->m_hComm, &CommEvent);
				if (CommEvent & EV_RXCHAR) //接收到字符,并置于输入缓冲区中 
					ReceiveChar(port, comstat);

				if (CommEvent & EV_CTS) //CTS信号状态发生变化
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_CTS_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_RXFLAG) //接收到事件字符,并置于输入缓冲区中 
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_BREAK)  //输入中发生中断
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_BREAK_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_ERR) //发生线路状态错误,线路状态错误包括CE_FRAME,CE_OVERRUN和CE_RXPARITY 
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_ERR_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);
				if (CommEvent & EV_RING) //检测到振铃指示
					::SendMessage(port->m_pOwner->m_hWnd, WM_COMM_RING_DETECTED, (WPARAM) 0, (LPARAM) port->m_nPortNr);

				break;
			}  
		case 2: // write event
			{
				// Write character event from port
				WriteChar(port);
				break;
			}

		} // end switch

	} // close forever loop

	return 0;
}
/*-------------------------------------------
| Name:startAsyncRs232
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int startAsyncRs2322(void)
{
   FILE *stream= (FILE *)0;

   uart2_config config={DFLT_SPEED,DFLT_PARITY,DFLT_DATA,DFLT_STOPBIT};

   int com_no=0;

   //const static char strConfig[]="COM1: baud=9600 parity=N data=8 stop=1";

   if( (stream  = fopen( "lepton_com.conf", "r" )) == NULL ) {
      printf( "error: lepton_com.conf was not opened\nuse default com:%s\r\n", DFLT_USE_COM);
   }else{
      printf( "lepton_com.conf was opened\n" );
      if(fscanf(stream,"com : %s",USE_COM)<0)
         printf( "cannot find com parameter\n" );
      //if com no >9 workaround with specific string format
      sscanf(USE_COM,"COM%d",&com_no);
      if(com_no>9){
         sprintf(USE_COM,"\\\\.\\COM%d",(com_no)); 
      }
   }


   hRS232PhysicalSimEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

   hCom = CreateFile(USE_COM, GENERIC_READ | GENERIC_WRITE,
                     0,
                     NULL,
                     OPEN_EXISTING,
                     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                     NULL );
   if(hCom==INVALID_HANDLE_VALUE)
      return -1;

   //set comm
   setRs2322(&config);

   // purge any information in the buffer
   PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );

   //
   ClearCommBreak(hCom);

   //
   //EscapeCommFunction( hCom, SETDTR ) ;

   // get any early notifications
   SetCommMask(hCom, EV_RXFLAG|EV_RXCHAR|EV_TXEMPTY);

   // setup device buffers
   SetupComm( hCom, 4096, 4096 );


   //
   bComStopped=COM_START;
   hComThread = CreateThread( (LPSECURITY_ATTRIBUTES) NULL,
                              0,
                              (LPTHREAD_START_ROUTINE) comThread2,
                              NULL,
                              0, &dwThreadID );
   if(hComThread==INVALID_HANDLE_VALUE)
      return -1;



   printf("uart started\n");

   return 0;
}
Beispiel #17
0
//
// Initialize the port. This can be port 1 to 4.
//
//
//parity:
//  n=none
//  e=even
//  o=odd
//  m=mark
//  s=space
//data:
//  5,6,7,8
//stop:
//  1,1.5,2 
//
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

	DWORD   ReadIntervalTimeout,
	DWORD   ReadTotalTimeoutMultiplier,
	DWORD   ReadTotalTimeoutConstant,
	DWORD   WriteTotalTimeoutMultiplier,
	DWORD   WriteTotalTimeoutConstant )	

{
	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);
	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 unsigned char[writebuffersize];

	m_nPortNr = portnr;

	m_nWriteBufferSize = writebuffersize;
	m_dwCommEvents = dwCommEvents;

	BOOL bResult = FALSE;
	char *szPort = new char[50];
	TCHAR *szBaud = new TCHAR[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
	//_stprintf(szPort, TEXT("COM%d"), portnr);
	sprintf(szPort, "COM%d", portnr);
	// 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;
	switch(parity)
	{
	case 'N':
		myparity = 0;
		break;
	case 'E':
		myparity = 1;
		break;
	case 'O':
		myparity = 2;
		break;
	case 'M':
		myparity = 3;
		break;
	case 'S':
		myparity = 4;
		break;
	}
	_stprintf_s(szBaud, 49, TEXT("baud=%d parity=%c data=%d stop=%d"), baud, parity, databits, mystop);

	// get a handle to the port
	m_hComm = CreateFileA(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
		0,//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         = ReadIntervalTimeout * 1000;
	m_CommTimeouts.ReadTotalTimeoutMultiplier  = ReadTotalTimeoutMultiplier * 1000;
	m_CommTimeouts.ReadTotalTimeoutConstant    = ReadTotalTimeoutConstant * 1000;
	m_CommTimeouts.WriteTotalTimeoutMultiplier = WriteTotalTimeoutMultiplier * 1000;
	m_CommTimeouts.WriteTotalTimeoutConstant   = WriteTotalTimeoutConstant * 1000;

	// configure
	if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
	{						   
		if (SetCommMask(m_hComm, dwCommEvents))
		{
			if (GetCommState(m_hComm, &m_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;

				if (BuildCommDCB(szBaud, &m_dcb))
				{
					if (SetCommState(m_hComm, &m_dcb))
						; // normal operation... continue
					else
					{
						DWORD dwError = GetLastError();
						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;
}
Beispiel #18
0
//清空输入输出缓冲区
BOOL ComRWTool::ClearComBuffer()
{
    return PurgeComm(m_hComm ,PURGE_TXCLEAR|PURGE_RXCLEAR);
}
Beispiel #19
0
void raw_serial::flush( _u32 flags)
{
    PurgeComm(_serial_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
}
Beispiel #20
0
Serial::Serial(char *portName)
{
	//We're not yet connected
	this->connected = false;

	//Try to connect to the given port throuh CreateFile
	this->hSerial = CreateFile(portName,
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	//Check if the connection was successfull
	if (this->hSerial == INVALID_HANDLE_VALUE)
	{
		//If not success full display an Error
		if (GetLastError() == ERROR_FILE_NOT_FOUND){

			//Print Error if neccessary
			printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);

		}
		else
		{
			printf("ERROR!!!");
		}
	}
	else
	{
		//If connected we try to set the comm parameters
		DCB dcbSerialParams = { 0 };

		//Try to get the current
		if (!GetCommState(this->hSerial, &dcbSerialParams))
		{
			//If impossible, show an error
			printf("failed to get current serial parameters!");
		}
		else
		{
			//Define serial connection parameters for the arduino board
			dcbSerialParams.BaudRate = CBR_115200;
			dcbSerialParams.ByteSize = 8;
			dcbSerialParams.StopBits = ONESTOPBIT;
			dcbSerialParams.Parity = NOPARITY;
			//Setting the DTR to Control_Enable ensures that the Arduino is properly
			//reset upon establishing a connection
			dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;

			//Set the parameters and check for their proper application
			if (!SetCommState(hSerial, &dcbSerialParams))
			{
				printf("ALERT: Could not set Serial Port parameters");
			}
			else
			{
				//If everything went fine we're connected
				this->connected = true;
				//Flush any remaining characters in the buffers 
				PurgeComm(this->hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
				//We wait 2s as the arduino board will be reseting
				Sleep(ARDUINO_WAIT_TIME);
			}
		}
	}

}
Beispiel #21
0
int
serialCancelOutput (SerialDevice *serial) {
  if (PurgeComm(serial->package.fileHandle, PURGE_TXCLEAR)) return 1;
  logWindowsSystemError("PurgeComm");
  return 0;
}
DWORD WINAPI CommMonitor( LPSTR lpData)
{
//监控串口接收数据,并完成数据格式分析,将结果放入结果队列
	CommData
	SYSTEMTIME SystemTime;
	int	 nItemCount,TrayNum,CupNum;//样本项目号,盘号,杯号
	BYTE  SampleIDLen ;//数据包功能号,样本ID长度
	WORD	wSampleNo;
	bool blogfile;
	int  i,ByteRecieved;
	bool isdataPacket=FALSE;
	char  DataBuffer[200];// 数据缓冲区!
	CHAR    TempWorkingID[c_MaxWorkingIDLength+1];//样本号,chj
	char LSampleID[5];
	Init()
	
	ResetOpPointer()				
	
	ResetRxPointer()																																																																																																															
	

 	nItemCount =0;
	FillDevName()					
	SetCommWaitMask(EV_RXCHAR)
	PurgeComm( hComm, PURGE_RXCLEAR );	
	blogfile=NewLogFile("Syn_ELISE.txt");
	WriteCommChar(XON)
	while (TRUE)
	{
		WaitEvent(EV_RXCHAR)		
		do
		{
			ReadFile(hComm, &RxChar, 1, &dwReadLength, NULL);	
			if(RxChar==STX)
				isdataPacket=TRUE;
			if(isdataPacket)
			{
				DataBuffer[i]=RxChar;
				i++;
			}
			if(RxChar==ENQ||RxChar==EOT)
			{
				break;
			}
			if(((RxChar==ETX)|(RxChar==ETB))&(isdataPacket))
			{
				//DataBuffer[i]=RxChar;
				ByteRecieved=i;
				break;
			}	
		}while(dwReadLength==1);
		i=0;
		if((RxChar==ETX))
		{
			while(DataBuffer[i]!=STX)	i++;
		}
		lpOpPointer=&DataBuffer[i];
		if (blogfile)
		{
			WriteLogData(hLogFile,lpOpPointer,ByteRecieved);
		}

		switch (RxChar) 
		{
		case ENQ:
		//	Sleep(300);
			TransmitCommChar(hComm,ACK);
			break;
		case ETB:
		case ETX:
			//先进行校验的计算,若为正常接受则进行结果处理!
			//目前,由于资料校验和的计算方法与结果包中数据不符!尚未加校验计算
			/*
			    需要到仪器上读出数据包进行分析
			*/
			switch(*(lpOpPointer+2))
			{
			case 'H':
				break;
			case 'P':
				break;
			case 'O':
				nItemCount=0;
				TrayNum=(int)StrToInt(lpOpPointer+c_TrayNumEOff,c_TrayNumLen);				
				CupNum=(int)StrToInt(lpOpPointer+c_CupNumEOff,c_CupNumLen);			
				wSampleNo =(int)StrToInt(lpOpPointer+c_SequenceNoOff,c_SequenceNoLen);
				_itoa(wSampleNo,LSampleID,10);
				TempWorkingID[0]=lpDevice->DevItemType;
				memset(&TempWorkingID[1],0x30,5);
				SampleIDLen=strlen(LSampleID);
				strncpy(&TempWorkingID[6-SampleIDLen],&LSampleID[0],SampleIDLen);
				TempWorkingID[6]='\0';
						
				break;	//继续接收	
			case 'R':
				FillSampleID(nItemCount, wSampleNo)	
				strncpy(OutResult[nItemCount].WorkingID,TempWorkingID,7);//填写工作单号
				OutResult[nItemCount].ItemNo=nItemCount+1;
				FillItemName(nItemCount,lpOpPointer+c_ItemNameOff ,c_ItemNameLen)	

				if (OutResult[nItemCount].ItemID[1]==124)//'|'  如果项目名称长度为1则添加字符串尾标志-ASCII 码值为 0
				{
					OutResult[nItemCount].ItemID[1]='\0';			
					FillResult(nItemCount,lpOpPointer+c_ResultOff-2,c_ResultLen)
				}
				else
					FillResult(nItemCount,lpOpPointer+c_ResultOff,c_ResultLen)

				OutResult[nItemCount].ItemNo=nItemCount+1;
//填日期
				GetSystemTime(&SystemTime); 
				FillDate(nItemCount, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour,SystemTime.wMinute,SystemTime.wSecond)
				nItemCount++;
				(*lpResultProcessRoutine)(lpDevice->nDevNO, &OutResult[nItemCount-1], 1);
				lpDevice->dwRecordCount+=1;  
				break;
			case 'L':
				break;
			}
		//	Sleep(300);
			TransmitCommChar(hComm,ACK);
			break;
		case EOT:
			//结果入队列
		default:
			TransmitCommChar(hComm,ACK);
			break;
		}
Beispiel #23
0
BOOL CComPort::Purge(const DWORD dwFlags) const
{
 return PurgeComm(m_hCom,dwFlags);
}
Beispiel #24
0
//
// Write a character.
//
void CSerialPort::WriteChar(CSerialPort* port)
{
	BOOL bWrite = TRUE;
	BOOL bResult = TRUE;

	DWORD BytesSent = 0;
	DWORD SendLen   = port->m_nWriteSize;
	ResetEvent(port->m_hWriteEvent);


	// Gain ownership of the critical section
	EnterCriticalSection(&port->m_csCommunicationSync);

	if (bWrite)
	{
		// Initailize variables
		port->m_ov.Offset = 0;
		port->m_ov.OffsetHigh = 0;
	 
		// Clear buffer
		PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);

		bResult = WriteFile(port->m_hComm,							// Handle to COMM Port
							port->m_szWriteBuffer,					// Pointer to message buffer in calling finction
							SendLen,	// add by mrlong
							//strlen((char*)port->m_szWriteBuffer),	// Length of message to send
							&BytesSent,								// Where to store the number of bytes sent
							&port->m_ov);							// Overlapped structure

		// deal with any error codes
		if (!bResult)  
		{
			DWORD dwError = GetLastError();
			switch (dwError)
			{
				case ERROR_IO_PENDING:
					{
						// continue to GetOverlappedResults()
						BytesSent = 0;
						bWrite = FALSE;
						break;
					}
				default:
					{
						// all other error codes
						port->ProcessErrorMessage("WriteFile()");
					}
			}
		} 
		else
		{
			LeaveCriticalSection(&port->m_csCommunicationSync);
		}
	} // end if(bWrite)

	if (!bWrite)
	{
		bWrite = TRUE;
	
		bResult = GetOverlappedResult(port->m_hComm,	// Handle to COMM port 
									  &port->m_ov,		// Overlapped structure
									  &BytesSent,		// Stores number of bytes sent
									  TRUE); 			// Wait flag

		LeaveCriticalSection(&port->m_csCommunicationSync);

		// deal with the error code 
		if (!bResult)  
		{
			port->ProcessErrorMessage("GetOverlappedResults() in WriteFile()");
		}	
	} // end if (!bWrite)

	// Verify that the data size send equals what we tried to send
	if (BytesSent != SendLen /*strlen((char*)port->m_szWriteBuffer)*/)  // add by 
	{
		//TRACE("WARNING: WriteFile() error.. Bytes Sent: %d; Message Length: %d\n", BytesSent, strlen((char*)port->m_szWriteBuffer));
	}
}
Beispiel #25
0
//////////////////////////////////////////////////////////////////////////////////////////
// Open a communication channel to the given serial port name.
XsensResultValue Cmt1s::open(
	const char* portName, const uint32_t baudRate, uint32_t readBufSize,
	uint32_t writeBufSize)
{
	MRPT_UNUSED_PARAM(readBufSize);
	MRPT_UNUSED_PARAM(writeBufSize);
	m_endTime = 0;

	CMT1LOG("L1: Open port %s at %d baud\n", portName, baudRate);

	if (m_isOpen)
	{
		CMT1LOG("L1: Port already open\n");
		return (m_lastResult = XRV_ALREADYOPEN);
	}
	m_baudrate = baudRate;

#ifdef _WIN32
	char winPortName[32];

	// Open port
	sprintf(winPortName, "\\\\.\\%s", portName);
	m_handle = CreateFileA(
		winPortName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0,
		nullptr);
	if (m_handle == INVALID_HANDLE_VALUE)
	{
		CMT1LOG("L1: Port cannot be opened\n");
		return (m_lastResult = XRV_INPUTCANNOTBEOPENED);
	}

	// Once here, port is open
	m_isOpen = true;

	// Get the current state & then change it
	GetCommState(m_handle, &m_commState);  // Get current state

	m_commState.BaudRate = baudRate;  // Setup the baud rate
	m_commState.Parity = NOPARITY;  // Setup the Parity
	m_commState.ByteSize = 8;  // Setup the data bits
	m_commState.StopBits = TWOSTOPBITS;  // Setup the stop bits
	m_commState.fDsrSensitivity = FALSE;  // Setup the flow control
	m_commState.fOutxCtsFlow = FALSE;  // NoFlowControl:
	m_commState.fOutxDsrFlow = FALSE;
	m_commState.fOutX = FALSE;
	m_commState.fInX = FALSE;
	if (!SetCommState(m_handle, (LPDCB)&m_commState))
	{  // Set new state
		// Bluetooth ports cannot always be opened with 2 stopbits
		// Now try to open port with 1 stopbit.
		m_commState.StopBits = ONESTOPBIT;
		if (!SetCommState(m_handle, (LPDCB)&m_commState))
		{
			CloseHandle(m_handle);
			m_handle = INVALID_HANDLE_VALUE;
			m_isOpen = false;
			return (m_lastResult = XRV_INPUTCANNOTBEOPENED);
		}
	}
	m_port = atoi(&portName[3]);
	sprintf(m_portname, "%s", portName);

	setTimeout(m_timeout);

	// Other initialization functions
	EscapeCommFunction(m_handle, SETRTS);  // Enable RTS (for Xbus Master use)
	// Set DTR (Calibration sensors need DTR to startup, won't hurt otherwise
	EscapeCommFunction(m_handle, SETDTR);
	SetupComm(m_handle, readBufSize, writeBufSize);  // Set queue size

	// Remove any 'old' data in buffer
	// PurgeComm(m_handle, PURGE_TXCLEAR | PURGE_RXCLEAR);
	PurgeComm(
		m_handle,
		PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
#else  // !_WIN32
	// Open port
	m_handle = ::open(portName, O_RDWR | O_NOCTTY);
	// O_RDWR: Read+Write
	// O_NOCTTY: Raw input, no "controlling terminal"
	// O_NDELAY: Don't care about DCD signal

	if (m_handle < 0)
	{
		// Port not open
		return m_lastResult = XRV_INPUTCANNOTBEOPENED;
	}

	// Once here, port is open
	m_isOpen = true;

	/* Start configuring of port for non-canonical transfer mode */
	// Get current options for the port
	tcgetattr(m_handle, &m_commState);

	// Set baudrate.
	cfsetispeed(&m_commState, baudRate);
	cfsetospeed(&m_commState, baudRate);

	// Enable the receiver and set local mode
	m_commState.c_cflag |= (CLOCAL | CREAD);
	// Set character size to data bits and set no parity Mask the characte size
	// bits
	m_commState.c_cflag &= ~(CSIZE | PARENB);
	m_commState.c_cflag |= CS8;  // Select 8 data bits
	m_commState.c_cflag |= CSTOPB;  // send 2 stop bits
	// Disable hardware flow control
	m_commState.c_cflag &= ~CRTSCTS;
	m_commState.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
	// Disable software flow control
	m_commState.c_iflag &=
		~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
	// Set Raw output
	m_commState.c_oflag &= ~OPOST;
	// Timeout 0.001 sec for first byte, read minimum of 0 bytes
	m_commState.c_cc[VMIN] = 0;
	m_commState.c_cc[VTIME] = (m_timeout + 99) / 100;  // 1

	// Set the new options for the port
	tcsetattr(m_handle, TCSANOW, &m_commState);

	m_port = 0;
	sprintf(m_portname, "%s", portName);

	tcflush(m_handle, TCIOFLUSH);

	// setting RTS and DTR; RTS for Xbus Master, DTR for calibration sensors
	int cmbits;
	if (ioctl(m_handle, TIOCMGET, &cmbits) < 0)
	{
		return (m_lastResult = XRV_ERROR);
	}

	cmbits |= TIOCM_RTS | TIOCM_DTR;

	if (ioctl(m_handle, TIOCMSET, &cmbits) < 0)
	{
		return (m_lastResult = XRV_ERROR);
	}
#endif  // !_WIN32

	CMT1LOG("L1: Port opened\n");
	return (m_lastResult = XRV_OK);
}
Beispiel #26
0
void
SerialPort::Flush()
{
  PurgeComm(hPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
  BufferedPort::Flush();
}
Beispiel #27
0
DWORD WINAPI CommMonitor( LPSTR lpData)
{
    //监控串口接收数据,并完成数据格式分析,将结果放入结果队列
	int		nItemCount,SampleIDLen,nDataOff,nResultLen,iSampleID;
	bool	bLogFile;
	char    TempWorkingID[7];
	LPSTR   lpPointer;
	//应答包
	char * p_Ack="\x2\x6\x3";
	char * p_Nak="\x2\x16\x3";
	char * p_IntSessionTXT="\x2I\x20\x3";
	char * p_ReleaseMaster="\x2M\x20\x20\x20\x20\x20\x3";
	char  PackageType;
	char SampleID[10];
	SYSTEMTIME SystemTime;
	CommData
    //通信类型1'、1''、2、3、4、5
	
	Init()
	ResetOpPointer()				

	FillDevName()					
	SetCommWaitMask(EV_RXFLAG)
	PurgeComm( hComm, PURGE_RXCLEAR );	
	memset(lpOpPointer , 0, c_RxBufferLength );
	if(NewLogFile("AEROSET.txt"))
	{
		bLogFile=TRUE;
	}

	while (TRUE)
	{


		WaitEvent(EV_RXFLAG)//等待接受数据包
		GetInQueueLength(dwReadLength)//分析数据
		ReadCommBlock(dwReadLength)
		PackageType=*(lpOpPointer+1);//数据包的类型
		if(bLogFile)
		{
			WriteLogData(hLogFile,lpOpPointer,dwReadLength);
		}
		//校验接收到的数据,若正确,则处理,否则给否定应答。
		/*
			checksum  calculation
		*/

		/*结果的数据块中可能包含病人信息、ID信息、结果数据等组。*/
		PackageType=*(lpOpPointer+1);
		switch(PackageType)
		{
		case 'Q':
			WriteCommBlock(p_Ack,3)//肯定应答
			//WriteCommChar(ACK)
			break;

		case 'R':
			//结果处理
			WriteCommBlock(p_Ack,3)//肯定应答
			iSampleID=StrToInt(lpOpPointer+c_SampleIDOff,c_SamlpeIDLen);
			itoa(iSampleID,&SampleID[0],10);
			SampleIDLen=strlen(SampleID);
			TempWorkingID[0]=lpDevice->DevItemType;
			if(SampleIDLen>=6)
			{
				strncpy(&TempWorkingID[1],&SampleID[SampleIDLen-5],5);
			}
			else
				strncpy(&TempWorkingID[6-SampleIDLen],SampleID,SampleIDLen);
			TempWorkingID[6]='\0';
			GetLocalTime(&SystemTime);
			nItemCount=0;
			for(nDataOff =c_DataOff; *(lpOpPointer+nDataOff)!=ETB ;)
			{
				strncpy(OutResult[nItemCount].WorkingID,TempWorkingID,7);
				OutResult[nItemCount].ItemNo=nItemCount+1;
				lpPointer=lpOpPointer+nDataOff;
				DeleSpace(4)
				strncpy(OutResult[nItemCount].ItemID,lpPointer,nResultLen);
				OutResult[nItemCount].ItemID[nResultLen]='\0';
				lpPointer=lpOpPointer+nDataOff+c_ResultOff;
				DeleSpace(c_ResultLen )
				FillResult(nItemCount, lpPointer ,nResultLen ) 
				FillDate(nItemCount, SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay, SystemTime.wHour,SystemTime.wMinute,SystemTime.wSecond)
				nDataOff = nDataOff + c_OneDataLen;
				nItemCount++;
			}
			if(nItemCount>0)
			{
				(*lpResultProcessRoutine)(lpDevice->nDevNO, OutResult, nItemCount);
				lpDevice->dwRecordCount+=nItemCount;
			}
		
			//WriteCommChar(ACK)
		///	WriteCommBlock(p_Ack,3)//肯定应答
			break;
		case ACK:
		case NAK:
			break;
       
		}
	

		ResetRxPointer()		
	

	}
	if(bLogFile)
	{
		CloseLogFile(hLogFile);
	}
	return TRUE;
} // end of CommWatchProc()
void EIO_Open(uv_work_t* req) {
  OpenBaton* data = static_cast<OpenBaton*>(req->data);

  // data->path is char[1024] but on Windows it has the form "COMx\0" or "COMxx\0"
  // We want to prepend "\\\\.\\" to it before we call CreateFile
  strncpy(data->path + 20, data->path, 10);
  strncpy(data->path, "\\\\.\\", 4);
  strncpy(data->path + 4, data->path + 20, 10);

  HANDLE file = CreateFile(
    data->path,
    GENERIC_READ | GENERIC_WRITE,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_OVERLAPPED,
    NULL);
  if (file == INVALID_HANDLE_VALUE) {
    DWORD errorCode = GetLastError();
    char temp[100];
    _snprintf(temp, sizeof(temp), "Opening %s", data->path);
    ErrorCodeToString(temp, errorCode, data->errorString);
    return;
  }

  bufferSize = data->bufferSize;
  if(bufferSize > MAX_BUFFER_SIZE) {
    bufferSize = MAX_BUFFER_SIZE;
  }

  DCB dcb = { 0 };
  dcb.DCBlength = sizeof(DCB);
  if(!BuildCommDCB("9600,n,8,1", &dcb)) {
    ErrorCodeToString("BuildCommDCB", GetLastError(), data->errorString);
    return;
  }

  dcb.fBinary = true;
  dcb.BaudRate = data->baudRate;
  dcb.ByteSize = data->dataBits;
  switch(data->parity) {
  case SERIALPORT_PARITY_NONE:
    dcb.Parity = NOPARITY;
    break;
  case SERIALPORT_PARITY_MARK:
    dcb.Parity = MARKPARITY;
    break;
  case SERIALPORT_PARITY_EVEN:
    dcb.Parity = EVENPARITY;
    break;
  case SERIALPORT_PARITY_ODD:
    dcb.Parity = ODDPARITY;
    break;
  case SERIALPORT_PARITY_SPACE:
    dcb.Parity = SPACEPARITY;
    break;
  }
  switch(data->stopBits) {
  case SERIALPORT_STOPBITS_ONE:
    dcb.StopBits = ONESTOPBIT;
    break;
  case SERIALPORT_STOPBITS_ONE_FIVE:
    dcb.StopBits = ONE5STOPBITS;
    break;
  case SERIALPORT_STOPBITS_TWO:
    dcb.StopBits = TWOSTOPBITS;
    break;
  }

  if(!SetCommState(file, &dcb)) {
    ErrorCodeToString("SetCommState", GetLastError(), data->errorString);
    return;
  }

  // Set the com port read/write timeouts
  DWORD serialBitsPerByte = 8/*std data bits*/ + 1/*start bit*/;
  serialBitsPerByte += (data->parity   == SERIALPORT_PARITY_NONE ) ? 0 : 1;
  serialBitsPerByte += (data->stopBits == SERIALPORT_STOPBITS_ONE) ? 1 : 2;
  DWORD msPerByte = (data->baudRate > 0) ?
                    ((1000 * serialBitsPerByte + data->baudRate - 1) / data->baudRate) :
                    1;
  if (msPerByte < 1) {
    msPerByte = 1;
  }
  COMMTIMEOUTS commTimeouts = {0};
  commTimeouts.ReadIntervalTimeout = msPerByte; // Minimize chance of concatenating of separate serial port packets on read
  commTimeouts.ReadTotalTimeoutMultiplier  = 0; // Do not allow big read timeout when big read buffer used
  commTimeouts.ReadTotalTimeoutConstant    = 1000; // Total read timeout (period of read loop)
  commTimeouts.WriteTotalTimeoutConstant   = 1000; // Const part of write timeout
  commTimeouts.WriteTotalTimeoutMultiplier = msPerByte; // Variable part of write timeout (per byte)
  if(!SetCommTimeouts(file, &commTimeouts)) {
    ErrorCodeToString("SetCommTimeouts", GetLastError(), data->errorString);
    return;
  }

  // Remove garbage data in RX/TX queues
  PurgeComm(file, PURGE_RXCLEAR);
  PurgeComm(file, PURGE_TXCLEAR);

  data->result = (int)file;
}
/*!
 * Open the specified device at a specified baud and create a new device handle
 * \param[in]	deviceName			Device name / address (COM21 , /dev/ttys0, depending on platform)
 * \param[in]	baudRate			Baudrate to be used
 * \param[out]	pHandle				Device handle returned
 * \return							SBG_NO_ERROR if the device could be oppened properly
 */
SbgErrorCode sbgDeviceOpen(const char *deviceName, uint32 baudRate, SbgDeviceHandle *pHandle)
{
	char errorMsg[256];
	char comPortPath[32];
	COMMTIMEOUTS comTimeOut;
	DCB comState;
	uint32 deviceNum;
	HANDLE hSerialDevice;

	//
	// First check if we have a valid pHandle
	//
	if (pHandle)
	{
		//
		// Extract device number
		//
		if (sscanf_s(deviceName, "COM%i", &deviceNum) == 1)
		{
			//
			// Build our com port path
			//
			sprintf_s(comPortPath, 32, "\\\\.\\COM%i", deviceNum);

			//
			// Init our com port
			//
			hSerialDevice = CreateFile(comPortPath, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

			if (hSerialDevice != INVALID_HANDLE_VALUE)
			{
				//
				// Define our device handle
				//
				*pHandle = hSerialDevice;

				//
				// Purge our com port
				//
				if (PurgeComm(hSerialDevice, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
				{
					//
					// Retreives current com state and com timeout
					//
					if ( (GetCommState(hSerialDevice, &comState)) && (GetCommTimeouts(hSerialDevice, &comTimeOut)) )
					{
						//
						// Define common attributes
						//
						comState.BaudRate= baudRate;
						comState.Parity= NOPARITY;
						comState.ByteSize= 8;
						comState.StopBits= ONESTOPBIT;

						//
						// Disable flow control
						//
						comState.fDsrSensitivity = FALSE;
						comState.fOutxCtsFlow = FALSE;
						comState.fOutxDsrFlow = FALSE;
						comState.fOutX = FALSE;
						comState.fInX = FALSE;

						//
						// Define timeout attributes (0 ms read timeout)
						//
						comTimeOut.ReadIntervalTimeout = MAXDWORD;
						comTimeOut.ReadTotalTimeoutMultiplier = 0;
						comTimeOut.ReadTotalTimeoutConstant = 0;

						comTimeOut.WriteTotalTimeoutConstant = 0;
						comTimeOut.WriteTotalTimeoutMultiplier = 0;
						

						//
						// Configure our com port
						//
						if ( (SetCommState(hSerialDevice, &comState)) && (SetCommTimeouts(hSerialDevice, &comTimeOut)) )
						{
							//
							// Wait until our com port has been configured by windows
							//
							sbgSleep(60);

							//
							// Define our COM port buffer size
							//
							if (SetupComm(hSerialDevice, SBG_SERIAL_RX_BUFFER_SIZE, SBG_SERIAL_TX_BUFFER_SIZE))
							{
								//
								// Purge our communication
								//
								return sbgDeviceFlush(hSerialDevice);
							}
							else
							{
								sbgGetWindowsErrorMsg(errorMsg);
								fprintf(stderr, "sbgDeviceOpen: Unable to define buffer size: %s.\n", errorMsg);
							}
						}
						else
						{
							sbgGetWindowsErrorMsg(errorMsg);
							fprintf(stderr, "sbgDeviceOpen: Unable to set com state and/or timeout: %s.\n", errorMsg);
						}
					}
					else
					{
						sbgGetWindowsErrorMsg(errorMsg);
						fprintf(stderr, "sbgDeviceOpen: Unable to retreive com state and/or timeout: %s.\n", errorMsg);
					}
				}
				else
				{
					sbgGetWindowsErrorMsg(errorMsg);
					fprintf(stderr, "sbgDeviceOpen: Unable to purge com port %i: %s.\n", deviceNum, errorMsg);
				}

				//
				// Close our device if only some part has been initialised
				//
				sbgDeviceClose(hSerialDevice);
			}
			else
			{
				//
				// We have an invalid device handle
				//
				*pHandle = SBG_INVALID_DEVICE_HANDLE;
				
				sbgGetWindowsErrorMsg(errorMsg);
				fprintf(stderr, "sbgDeviceOpen: Unable to open com port %i: %s\n", deviceNum, errorMsg);
			}

			return SBG_ERROR;
		}
		else
		{
			fprintf(stderr, "sbgDeviceOpen: Invalid deviceName: %s\n", deviceName);
			return SBG_INVALID_PARAMETER;
		}
	}
	else
	{
		fprintf(stderr, "sbgDeviceOpen: pHandle == NULL for deviceName: %s\n", deviceName);
		return SBG_NULL_POINTER;
	}
}