社区
驱动开发/核心开发
帖子详情
C++程序,打开串口时GetLastError返回错误值87
ylongwu
2012-12-29 04:50:06
问题是这样的,如果单独运行我的程序,则能正确打开串口并写入数据。但是如果先通过“串口专家”这个软件打开串口,再关闭串口,接着再用我的程序来打开串口,则GetlastError返回87。 请问这是怎么回事呢?
另外还有一个现象,有时先通过“串口专家”这个软件打开串口,再关闭串口,接着再用我的程序来打开串口,也能正确打开,但是接收到的数据或出现分段的现象,也就是不能一次完整接收
...全文
967
4
打赏
收藏
C++程序,打开串口时GetLastError返回错误值87
问题是这样的,如果单独运行我的程序,则能正确打开串口并写入数据。但是如果先通过“串口专家”这个软件打开串口,再关闭串口,接着再用我的程序来打开串口,则GetlastError返回87。 请问这是怎么回事呢? 另外还有一个现象,有时先通过“串口专家”这个软件打开串口,再关闭串口,接着再用我的程序来打开串口,也能正确打开,但是接收到的数据或出现分段的现象,也就是不能一次完整接收
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用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; }
串口
类CSerial
CSerial::EPort CSerial::CheckPort (LPCTSTR lpszDevice) { // Try to open the device HANDLE hFile = ::CreateFile(lpszDevice, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); // Check if we could open the device if (hFile == INVALID_HANDLE_VALUE) { // Display
error
switch (::GetLast
Error
()) { case
ERROR
_FILE_NOT_FOUND: // The specified COM-port does not exist return EPortNotAvailable; case
ERROR
_ACCESS_DENIED: // The specified COM-port is in use return EPortInUse; default: // Something else is wrong return EPortUnknown
Error
; } } // Close handle ::CloseHandle(hFile); // Port is available return EPortAvailable; }
C++
所有GetLast
Error
返回
错误
码代表的意思
在VC中编写应用
程序
时
,经常需要涉及到
错误
处理问题。许多函数调用只用TRUE和FALSE来表明函数的运行结果。一旦出现
错误
,MSDN中往往会指出请用GetLast
Error
()函数来获得
错误
原因。 可问题是,GetLast
Error
()
返回
的只是一个双字节数
值
(DWORD)。OH,MY GOD!目前Win32的出错编号已经从0排到11031,而这还不是
错误
编码的全部。因为
错误
代码还在不
C++
-win32-GetLast
Error
的
返回
值
的含义
GetLast
Error
返回
的
值
通过在api函数中调用SetLast
Error
或SetLast
Error
Ex设置。函数并无必要设置上一次
错误
信息,所以即使一次GetLast
Error
调用
返回
的是零
值
,也不能担保函数已成功执行。只有在函数调用
返回
一个
错误
结果
时
,这个函数指出的
错误
结果才是有效的。通常,只有在函数
返回
一个
错误
结果,而且已知函数会设置GetLast
Error
变量的前提下,才应访问GetLast
Error
;这
时
能保证获得有效的结果。SetLast
Error
函数主要在对api函数进行模拟的dll函数中
C++
:用GetLast
Error
()查找
错误
原因;
DWORD
error
= GetLast
Error
();
错误
对照码功能:查询LoadIcon()函数
返回
的
错误
值
〖0〗-操作成功完成。 〖1〗-功能
错误
。 〖2〗-系统找不到指定的文件。 〖3〗-系统找不到指定的路径。 〖4〗-系统无法
打开
文件。 〖5〗-拒绝访问。 〖6〗-句柄无效。 〖7〗-存储控制块被损坏。 〖8〗-存储空间不足,无法处理此命令。 〖9〗-存储控制块...
GetLast
Error
函数使用及
返回
代码对照
DWORD i = ::GetLast
Error
(); 功能:查询LoadIcon()函数
返回
的
错误
值
〖0〗-操作成功完成。 〖1〗-功能
错误
。 〖2〗-系统找不到指定的文件。 〖3〗-系统找不到指定的路径。 〖4〗-系统无法
打开
文件。 〖5〗-拒绝访问。 〖6〗-句柄无效。 〖7〗-存储控制块被损坏。 〖8〗-存储空间不足
驱动开发/核心开发
21,597
社区成员
21,709
社区内容
发帖
与我相关
我的任务
驱动开发/核心开发
硬件/嵌入开发 驱动开发/核心开发
复制链接
扫一扫
分享
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章