C++程序,打开串口时GetLastError返回错误值87

ylongwu 2012-12-29 04:50:06
问题是这样的,如果单独运行我的程序,则能正确打开串口并写入数据。但是如果先通过“串口专家”这个软件打开串口,再关闭串口,接着再用我的程序来打开串口,则GetlastError返回87。 请问这是怎么回事呢?

另外还有一个现象,有时先通过“串口专家”这个软件打开串口,再关闭串口,接着再用我的程序来打开串口,也能正确打开,但是接收到的数据或出现分段的现象,也就是不能一次完整接收
...全文
967 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
花开花折 2013-10-20
  • 打赏
  • 举报
回复
哎呀,我现在也遇到这个问题啊,错误码87
lr2131 2012-12-30
  • 打赏
  • 举报
回复
感觉应该是串口的设置和操作有问题: 1.查一下串口双方的串口设置是不是全部对应的。 2.你的程序在每次打开串口时有没有清除串口数据,然后才是收发数据。退出时有没有现式的关闭串口呢。
ylongwu 2012-12-30
  • 打赏
  • 举报
回复
bool CReadComThread::SetBreakEvent(DWORD& dwMask ) { SetBegin: if(this->m_pPort->GetSerialPort()->WaitEvent(dwMask,this->m_BreakOverlapped)) { if(!this->HandleBreakEvent(dwMask)) return false; goto SetBegin; } DWORD error=::GetLastError(); if(error==ERROR_IO_PENDING) { return true; } else { return false; } } bool CReadComThread::HandleBreakEvent(DWORD dwMask) { DWORD dwReadBytes; bool successed= this->m_pPort->GetSerialPort()->GetOverlappedResult(this->m_BreakOverlapped,dwReadBytes,false); if(successed) { this->m_pPort->ComBreak(dwMask); //调用处理过程 return true; } return false; } void CReadComThread::Execute() { if(this->m_pPort->GetReceiveMode()==CComPort::ManualReceiveByQuery) { this->ExecuteByManualQueryRecvMode(); } else if(this->m_pPort->GetReceiveMode()==CComPort::ManualReceiveByConst) { this->ExecuteByManualConstRecvMode(); } else if(this->m_pPort->GetReceiveMode()==CComPort::AutoReceiveBySignal) { this->ExecuteByAutoSignalRecvMode(); } else//中断模式 { this->ExecuteByAutoBreakRecvMode(); } } void CReadComThread::ExecuteByAutoSignalRecvMode() { DWORD dwMask=0; HANDLE WaitHandles[3]; //监听事件数组 DWORD dwSignaledHandle; //DWORD dwStoredFlags = EV_ERR | EV_RLSD | EV_RING; DWORD dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\ EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ; WaitHandles[0] = this->m_pPort->GetCloseHandle(); WaitHandles[1] = this->m_ReadOverlapped.hEvent; WaitHandles[2] = this->m_BreakOverlapped.hEvent; this->m_pPort->GetSerialPort()->SetMask(dwStoredFlags); if(!SetBreakEvent(dwMask)) goto EndThread; //设置读事件 if(!SetReadEvent(this->m_ReadOverlapped)) goto EndThread; //设置comEvent for(;;) { dwSignaledHandle=::WaitForMultipleObjects(3,WaitHandles,false,INFINITE); switch(dwSignaledHandle) { case WAIT_OBJECT_0: goto EndThread; break; case WAIT_OBJECT_0+1: if(!this->HandleReadEvent(this->m_ReadOverlapped)) goto EndThread; if(!this->SetReadEvent(this->m_ReadOverlapped)) goto EndThread; break; case WAIT_OBJECT_0+2: if(!this->HandleBreakEvent(dwMask)) goto EndThread; if(!this->SetBreakEvent(dwMask)) goto EndThread; break; default: //goto EndThread; break; } } EndThread: this->m_pPort->GetSerialPort()->Purge(PURGE_RXABORT | PURGE_RXCLEAR); ::CloseHandle(this->m_ReadOverlapped.hEvent); ::CloseHandle(this->m_BreakOverlapped.hEvent); return ; } void CReadComThread::ExecuteByManualQueryRecvMode() { DWORD dwMask=0; HANDLE WaitHandles[2]; //监听事件数组 DWORD dwSignaledHandle; WaitHandles[0] = this->m_pPort->GetCloseHandle(); /*this->m_pPort->GetSerialPort()->SetMask(dwStoredFlags); this->m_pPort->GetSerialPort()->SetBreak(); */ for(;;) { dwSignaledHandle=::WaitForMultipleObjects(1,WaitHandles,false,INFINITE); switch(dwSignaledHandle) { case WAIT_OBJECT_0: goto EndThread; break; default: //goto EndThread; break; } this->m_pPort->GetSerialPort()->GetMask(dwMask); if(dwMask>0) { this->m_pPort->ComBreak(dwMask); } } EndThread: this->m_pPort->GetSerialPort()->Purge(PURGE_RXABORT | PURGE_RXCLEAR); return ; } void CReadComThread::ExecuteByManualConstRecvMode() { DWORD dwMask=0; HANDLE WaitHandles[2]; //监听事件数组 DWORD dwSignaledHandle; DWORD dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\ EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ; WaitHandles[0] = this->m_pPort->GetCloseHandle(); WaitHandles[1] = this->m_BreakOverlapped.hEvent; this->m_pPort->GetSerialPort()->SetMask(dwStoredFlags); if(!SetBreakEvent(dwMask)) goto EndThread; //设置comEvent for(;;) { dwSignaledHandle=::WaitForMultipleObjects(2,WaitHandles,false,INFINITE); switch(dwSignaledHandle) { case WAIT_OBJECT_0: goto EndThread; break; case WAIT_OBJECT_0+1: if(!this->HandleBreakEvent(dwMask)) goto EndThread; if(!this->SetBreakEvent(dwMask)) goto EndThread; break; default: //goto EndThread; break; } } EndThread: this->m_pPort->GetSerialPort()->Purge(PURGE_RXABORT | PURGE_RXCLEAR); ::CloseHandle(this->m_ReadOverlapped.hEvent); ::CloseHandle(this->m_BreakOverlapped.hEvent); return ; } void CReadComThread::ExecuteByAutoBreakRecvMode() { DWORD dwMask=0; HANDLE WaitHandles[2]; //监听事件数组 DWORD dwSignaledHandle; DWORD dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\ EV_RLSD | EV_RXCHAR | EV_RXFLAG ;//??| EV_TXEMPTY 添加后在首次执行时总是接收不到全部数据 WaitHandles[0] = this->m_pPort->GetCloseHandle(); WaitHandles[1] = this->m_BreakOverlapped.hEvent; this->m_pPort->GetSerialPort()->SetMask(dwStoredFlags); //this->m_BreakOverlapped??两个事件同时给一个重叠结果的话?? if(!SetBreakEvent(dwMask)) goto EndThread; //设置读事件 if(!SetReadEvent(this->m_BreakOverlapped)) goto EndThread; //设置comEvent for(;;) { dwSignaledHandle=::WaitForMultipleObjects(2,WaitHandles,false,INFINITE); switch(dwSignaledHandle) { case WAIT_OBJECT_0: goto EndThread; break; case WAIT_OBJECT_0+1: if((dwMask&EV_RXCHAR)==EV_RXCHAR) { if(!this->HandleReadEvent(this->m_BreakOverlapped)) goto EndThread; if(!SetReadEvent(this->m_BreakOverlapped)) goto EndThread; } else { if(!this->HandleBreakEvent(dwMask)) goto EndThread; if(!this->SetBreakEvent(dwMask)) goto EndThread; } break; default: //goto EndThread; break; } } EndThread: this->m_pPort->GetSerialPort()->Purge(PURGE_RXABORT | PURGE_RXCLEAR); ::CloseHandle(this->m_ReadOverlapped.hEvent); ::CloseHandle(this->m_BreakOverlapped.hEvent); return ; } DWORD WINAPI ThreadFunc(LPVOID lpParam ) { CReadComThread* pThread =(CReadComThread*)lpParam; ASSERT(pThread); pThread->m_IsTerminated = false; pThread->Execute(); pThread->m_IsTerminated = true; return 0; } void CReadComThread::Create() { m_hThread = CreateThread( NULL, // no security attributes 0, // use default stack size ThreadFunc, // thread function this, // argument to thread function CREATE_SUSPENDED, // use default creation flags &dwThreadId); // returns the thread identifier ::SetThreadPriority(m_hThread,THREAD_PRIORITY_HIGHEST); } void CReadComThread::Terminate() { //char szMsg[80]; if (m_hThread == NULL) { // wsprintf(szMsg,_T("CreateThread failed.") ); //::MessageBox(NULL,szMsg,_T("ok"),0); } else { if(!this->IsTerminated()) { Sleep(1000); } if(!this->IsTerminated()) { Sleep(1000); //::TerminateThread(m_hThread,0); } CloseHandle( m_hThread ); } } void CReadComThread::Resume() { ResumeThread(this->m_hThread); } void CReadComThread::BandSerialPort(CComPort* pPort) { ASSERT(pPort); this->m_pPort = pPort; //创建异步读取事件 if(this->m_pPort->IsOverlapped()) { this->m_ReadOverlapped.hEvent =::CreateEvent(NULL,true,false,NULL); ASSERT(this->m_ReadOverlapped.hEvent); this->m_BreakOverlapped.hEvent = ::CreateEvent(NULL,true,false,NULL); ASSERT(this->m_BreakOverlapped.hEvent); } } DWORD CReadComThread::ReadInput(void* pBuf,DWORD Count,DWORD dwMilliseconds) { DWORD dwRead=0; if(!this->m_pPort->GetSerialPort()->Read(pBuf,Count,this->m_ReadOverlapped,&dwRead)) { if(WaitForSingleObject(this->m_ReadOverlapped.hEvent,dwMilliseconds)==WAIT_OBJECT_0) { this->m_pPort->GetSerialPort()->GetOverlappedResult(this->m_ReadOverlapped,dwRead,false); } } return dwRead; } }
ylongwu 2012-12-30
  • 打赏
  • 举报
回复
程序源码如下 大家帮忙看看! // ComPort.cpp : 实现文件 // #include "stdafx.h" #include "ComPort.h" namespace LsComm{ // CComPort CComPort::CComPort() : m_bIsOpen(false) { this->m_pfnOnReceiveData = NULL; this->m_pfnOnComBreak =NULL; this->m_pPort = NULL; this->m_pReadThread = NULL; ::ZeroMemory(&this->m_WriteOverlapped,sizeof(this->m_WriteOverlapped)); this->m_hWriteEvent = NULL; this->m_bIsOpen = false; } CComPort::~CComPort() { if(this->m_pPort) { if(this->m_pPort->IsOpen()) { this->Close(); } } if(this->m_pPort) { delete this->m_pPort; this->m_pPort = NULL; } } // CComPort 成员函数 // //当前串口是否打开 bool CComPort::IsOpen(void) { return this->m_bIsOpen; } bool CComPort::Open(int nPort,ReceiveMode mode, DWORD dwBaud, Parity parity, BYTE DataBits, StopBits stopbits,FlowControl fc) { //1.新建串口 if(this->m_pPort) delete this->m_pPort; this->m_pPort = new CSerialPort(); this->m_bIsOpen = false; //2.判断收发模式 if(mode == ReceiveMode::ManualReceiveByQuery) { this->m_IsOverlapped = false; } else { this->m_IsOverlapped = true; } this->m_RecvMode = mode; //3.转换参数,打开串口 int index; index=parity-CComPort::EvenParity; CSerialPort::Parity spParity=(CSerialPort::Parity)(CSerialPort::EvenParity+index); index=stopbits-CComPort::OneStopBit; CSerialPort::StopBits spStopbits=(CSerialPort::StopBits)(CSerialPort::OneStopBit+index); index=fc-CComPort::NoFlowControl; CSerialPort::FlowControl spFC=(CSerialPort::FlowControl)(CSerialPort::NoFlowControl+index) ; try { this->m_pPort->Open(nPort,dwBaud,spParity,DataBits,spStopbits,spFC,m_IsOverlapped); } catch(CSerialException* pE) { //AfxMessageBox(pE->GetErrorMessage()); pE->Delete(); return false; } //it is important!! COMMTIMEOUTS timeouts; this->m_pPort->GetTimeouts(timeouts); timeouts.ReadIntervalTimeout=100; //timeouts.WriteTotalTimeoutConstant = 1000; this->m_pPort->SetTimeouts(timeouts); this->m_pPort->Purge(PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); this->m_pPort->Setup(4096,4096); this->m_CurPortNum = nPort; //创建关闭事件 this->m_hCloseEvent = CreateEvent(NULL,true,false,NULL); if(this->m_hCloseEvent==NULL) { return false; } //4.创建线程类 this->m_pReadThread = new CReadComThread(); this->m_pReadThread->BandSerialPort(this); this->m_pReadThread->Create(); this->m_pReadThread->Resume(); if(this->IsOverlapped()) { this->m_hWriteEvent = ::CreateEvent(NULL,true,false,NULL); if(this->m_hCloseEvent==NULL) return false; this->m_WriteOverlapped.hEvent = this->m_hWriteEvent; } this->m_bIsOpen = true; return true; } void CComPort::Close() { //1.串口 if(this->m_pPort==NULL) return; if(!this->m_pPort->IsOpen()) return; //2.事件 ::SetEvent(this->m_hCloseEvent);//通知关闭系统 Sleep(1000); //3.结束读线程 try { this->m_pReadThread->Terminate(); delete this->m_pReadThread; this->m_pReadThread = NULL; } catch(char e[150]) { ::AfxMessageBox((CString)(e)); } //4.结束关闭线程 ::CloseHandle(this->m_hCloseEvent); this->m_pPort->Close(); //5.结束写事件 if(this->m_hWriteEvent) { ::CloseHandle(this->m_hWriteEvent); this->m_hWriteEvent = NULL; } //6.释放串口对象 if(this->m_pPort) { delete this->m_pPort; this->m_pPort = NULL; } //7.重置串口状态 this->m_bIsOpen = false; } void CComPort::ReceiveData(void* pBuf,DWORD InBufferCount) { if(this->m_pfnOnReceiveData) this->m_pfnOnReceiveData(this->m_pSender,pBuf,InBufferCount); } void CComPort::SetReceiveFunc(FOnReceiveData pfnOnReceiveData,LPVOID pSender) { this->m_pfnOnReceiveData = pfnOnReceiveData; this->m_pSender = pSender; } void CComPort::ComBreak(DWORD dwMask) { if(this->m_pfnOnComBreak) { COMSTAT stat; this->m_pPort->GetStatus(stat); this->m_pfnOnComBreak(this->m_pPort,dwMask,stat); } } void CComPort::SetBreakHandleFunc(FOnComBreak pfnOnComBreak) { this->m_pfnOnComBreak = pfnOnComBreak; } CComPort::ReceiveMode CComPort::GetReceiveMode() { return this->m_RecvMode; } DWORD CComPort::GetInBufferCount() { if(this->IsOverlapped()) { ::AfxMessageBox(_T("this methord is only used for ManualQueryMode!")); return 0; } COMSTAT stat; ::ZeroMemory(&stat,sizeof(stat)); this->m_pPort->GetStatus(stat); return stat.cbInQue; } DWORD CComPort::GetInput(void* pBuf,DWORD Count,DWORD dwMilliseconds) { //不能在自动模式下getinput if(this->GetReceiveMode()==CComPort::AutoReceiveByBreak|| this->GetReceiveMode()==CComPort::AutoReceiveBySignal) { ::AfxMessageBox(_T("Can't use GetInput methord in this mode!")); return 0; } if(this->IsOverlapped()) { ASSERT(this->m_pReadThread); DWORD dwBytes = this->m_pReadThread->ReadInput(pBuf,Count,dwMilliseconds); this->m_pPort->TerminateOutstandingReads(); return dwBytes; } else return this->m_pPort->Read(pBuf,Count); } DWORD CComPort::Output(void* pBuf,DWORD Count) { DWORD dwWriteBytes=0; if(this->IsOverlapped())//异步模式 { this->m_pPort->Write(pBuf,Count,this->m_WriteOverlapped); if(WaitForSingleObject(this->m_WriteOverlapped.hEvent,INFINITE)==WAIT_OBJECT_0) { this->m_pPort->GetOverlappedResult(this->m_WriteOverlapped,dwWriteBytes,false); } } else { /*for(DWORD i=0;i<Count;i++) { dwWriteBytes+= this->m_pPort->Write(pBuf,1); } //for use in win98 */ dwWriteBytes = this->m_pPort->Write(pBuf,Count); } return dwWriteBytes; } CSerialPort* CComPort::GetSerialPort() { ASSERT(m_pPort); return m_pPort; } HANDLE CComPort::GetCloseHandle() { ASSERT(this->m_hCloseEvent); return this->m_hCloseEvent; } //CReadComThread CReadComThread::CReadComThread() { this->m_hThread = NULL; this->m_pPort = NULL; this->IsClose =false; ::ZeroMemory(&this->m_BreakOverlapped,sizeof(this->m_BreakOverlapped)); ::ZeroMemory(&this->m_ReadOverlapped,sizeof(this->m_ReadOverlapped)); memset(this->m_InputBuffer,0,2048); } CReadComThread::~CReadComThread() { this->m_hThread = NULL; } // CReadComThread 成员函数 bool CReadComThread::SetReadEvent(OVERLAPPED& overlapped) { BeginSet: memset(this->m_InputBuffer,0,2048); if(this->m_pPort->GetSerialPort()->Read(this->m_InputBuffer,2048,overlapped,&this->m_InBufferCount)) { if(!this->HandleData()) return false; ::ResetEvent(this->m_ReadOverlapped.hEvent); goto BeginSet; } DWORD error=::GetLastError(); if(error==ERROR_IO_PENDING) { return true; } else { return false; } } bool CReadComThread::HandleData() //处理读取数据 { if(this->m_InBufferCount>0) { this->m_pBuffer = new byte[this->m_InBufferCount]; for(int i=0;i<(int)this->m_InBufferCount;i++) { this->m_pBuffer[i] = this->m_InputBuffer[i]; } //this->m_pSerialPort-> this->m_pPort->ReceiveData(this->m_pBuffer,this->m_InBufferCount); delete[] this->m_pBuffer; } return true; } bool CReadComThread::HandleReadEvent(OVERLAPPED& overlapped) { if(this->m_pPort->GetSerialPort()->GetOverlappedResult(overlapped,this->m_InBufferCount,false)) { return this->HandleData(); } DWORD dwError = ::GetLastError(); if(dwError==ERROR_INVALID_HANDLE) return false; else return true; }

21,597

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