API串口编程CSerialPort类为什么发送一个后就锁死在读的事件上了?

ohohd 2015-07-12 06:32:13

这个函数在等三个事件:关线程,IO口状态(读事件 EX_CHAR),发送事件(排名分优先级)
点发送按键就会激活发送事件(Event=2)然后进入到相应的case进行发送,但是发送完成后再次到这个等待函数的时候莫名其妙直接通过并让Event=1(读),但是我外界没有向串口发东西,读缓冲区也是空的,然后就一直这样读空缓存区并封锁了发送事件,想再次向外界发东西就只能先关串口再开才行。
还有,我向电脑本身空的COM1口发送没这个问题,可连续发送。是不是我用的是usb转串口的原因啊(电脑和FPGA通信)

...全文
523 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
这菜真辣 2015-12-22
  • 打赏
  • 举报
回复
楼主你好,我也遇到了跟你一样的问题,把读写的优先级颠倒后还是写事件不会被奇怪的read事件锁死,但是这样做我的一个程序真正接收的时候还是会出现问题,经常出现接收的一帧数据(12个字节)全部为零的情况。能不能一起交流一下啊 ,这个问题搞得我好郁闷啊
ohohd 2015-07-14
  • 打赏
  • 举报
回复
引用 11 楼 jiqiang01234 的回复:
用串口工具,看看是不是能收到干扰数据。既然响应的是EV_RXCHAR,那就是串口收到了数据。你提到了用的是usb转串口,可以换一条线试试。
串口没收到数据: 跳过wait函数后检查 Inque(读缓冲区的字节数)==0 。 算了就让他不停的读空的吧 我已经把写事件优先级设的比读优先级高了 对写没影响了 不过还是谢谢你
jiqiang01234 2015-07-13
  • 打赏
  • 举报
回复
用串口工具,看看是不是能收到干扰数据。既然响应的是EV_RXCHAR,那就是串口收到了数据。你提到了用的是usb转串口,可以换一条线试试。
jiqiang01234 2015-07-13
  • 打赏
  • 举报
回复
如果投递读取事件后, 即使没有收到数据,wait函数也不停留,那就看一下返回值,到底是wait响应了什么事件。可以能是readfile的参数没有设置正确,也有可能是串口有干扰数据发送(这个可以通过串口调试工具来排除)。
ohohd 2015-07-13
  • 打赏
  • 举报
回复
引用 7 楼 jiqiang01234 的回复:
如果是异步读写串口,根本不需要单独的线程。所谓“异步读取”的条件是,先投递异步读的事件,也就是先调用ReadFile(...)(需设置overlaped参数),然后再等待事件(各种wait函数)。直到wait函数确实收到数据后,读取到数据后,再投递读取事件,如此往复。总之,异步模式下,程序大部分时间在wait函数停留,只有有事件触发时才会处理。
引用 7 楼 jiqiang01234 的回复:
如果是异步读写串口,根本不需要单独的线程。所谓“异步读取”的条件是,先投递异步读的事件,也就是先调用ReadFile(...)(需设置overlaped参数),然后再等待事件(各种wait函数)。直到wait函数确实收到数据后,读取到数据后,再投递读取事件,如此往复。总之,异步模式下,程序大部分时间在wait函数停留,只有有事件触发时才会处理。
我这个调用一次ReadFile()后就不停在wait函数了不管读没读到数据。但是我对空串口COM1操作时读一次确实也能停下来等。难道是硬件的问题?
ohohd 2015-07-13
  • 打赏
  • 举报
回复
引用 9 楼 jiqiang01234 的回复:
如果投递读取事件后, 即使没有收到数据,wait函数也不停留,那就看一下返回值,到底是wait响应了什么事件。可以能是readfile的参数没有设置正确,也有可能是串口有干扰数据发送(这个可以通过串口调试工具来排除)。
原来不会停留啊 那我对空串口(没接东西的COM1)操作为啥每次都会停留呢? 响应的是RX_CHAR 还有我在读的地方设断点 第二次点发送不会停在这个地方
jiqiang01234 2015-07-12
  • 打赏
  • 举报
回复
如果是异步读写串口,根本不需要单独的线程。所谓“异步读取”的条件是,先投递异步读的事件,也就是先调用ReadFile(...)(需设置overlaped参数),然后再等待事件(各种wait函数)。直到wait函数确实收到数据后,读取到数据后,再投递读取事件,如此往复。总之,异步模式下,程序大部分时间在wait函数停留,只有有事件触发时才会处理。
ohohd 2015-07-12
  • 打赏
  • 举报
