|
此程序是我自己参考了VictorComm(VCL控件)写的串口程序,使用时除2303会蓝屏(不管什么系统,WIN7也蓝),其它类型端口使用正常
发上来让大家看看会有什么问题
先谢了
初始化:
- SerialPort::SerialPort(char* portname,int baudrate,CTCParity parity,CTCStopBits stopbits,BYTE ByteSize)
- {
- //char tmp[50];
- _Opened = false;
- _bFromHandle = false;
- _DisableWrite = false;
- _isReading = false;
- std::string tmp = std::string(portname).substr(3);
- _PortNo = atoi(tmp.c_str()); //"COM1"
- _PortName = std::string(portname);
- _HwInSize = 1200;
- _HwOutSize = 1200;
- //---- DCB settings ----//
- memset(&_dcb, 0, sizeof(DCB)); //Clear DCB
- _dcb.DCBlength = sizeof(DCB); //DWORD: sizeof(DCB)
- _dcb.BaudRate = baudrate; //DWORD: current baud rate
- _dcb.Parity = parity; //BYTE : 0-4=no,odd,even,mark,space
- _dcb.ByteSize = ByteSize; //BYTE : number of bits/byte, 4-8
- _dcb.StopBits = stopbits; //BYTE : 0,1,2 = 1, 1.5, 2
- _dcb.fBinary = true; //DWORD: binary mode, no EOF check
- if(parity!=NoParity)
- {
- _dcb.fParity = true; //DWORD: enable parity checking
- }
- else
- {
- _dcb.fParity = false; //DWORD: enable parity checking
- }
- _dcb.fOutxCtsFlow = false; //DWORD: CTS output flow control
- _dcb.fOutxDsrFlow = false; //DWORD: DSR output flow control
- _dcb.fDtrControl = DTR_CONTROL_ENABLE; //DWORD: DTR flow control type
- _dcb.fDsrSensitivity = false; //DWORD: DSR sensitivity
- _dcb.fTXContinueOnXoff = false; //DWORD: XOFF continues Tx
- _dcb.fOutX = false; //DWORD: XON/XOFF out flow control
- _dcb.fInX = false; //DWORD: XON/XOFF in flow control
- _dcb.fErrorChar = false; //DWORD: enable error replacement
- _dcb.fNull = false; //DWORD: enable null stripping
- _dcb.fRtsControl = RTS_CONTROL_ENABLE; //DWORD: RTS flow control
- _dcb.fAbortOnError = false; //WORD : abort reads/writes on error
- _dcb.XonLim = 2048; //0xffff; //WORD : transmit XON threshold
- _dcb.XoffLim = 512; //0xffff; //WORD : transmit XOFF threshold
- _dcb.XonChar = 0x11; //char : Tx and Rx XON character
- _dcb.XoffChar = 0x13; //char : Tx and Rx XOFF character
- _dcb.ErrorChar = 0; //char : error replacement character
- _dcb.EofChar = 0; //char : end of input character
- _dcb.EvtChar = 0; //char : received event character
- //---- Variables ----//
- _ModemStatus = 0; //MS_CTS_ON | MS_DSR_ON | MS_RING_ON | MS_RLSD_ON
- _Handle = INVALID_HANDLE_VALUE;
- _ReadThreadId = -1;
- _RunReadThread = 0;
- _ReadThreadRunning = 0;
- _WriteThreadId = -1;
- _RunWriteThread = 0;
- _WriteThreadRunning = 0;
- _dwTimerInterval = 10; //5 ms
- _FrameReceiveTimeOutCnt=0;
- _iSkipTimerEvents = 0; //no skip
- _bTimerThreadRunning = false; //not running
- _bRunTimerThread = true; //run enabled
- _hKillRead = 0;
- _hKillWrite = 0;
- _hSyncWrite = 0;
- memset(&_ReadOS, 0, sizeof(OVERLAPPED));
- memset(&_WriteOS, 0, sizeof(OVERLAPPED));
- _ReadBuffer = new CircularBuffer();
- _WriteBuffer = new CircularBuffer();
- _ReadFrameBuffer = new CircularBuffer();
- _hFrameReceivedEvent = CreateEvent(NULL, false, false, NULL); //Create Auto-Reset Event
- _isFrameMode = false;
- _hSemaphore = CreateSemaphore(NULL,1, 1, NULL);
- }
复制代码
打开串口:
- bool SerialPort::Open(bool isFrameMode)
- {
- if(!_Opened)
- {
- CTErrorCode ecErrCode = SerialPort::COMM_NOERROR;
- if((!ecErrCode) && (!_bFromHandle)) //如果已知句柄,不需要打开端口
- {
- wchar_t *sDeviceName = new wchar_t[50];
- wsprintf(sDeviceName,L"\\\\.\\COM%d",_PortNo);
- _Handle=CreateFile(sDeviceName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);
- if(_Handle==INVALID_HANDLE_VALUE)
- {
- ecErrCode = SerialPort::COMM_OPENPORT; //不能打开端口
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能打开端口";
- }
- }
- if((!ecErrCode) && (!SetCommMask(_Handle, EV_RXFLAG/*0x1fb*/)))
- {
- ecErrCode = SerialPort::COMM_SETMASK; //不能设置端口事件MASK
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能设置端口事件MASK";
- }
- if((!ecErrCode) && (!_bFromHandle)) //如果已知句柄,不需要设置缓存
- {
- if(!SetupComm(_Handle, _HwInSize, _HwOutSize))
- {
- ecErrCode = SerialPort::COMM_BUFSIZE; //不能设置端口缓存
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能设置端口缓存";
- }
- }
- if(!ecErrCode)
- {
- if(!_bFromHandle)
- {
- //设置预先设定的 DTR 和 RTS 值
- if(_dcb.fDtrControl != DTR_CONTROL_HANDSHAKE)
- {
- _dcb.fDtrControl = DTR_CONTROL_DISABLE;
- }
- if((_dcb.fRtsControl != RTS_CONTROL_HANDSHAKE) && (_dcb.fRtsControl != RTS_CONTROL_TOGGLE))
- {
- _dcb.fRtsControl = RTS_CONTROL_DISABLE;
- }
- DCB dcb = _dcb; //设定串口参数
- if(!SetCommState(_Handle, &dcb))
- {
- ecErrCode = SerialPort::COMM_SETSTATE; //不能设置端口参数
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能设置端口参数";
- }
- }
- else //如果已知句柄,不需要设置参数
- {
- DCB dcb;
- if(GetCommState(_Handle, &dcb))
- {
- dcb.fAbortOnError = false;
- if(!SetCommState(_Handle, &dcb))
- {
- ecErrCode = SerialPort::COMM_SETSTATE; //不能设置端口参数
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能设置端口参数";
- }
- }
- else
- {
- ecErrCode = SerialPort::COMM_GETSTATE; //不能得到端口参数
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能得到端口参数";
- }
- }
- }
- if(!ecErrCode)
- {
- memset(&_ReadOS, 0, sizeof(OVERLAPPED));
- _ReadOS.hEvent = CreateEvent(NULL,true,false,NULL);
- _hKillRead = CreateEvent(NULL,true,false,NULL);
- if((!_hKillRead) || (!_ReadOS.hEvent))
- {
- ecErrCode = SerialPort::COMM_CRRDEVENT; //不能创建端口异步读事件
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能创建端口异步读事件";
- }
- }
- if(!ecErrCode)
- {
- memset(&_WriteOS, 0, sizeof(OVERLAPPED));
- _WriteOS.hEvent = CreateEvent(NULL, true, false, NULL);
- _hSyncWrite = CreateEvent(NULL, true, false, NULL);
- _hKillWrite = CreateEvent(NULL, true, false, NULL);
- if((!_hKillWrite) || (!_hSyncWrite) || (!_WriteOS.hEvent))
- {
- ecErrCode = SerialPort::COMM_CRWREVENT; //不能创建端口异步写事件
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能创建端口异步写事件";
- }
- }
- if(!ecErrCode)
- {
- _RunReadThread = 1;
- if((_ReadThreadId=_beginthread(_ReadThread, 4096, this))==-1)
- {
- _RunReadThread = 0;
- ecErrCode = SerialPort::COMM_CRRDTHREAD; //不能创建端口读线程
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能创建端口读线程";
- }
- }
- if(!ecErrCode)
- {
- _RunWriteThread = 1;
- if((_WriteThreadId=_beginthread(_WriteThread, 4096, this))==-1)
- {
- _RunWriteThread = 0;
- ecErrCode = SerialPort::COMM_CRWRTHREAD; //不能创建端口写线程
- LOG(ERROR)<<"SerialPort::Open->ecErrCode:不能创建端口写线程";
- }
- }
- if(!ecErrCode)
- {
- SetThreadPriority((HANDLE)_ReadThreadId,THREAD_PRIORITY_HIGHEST);
- //SetThreadPriority((HANDLE)_WriteThreadId,THREAD_PRIORITY_HIGHEST);
- _Opened = true;
- _DisableWrite = false;
- DWORD dwMs; //MS_CTS_ON | MS_DSR_ON | MS_RING_ON | MS_RLSD_ON
- if(GetCommModemStatus(_Handle, &dwMs)) //Get modem status after port opened
- _ModemStatus = dwMs;
- if(isFrameMode)
- {
- _isFrameMode = true;
- //init timer
- _hTimerEvent = CreateEvent(NULL, false, false, NULL); //Create Auto-Reset Event
- _hFrameReceivedEvent = CreateEvent(NULL, false, false, NULL); //Create Auto-Reset Event
- _hTimerThreadId = _beginthread(_fnTimerThread, 4096, this);
- }
- return true;
- }
- else
- {
- Close();
- //throw std::exception(_PortName.c_str(),ecErrCode);
- return false;
- }
- }
- }
复制代码
两种方式读线程:
- #ifdef READTHREAD_ON_EVENT
- ////////////////////////////////////////////////
- /*
- *
- * 事件方式收取串口数据
- *
- * */
- void SerialPort::_ReadThread(void *Param)
- {
- SerialPort *Comm = (SerialPort *) Param;
- Comm->_ReadThreadRunning = 1;
- COMSTAT ComStat;
- const int RecvBufSize = 2048;
- char RecvBuf[RecvBufSize];
- DWORD dwErrorFlag, dwBytes, BytesToRead, BytesRemain;
- OVERLAPPED os;
- DWORD dwEvtMask, dwModemStatus;
- os.hEvent = CreateEvent(NULL, true, false, NULL);
- if(os.hEvent)
- {
- DWORD dwMask = EV_RXCHAR|EV_TXEMPTY|EV_ERR
- /*: EV_RXCHAR|EV_TXEMPTY|EV_CTS|EV_DSR|EV_RING|EV_RLSD|EV_RXFLAG|EV_RX80FULL|EV_ERR*/;
- if(SetCommMask(Comm->_Handle, dwMask))
- {
- HANDLE StatusWaits[2] = {Comm->_hKillRead, os.hEvent};
- while(Comm->_RunReadThread)
- {
- dwEvtMask = 0;
- if(!WaitCommEvent(Comm->_Handle, &dwEvtMask, &os))
- {
- if(GetLastError() == ERROR_IO_PENDING)
- {
- if(WaitForMultipleObjects(2, StatusWaits, false, INFINITE) == WAIT_OBJECT_0)
- break;
- }
- }
- if(!Comm->_RunReadThread)
- break;
- if(dwEvtMask & EV_RXCHAR)
- {
- ClearCommError(Comm->_Handle, &dwErrorFlag, &ComStat);
- BytesRemain = ComStat.cbInQue;
- while(BytesRemain>0)
- {
- BytesToRead = BytesRemain<RecvBufSize?BytesRemain:RecvBufSize;
- if(ReadFile(Comm->_Handle, RecvBuf, BytesToRead, &dwBytes, &Comm->_ReadOS))
- {
- Comm->_ReadBuffer->In(RecvBuf, dwBytes);
- BytesRemain-=dwBytes;
- }
- else
- {
- DWORD dwError = GetLastError();
- if(dwError==ERROR_IO_PENDING)
- {
- if(GetOverlappedResult(Comm->_Handle, &Comm->_ReadOS, &dwBytes, false))
- {
- Comm->_ReadBuffer->In(RecvBuf, dwBytes);
- BytesRemain-=dwBytes;
- }
- }
- }
- }
- }
- if(dwEvtMask & EV_TXEMPTY)
- {
- }
- if(dwEvtMask & EV_ERR)
- {
- ClearCommError(Comm->_Handle, &dwErrorFlag, &ComStat);
- }
- }
- }
- CloseHandle(os.hEvent);
- }
- Comm->_ReadThreadRunning = 0;
- }
- #else
- ////////////////////////////////////////////////
- /*
- *
- * 查询方式收取串口数据
- *
- * */
- void SerialPort::_ReadThread(void *Param)
- {
- SerialPort *Comm = (SerialPort *) Param;
- Comm->_ReadThreadRunning = 1;
- const int RecvBufSize = 2048;
- char RecvBuf[RecvBufSize];
- DWORD dwErrorFlag, dwBytes, BytesRemain, BytesToRead;
- COMSTAT ComStat;
- while(Comm->_RunReadThread)
- {
- if(!Comm->_RunReadThread)
- break;
- ClearCommError(Comm->_Handle, &dwErrorFlag, &ComStat);
- BytesRemain = ComStat.cbInQue;
- while(BytesRemain>0)
- {
- BytesToRead = BytesRemain<RecvBufSize?BytesRemain:RecvBufSize;
- if(ReadFile(Comm->_Handle, RecvBuf, BytesToRead, &dwBytes, &Comm->_ReadOS))
- {
- Comm->_ReadBuffer->In(RecvBuf,dwBytes);
- BytesRemain-=dwBytes;
- }
- Sleep(0);
- }
- Sleep(10);
- }
- Comm->_ReadThreadRunning = 0;
- }
- #endif
复制代码
写线程:
- void SerialPort::_WriteThread(void *Param)
- {
- SerialPort *Comm = (SerialPort *) Param;
- Comm->_WriteThreadRunning = 1;
- const int SendBufSize = 512;
- char SendBuf[SendBufSize];
- DWORD BytesSent=0, BytesToSend=0;
- COMSTAT ComStat;
- DWORD dwErrorFlag, dwBytesWr;
- DWORD dwSingled;
- HANDLE MainWaits[2] = {Comm->_hKillWrite, Comm->_hSyncWrite};
- HANDLE OvlWriteWaits[2] = {Comm->_hKillWrite, Comm->_WriteOS.hEvent};
- while(Comm->_RunWriteThread)
- {
- dwSingled = WaitForMultipleObjects(2, MainWaits, false, INFINITE);
- if((!Comm->_RunWriteThread) || (dwSingled==WAIT_OBJECT_0))
- break;
- ResetEvent(Comm->_hSyncWrite);
- if(BytesSent<BytesToSend)
- {
- if(WriteFile(Comm->_Handle, SendBuf+BytesSent, BytesToSend-BytesSent, &dwBytesWr, &Comm->_WriteOS))
- {
- BytesSent+=dwBytesWr;
- //LOG(INFO)<<"SerialPort::_WriteThread->dwBytesWr:"<<dwBytesWr;
- }
- else if(GetLastError()==ERROR_IO_PENDING)
- {
- dwSingled = WaitForMultipleObjects(2, OvlWriteWaits, false, INFINITE);
- if((!Comm->_RunWriteThread) || (dwSingled==WAIT_OBJECT_0))
- break;
- if(GetOverlappedResult(Comm->_Handle, &Comm->_WriteOS, &dwBytesWr, false))
- BytesSent+=dwBytesWr;
- }
- if(BytesSent<BytesToSend)
- {
- SetEvent(Comm->_hSyncWrite);
- }
- Sleep(0);
- }
- else if(Comm->_WriteBuffer->Count()>0)
- {
- BytesSent = 0;
- BytesToSend = Comm->_WriteBuffer->Out(SendBuf, SendBufSize);
- SetEvent(Comm->_hSyncWrite);
- }
- }
- Comm->_WriteThreadRunning = 0;
- }
复制代码
帧读取:
- void SerialPort::_TimerThread(void)
- {
- DWORD dwWait;
- const long BufSize = 20480;
- char Buf[BufSize];
- volatile long nRead;
- //std::string sss;
- //__try
- {
- _bTimerThreadRunning = true;
- while(_bRunTimerThread)
- {
- dwWait = (_Opened && _isFrameMode) ? _dwTimerInterval : INFINITE;
- WaitForSingleObject(_hTimerEvent,dwWait);
- if((_Opened&&_bRunTimerThread) && (_isFrameMode))
- {
- //如果这个_dwTimerInterval时间内没有收到数据,那就收超时,产生一个_OnFrameReceivedEventHandler事件
- nRead = Read(Buf,BufSize);
- if(nRead==0)
- {
- if(_isReading)
- {
- _FrameReceiveTimeOutCnt++;
- if(_FrameReceiveTimeOutCnt>5)//如果没读到数据超过5次,认为帧超时
- {
- //LOG(INFO)<<"_TimerThread.SetEvent._FrameReceiveTimeOutCnt:"<<_FrameReceiveTimeOutCnt;
- SetEvent(_hFrameReceivedEvent);
- _FrameReceiveTimeOutCnt=0;
- }
- }
- }
- else if(nRead>0)//如果读到数据了,那就写到帧缓冲区中,并清掉超时计数器
- {
- _isReading = true;
- _ReadFrameBuffer->In(Buf,nRead);
- _FrameReceiveTimeOutCnt=0;
- }
- }
- }
- }
- //__finally
- {
- _bTimerThreadRunning = false;
- }
- }
复制代码 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
阿莫论坛20周年了!感谢大家的支持与爱护!!
你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。
|