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

ohohd 2015-07-12 06:32:13

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

...全文
680 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
  • 打赏
  • 举报
回复
是异步读取还是同步读取?如果是异步读取会始终投递读事件,保证串口有数据时能马上读取到
内容概要:本文提出了一种基于加权稀疏矩阵恢复与加速交替方向乘子法(ADMM)的单通道盲解混响算法,并提供了完整的Matlab代码实现。该方法旨在从仅有的单路接收信号中有效分离出原始声源信号,克服传统多通道方法对硬件的依赖。核心技术结合了信号在时频域的稀疏性先验,通过构建加权机制以增强稀疏矩阵恢复的准确性,并引入加速ADMM算法来优化求解过程,显著提升了算法的收敛速度与计算效率。该算法特别适用于麦克风阵列受限或无法部署的复杂声学环境,能够有效抑制混响干扰,从而显著提升语音信号的清晰度与后续语音识别系统的性能。; 适合人群:具备扎实的数字信号处理、凸优化理论及稀疏表示基础,从事音频信号处理、语音增强、盲源分离或相关领域研究与开发工作的研究生、科研人员及工程技术人员。; 使用场景及目标:①解决单麦克风场景下的语音混响去除难题,提升语音通信质量;②应用于智能助听器、车载语音系统、远程视频会议、人机交互等存在严重混响的实际应用场景;③为盲解卷积、稀疏信号恢复等领域的研究提供一种高效的算法实现范例与优化思路。; 阅读建议:建议读者在深入理解信号稀疏性、ADMM优化框架等理论基础上,结合所提供的Matlab代码进行实践,重点分析加权策略的设计原理及其对恢复性能的影响,并通过调整正则化参数、权重因子等关键变量,探究其在不同混响强度和噪声条件下的鲁棒性与泛化能力。
内容概要:本文介绍了一个基于Simulink的永磁同步电机(PMSM)电流环控制策略仿真模型,重点实现了二阶滑模控制(STSMC)、有限集模型预测控制(FCS-MPC)和PI控制三种先进控制算法。该模型通过构建完整的电机驱动系统仿真环境,对比分析了不同控制方法在动态响应速度、抗干扰能力、稳态精度以及鲁棒性等方面的性能表现,验证了各算法在高性能电机驱动应用中的可行性与优势。文档内容涵盖控制器设计、参数整定、仿真结果分析及系统稳定性评估,具有较强的可复现性和拓展性,适用于先进控制算法的教学演示、科研验证与工程原型开发。; 适合人群:具备一定电机控制理论基础和Simulink仿真经验的电气工程、自动化、控制科学与工程等相关专业的研究生、科研人员以及从事电机驱动系统研发的工程师。; 使用场景及目标:①开展永磁同步电机先进电流控制策略的仿真研究与性能对比;②深入理解滑模控制、模型预测控制与传统PI控制的原理与实现差异;③支撑毕业设计、科研课题或工业项目中控制算法的选型、验证与优化工作。; 阅读建议:此资源以Simulink仿真实现为核心,建议读者结合现代控制理论教材与仿真模型同步操作,重点关注各控制器的结构设计、参数调节过程及仿真响应曲线,通过对比分析深入掌握不同控制策略的作用机制与适用条件,并可在此基础上进行算法改进与功能扩展。

15,466

社区成员

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

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