回复

基本解决了 我把读,写事件的优先级对换掉就好了 这样就算不停投递读事件我也照样可以写了 也能正常读 只是不知道之后会不会有bug。。。 还有一个问题想请教,投递读事件的条件到底是什么? 我一直觉得是读缓冲区有数据才会投
ohohd 2015-07-12
  • 打赏
  • 举报
回复
引用 4 楼 wxhxj0268 的回复:
看你的程序就有问题,请将事件放到到另一个线程中。例

//***************************************************************
//				全局变量
//***************************************************************
DWORD		ThreadProcEvent(LPVOID pParam);		// 事件响应函数(线程)

HANDLE		hCom;								// 串口的句柄
HANDLE		hThreadEvent;						// 事件线程句柄
bool		fEventRun;							// 事件函数执行标志
DWORD		dwWinThreadID;						// 窗口线程ID
DWORD		dwThreadID;							// 事件线程ID
OVERLAPPED	Eol={0};							// 事件线程使用的结构
OVERLAPPED	Wol={0};							// 写操作使用的结构
OVERLAPPED	Rol={0};							// 读操作使用的结构
bool		fStopMsg;							// 停止事件线程向主线程发送消息标志
// ************		串口事件响应程序	**************
DWORD ThreadProcEvent(LPVOID pParam)
{
	DWORD dwEvtMask,dwRes;
	Eol.hEvent=CreateEvent(NULL,							// 设置为无信号状态
				FALSE,										// 自动复原
				FALSE,
				NULL);
	while(fEventRun)
	{
		WaitCommEvent(hCom,
			&dwEvtMask,
			&Eol);
		dwRes=WaitForSingleObject(Eol.hEvent,
					TO_EVENT_TIMEOUT);
		switch(dwRes)
		{
		case WAIT_OBJECT_0:										// 得到监视结果
			switch(dwEvtMask)
			{
			case EV_RXCHAR:										// 接收到数据
				if(!fStopMsg)
				{
					fStopMsg=true;
					::PostThreadMessage(dwWinThreadID,			// 向窗口线程发收到数据的消息
							WM_COMMDATA_MESSAGE,
							(WPARAM)EV_RXCHAR,1);				// 发送接收缓冲区有数据事件消息
				}
				break;
			case EV_TXEMPTY:									// 发送缓冲区已空
				// 发送缓冲区空
				::PostThreadMessage(dwWinThreadID,			// 向窗口线程发收到数据的消息
						WM_COMMDATA_MESSAGE,
						(WPARAM)EV_TXEMPTY,1);				// 发送缓冲区已空事件消息
				break;
			}
			break;
		}
	}
	return true;
}
//////////////////////////////////////		全局END		/////////////////////////////////////////
引用 4 楼 wxhxj0268 的回复:
看你的程序就有问题,请将事件放到到另一个线程中。例

//***************************************************************
//				全局变量
//***************************************************************
DWORD		ThreadProcEvent(LPVOID pParam);		// 事件响应函数(线程)

HANDLE		hCom;								// 串口的句柄
HANDLE		hThreadEvent;						// 事件线程句柄
bool		fEventRun;							// 事件函数执行标志
DWORD		dwWinThreadID;						// 窗口线程ID
DWORD		dwThreadID;							// 事件线程ID
OVERLAPPED	Eol={0};							// 事件线程使用的结构
OVERLAPPED	Wol={0};							// 写操作使用的结构
OVERLAPPED	Rol={0};							// 读操作使用的结构
bool		fStopMsg;							// 停止事件线程向主线程发送消息标志
// ************		串口事件响应程序	**************
DWORD ThreadProcEvent(LPVOID pParam)
{
	DWORD dwEvtMask,dwRes;
	Eol.hEvent=CreateEvent(NULL,							// 设置为无信号状态
				FALSE,										// 自动复原
				FALSE,
				NULL);
	while(fEventRun)
	{
		WaitCommEvent(hCom,
			&dwEvtMask,
			&Eol);
		dwRes=WaitForSingleObject(Eol.hEvent,
					TO_EVENT_TIMEOUT);
		switch(dwRes)
		{
		case WAIT_OBJECT_0:										// 得到监视结果
			switch(dwEvtMask)
			{
			case EV_RXCHAR:										// 接收到数据
				if(!fStopMsg)
				{
					fStopMsg=true;
					::PostThreadMessage(dwWinThreadID,			// 向窗口线程发收到数据的消息
							WM_COMMDATA_MESSAGE,
							(WPARAM)EV_RXCHAR,1);				// 发送接收缓冲区有数据事件消息
				}
				break;
			case EV_TXEMPTY:									// 发送缓冲区已空
				// 发送缓冲区空
				::PostThreadMessage(dwWinThreadID,			// 向窗口线程发收到数据的消息
						WM_COMMDATA_MESSAGE,
						(WPARAM)EV_TXEMPTY,1);				// 发送缓冲区已空事件消息
				break;
			}
			break;
		}
	}
	return true;
}
//////////////////////////////////////		全局END		/////////////////////////////////////////
这个就是在另一个进程里的 用的是别人写的一个串口类 里面读写都用的同一个overlapped。。。
笨笨仔 2015-07-12
  • 打赏
  • 举报
