串口有时打开错误,GetLastError为2

FlyToTMoon 2012-01-16 02:38:26
最近一个程序需要用到串口操作,使用的是网上DOWN的CSerial类(以前人写的程序,最近需要修改)
但是使用中会有时出现串口打开失败GetLastError返回值是2,几率小于1%,大多数都是正常的程序跑完。。。有没人知道为什么啊。。。求助。。。已经让测试的看下是否被其他程序占用了,还是OPEN的参数设置有问题吗?求哪位大神帮忙看下。。。
下面是open的代码

LONG CSerial::Open (LPCTSTR lpszDevice, DWORD dwInQueue, DWORD dwOutQueue, bool fOverlapped)
{
// Reset error state
m_lLastError = ERROR_SUCCESS;

// Check if the port isn't already opened
if (m_hFile)
{
m_lLastError = ERROR_ALREADY_INITIALIZED;
_RPTF0(_CRT_WARN,"CSerial::Open - Port already opened\n");
return m_lLastError;
}

// Open the device

CString csPortName;
csPortName = CString("\\\\.\\") + CString(lpszDevice) ;
LPCTSTR cDeviceName = csPortName;

m_hFile = ::CreateFile(cDeviceName,
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
fOverlapped?FILE_FLAG_OVERLAPPED:0,
0);
if (m_hFile == INVALID_HANDLE_VALUE)
{
// Reset file handle
m_hFile = 0;

// Display error
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN, "CSerial::Open - Unable to open port\n");
return m_lLastError;
}

#ifndef SERIAL_NO_OVERLAPPED
// We cannot have an event handle yet
_ASSERTE(m_hevtOverlapped == 0);

// Create the event handle for internal overlapped operations (manual reset)
if (fOverlapped)
{
m_hevtOverlapped = ::CreateEvent(0,true,false,0);
if (m_hevtOverlapped == 0)
{
// Obtain the error information
m_lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to create event\n");

// Close the port
::CloseHandle(m_hFile);
m_hFile = 0;

// Return the error
return m_lLastError;
}
}
#else

// Overlapped flag shouldn't be specified
_ASSERTE(!fOverlapped);

#endif

// Setup the COM-port
if (dwInQueue || dwOutQueue)
{
// Make sure the queue-sizes are reasonable sized. Win9X systems crash
// if the input queue-size is zero. Both queues need to be at least
// 16 bytes large.
_ASSERTE(dwInQueue >= 16);
_ASSERTE(dwOutQueue >= 16);

if (!::SetupComm(m_hFile,dwInQueue,dwOutQueue))
{
// Display a warning
long lLastError = ::GetLastError();
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to setup the COM-port\n");

// Close the port
Close();

// Save last error from SetupComm
m_lLastError = lLastError;
return m_lLastError;
}
}

// Setup the default communication mask
SetMask();

// Non-blocking reads is default
SetupReadTimeouts(EReadTimeoutNonblocking);

// Setup the device for default settings
COMMCONFIG commConfig = {0};
DWORD dwSize = sizeof(commConfig);
commConfig.dwSize = dwSize;
if (::GetDefaultCommConfig(lpszDevice,&commConfig,&dwSize))
{
// Set the default communication configuration
if (!::SetCommConfig(m_hFile,&commConfig,dwSize))
{
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to set default communication configuration.\n");
}
}
else
{
// Display a warning
_RPTF0(_CRT_WARN,"CSerial::Open - Unable to obtain default communication configuration.\n");
}

// Return successful
return m_lLastError;
}

...全文
937 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
shangwu_35 2012-01-19
  • 打赏
  • 举报
回复
2说明端口之前木有释放完成或被占用。
FlyToTMoon 2012-01-17
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 saleayas 的回复:]
可以肯定的告诉你,PostMessage就是没有同步的。
至于是否是因为这个问题,不知道。
但这个肯定是BUG。
[/Quote]
嗯,我看了下,的确有问题。。程序别人写的,我加了些功能看到这边也没细想,就觉得程序用了2、3年了不会有问题吧。。。唉,还是要脚踏实地,学习了
Saleayas 2012-01-17
  • 打赏
  • 举报
回复
好幸福哦!
这种 BUG 的调试,还有人帮你测试。
我们都是自己调试的。
测试的都是走测试流程的。
Saleayas 2012-01-17
  • 打赏
  • 举报
回复
可以肯定的告诉你,PostMessage就是没有同步的。
至于是否是因为这个问题,不知道。
但这个肯定是BUG。
FlyToTMoon 2012-01-17
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 saleayas 的回复:]
::PostMessage(ms_hwndView,WM_USER_CLOSE_RS232_SCAN,0,0); //关闭

只是把消息发送给了窗口,
消息队列需要处理这个消息。
在窗口函数中关闭。
这个需要等待的。

尝试 SendMessage。
[/Quote]
谢谢了,我先改一版让他们测试下
Saleayas 2012-01-17
  • 打赏
  • 举报
回复
::PostMessage(ms_hwndView,WM_USER_CLOSE_RS232_SCAN,0,0); //关闭

只是把消息发送给了窗口,
消息队列需要处理这个消息。
在窗口函数中关闭。
这个需要等待的。

尝试 SendMessage。
FlyToTMoon 2012-01-17
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 saleayas 的回复:]
比如说线程同步?
[/Quote]
基本上每次对COM操作都是做到使用后关闭。。。等待释放完成应该是不用的吧

//COM的使用
::PostMessage(hView, WM_USER_OPEN_COM_SCAN, NULL, 0); //打开COM
ms_bStart=FALSE;
BOOL blWaitMessage = FALSE;
blWaitMessage = WaitForRS232Message(pAsusDoc); //等待COM接受消息
if (blWaitMessage == TRUE)
{
::PostMessage(ms_hwndView,WM_USER_CLEARUI,NULL,NULL);
}
else
{
}
::PostMessage(ms_hwndView,WM_USER_CLOSE_RS232_SCAN,0,0); //关闭
Saleayas 2012-01-17
  • 打赏
  • 举报
回复
比如说线程同步?
Saleayas 2012-01-17
  • 打赏
  • 举报
回复
看看你上次释放的时候,有没有等待释放完成。
FlyToTMoon 2012-01-17
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 saleayas 的回复:]
那应该是串口被占用了。
上一次没有释放完成。
[/Quote]
可是出现的几率很低。。<1%,如果是程序哪边忘记释放com口,应该是每次都会有错误吧
Saleayas 2012-01-17
  • 打赏
  • 举报
回复
那应该是串口被占用了。
上一次没有释放完成。
FlyToTMoon 2012-01-17
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 saleayas 的回复:]
我还以为是 CreateFile 函数抛出的 LastError 呢?
如果是这样,我觉得你应该具体看看是哪个函数抛出这个 LastError。
[/Quote]
是CreateFile 时候抛出的,LastError == 5(拒绝访问)
Saleayas 2012-01-16
  • 打赏
  • 举报
回复
我还以为是 CreateFile 函数抛出的 LastError 呢?
如果是这样,我觉得你应该具体看看是哪个函数抛出这个 LastError。
FlyToTMoon 2012-01-16
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 saleayas 的回复:]
你的串口是机器上固化的硬件串口吗?
如果是驱动虚拟的,可能是那个串口丢了。
[/Quote]
是机器上的硬件,明天来看。。现在看来一头雾水。。。
1466 [00000000] IRP_MJ_CREATE Port Opened - TA1.exe
1467 [00000000] IOCTL_SERIAL_SET_BAUD_RATE Baud Rate: 9600
1468 [00000001] IOCTL_SERIAL_SET_LINE_CONTROL StopBits: 1, Parity: No, DataBits: 8
1469 [00000002] IOCTL_SERIAL_SET_BAUD_RATE Baud Rate: 9600
1470 [00000003] IOCTL_SERIAL_SET_LINE_CONTROL StopBits: 1, Parity: No, DataBits: 8
1471 [00001326] IRP_MJ_CLOSE Port Closed
上面是监测的数据,没看到哪边问题。。
ken_scott 2012-01-16
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 caojian005 的回复:]
嗯,不是我这边使用的。。用了点方法获得了出错后的返回值,知道是2,只知道是在调用这个OPEN的返回值
[/Quote]
加下日志或断言吧 看看具体在哪里
Saleayas 2012-01-16
  • 打赏
  • 举报
回复
你的串口是机器上固化的硬件串口吗?
如果是驱动虚拟的,可能是那个串口丢了。
FlyToTMoon 2012-01-16
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ken_scott 的回复:]
如果是内部测试的话,在每一处有可能的出错的地方(比如打开文件之类)加个断言,程序挂了的时候就知道在哪里挂的了,如果是客户那边测,可能就不好这么搞了
[/Quote]
嗯,不是我这边使用的。。用了点方法获得了出错后的返回值,知道是2,只知道是在调用这个OPEN的返回值
ken_scott 2012-01-16
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ken_scott 的回复:]
如果是内部测试的话,在每一处有可能的出错的地方(比如打开文件之类)加个断言,程序挂了的时候就知道在哪里挂的了,如果是客户那边测,可能就不好这么搞了
[/Quote]
如果是客户那边测,就在函数里面加些写日志文件的操作(就是上面说的加断言的地方),客户出了问题时就讨要一下这个日志,应该就知道了

一般应该是文件被占用了
ken_scott 2012-01-16
  • 打赏
  • 举报
回复
如果是内部测试的话,在每一处有可能的出错的地方(比如打开文件之类)加个断言,程序挂了的时候就知道在哪里挂的了,如果是客户那边测,可能就不好这么搞了
FlyToTMoon 2012-01-16
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 vector_fz 的回复:]
检查一下csPortName是否为:\\.\com 这种。
[/Quote]
这个没有问题,错误出现的几率还是比较小的。。
加载更多回复(3)

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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