回复
看你的程序就有问题,请将事件放到到另一个线程中。例

//***************************************************************
//				全局变量
//***************************************************************
DWORD		ThreadProcEvent(LPVOID pParam);		// 事件响应函数(线程)

HANDLE		hCom;								// 串口的句柄
HANDLE		hThreadEvent;						// 事件线程句柄
bool		fEventRun;							// 事件函数执行标志
DWORD		dwWinThreadID;						// 窗口线程ID
DWORD		dwThreadID;							// 事件线程ID
OVERLAPPED	Eol={0};							// 事件线程使用的结构
OVERLAPPED	Wol={0};							// 写操作使用的结构
OVERLAPPED	Rol={0};							// 读操作使用的结构
bool		fStopMsg;							// 停止事件线程向主线程发送消息标志
// ************		串口事件响应程序	**************
DWORD ThreadProcEvent(LPVOID pParam)
{
	DWORD dwEvtMask,dwRes;
	Eol.hEvent=CreateEvent(NULL,							// 设置为无信号状态
				FALSE,										// 自动复原
				FALSE,
				NULL);
	while(fEventRun)
	{
		WaitCommEvent(hCom,
			&dwEvtMask,
			&Eol);
		dwRes=WaitForSingleObject(Eol.hEvent,
					TO_EVENT_TIMEOUT);
		switch(dwRes)
		{
		case WAIT_OBJECT_0:										// 得到监视结果
			switch(dwEvtMask)
			{
			case EV_RXCHAR:										// 接收到数据
				if(!fStopMsg)
				{
					fStopMsg=true;
					::PostThreadMessage(dwWinThreadID,			// 向窗口线程发收到数据的消息
							WM_COMMDATA_MESSAGE,
							(WPARAM)EV_RXCHAR,1);				// 发送接收缓冲区有数据事件消息
				}
				break;
			case EV_TXEMPTY:									// 发送缓冲区已空
				// 发送缓冲区空
				::PostThreadMessage(dwWinThreadID,			// 向窗口线程发收到数据的消息
						WM_COMMDATA_MESSAGE,
						(WPARAM)EV_TXEMPTY,1);				// 发送缓冲区已空事件消息
				break;
			}
			break;
		}
	}
	return true;
}
//////////////////////////////////////		全局END		/////////////////////////////////////////
ohohd 2015-07-12
  • 打赏
  • 举报
回复
引用 1 楼 jiqiang01234 的回复:
是异步读取还是同步读取?如果是异步读取会始终投递读事件,保证串口有数据时能马上读取到
异步的 我点打开串口的时候线程停在这个函数等待事件(说明这时也没有投递读事件啊) 然后我按下发送投递写事件 完成写操作后回到这里就不等待了直接跳到读的处理函数,读函数发现缓存里没东西继续回到这个等待函数然后又停不下来又是读事件。。。更本不让写事件投进来 这个读事件是读缓冲区里有东西才会投吧? 我压根就没向读缓冲区里写东西
ohohd 2015-07-12
  • 打赏
  • 举报
回复
异步的 我点打开串口的时候线程停在这个函数等待事件(说明这时也没有投递读事件啊) 然后我按下发送投递写事件 完成写操作后回到这里就不等待了直接跳到读的处理函数,读函数发现缓存里没东西继续回到这个等待函数然后又停不下来又是读事件。。。更本不让写事件投进来 这个读事件是读缓冲区里有东西才会投吧? 我压根就没向读缓冲区里写东西
jiqiang01234 2015-07-12
  • 打赏
  • 举报
回复
是异步读取还是同步读取?如果是异步读取会始终投递读事件,保证串口有数据时能马上读取到

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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