艹艹艹!!!耍帅自己用API写串口,结果现在出糗了~~~

thundersung 2014-03-10 04:54:21
定期读写串口程序。自己为了锻炼所以用API了。
但是,现象是设备上电,然后打开程序,一切正常。设备断电再上电,读线程readfile就基本上读不到任何东西了。。。而调试设备的哥们儿说他也没收到任何我writefile的字符。。。关键还有!特么啥函数返回值还是getlasterror都特么没错误!!!

不多说了!贴代码吧。。。

这个是第一次创建COM口的处理,CommWatchProc是监听线程,CommRequestProc是定期向设备发请求并查看是否掉线的线程。
		hComArray[iLoop] = CreateFile(szComPort, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);

if (hComArray[iLoop] == INVALID_HANDLE_VALUE)
{
return;
}
SetCommMask(hComArray[iLoop], EV_RXCHAR|EV_TXEMPTY );
SetupComm(hComArray[iLoop], 10240, 10240);
PurgeComm(hComArray[iLoop], PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
COMMTIMEOUTS commTimeOuts;
commTimeOuts.ReadIntervalTimeout = MAXDWORD;
commTimeOuts.ReadTotalTimeoutConstant = 0;
commTimeOuts.ReadTotalTimeoutMultiplier = 0;
commTimeOuts.WriteTotalTimeoutConstant = 2000;
commTimeOuts.WriteTotalTimeoutMultiplier = 50;
SetCommTimeouts(hComArray[iLoop], &commTimeOuts);
DCB dcb;
dcb.BaudRate = 115200;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fBinary = TRUE;
dcb.fParity = FALSE;
SetCommState(hComArray[iLoop], &dcb);

CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CommWatchProc, (LPVOID)(&iComIndexArray[iLoop]), 0, &dwThreadID);
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CommRequestProc, (LPVOID)(&iComIndexArray[iLoop]), 0, &dwThreadID);


这个是监听。bufferGlobalArray和Backup都是全局的,为了拼接没有一次全发过来的字符串而准备的,mutexArray相应位置放的是共享信号量。ProcessRcvBuffer是具体处理字符串的函数,可以无视。
UINT CommWatchProc(LPVOID lpPara)
{
try
{
int iComIndex = *(int*)lpPara;
InitializeCriticalSection(&mutexArray[iComIndex]);
memset(bufferGlobalArray[iComIndex], 0, 10240);
memset(bufferGlobalBackupArray[iComIndex], 0, 10240);
iBufferGlobalStartIndexArray[iComIndex] = 0;
iBufferGlobalEndIndexArray[iComIndex] = -1;
HANDLE hEventWait100 = CreateEvent(NULL, TRUE, FALSE, NULL);
BYTE buffer[1024] = {0};
OVERLAPPED osReader = {0};
COMSTAT comStat = {0};
DWORD dwByteRead = 0, dwLastError = 0, dwWaitRet = 0, dwError = 0;
BOOL bThreadDone = FALSE, bRet = TRUE, bWaitingOnRead = FALSE;
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
while (!bThreadDone)
{
SetLastError(ERROR_SUCCESS);
if (!bWaitingOnRead)
{
bRet = ReadFile(hComArray[iComIndex], buffer, 1024, &dwByteRead, &osReader);
if (!bRet)
{
dwLastError = GetLastError();
if (ERROR_IO_PENDING == dwLastError)
bWaitingOnRead = TRUE;
else
{
bThreadDone = TRUE;
continue;
}
}
else
{
if (dwByteRead)
ProcessRcvBuffer(buffer, dwByteRead, iComIndex);
}
}
if (bWaitingOnRead)
{
dwWaitRet = WaitForSingleObject(osReader.hEvent, INFINITE);
switch (dwWaitRet)
{
case WAIT_OBJECT_0:
SetLastError(ERROR_SUCCESS);
bRet = GetOverlappedResult(hComArray[iComIndex], &osReader, &dwByteRead, FALSE);
if (!bRet)
{
dwLastError = GetLastError();
if (dwLastError == ERROR_OPERATION_ABORTED)
continue;
else if (dwLastError == ERROR_IO_INCOMPLETE)
{
WaitForSingleObject(hEventWait100, 100);
continue;
}
else
bThreadDone = TRUE;
}
else
{
if (dwByteRead)
ProcessRcvBuffer(buffer, dwByteRead, iComIndex);
}
bWaitingOnRead = FALSE;
break;
case WAIT_TIMEOUT:
WaitForSingleObject(hEventWait100, 100);
break;
default:
break;
}
}
memset(buffer, 0, 1024);
WaitForSingleObject(hEventWait100, 100);
}
CloseHandle(osReader.hEvent);
CloseHandle(hEventWait100);
DeleteCriticalSection(&mutexArray[iComIndex]);
}
catch (...)
{
}

return 0;
}


这个是定期询问设备的。
UINT CommRequestProc(LPVOID lpPara)
{
try
{
int iComIndex = *((int*)lpPara), iLoop = 0, iLoopAnother = 0;
CString szComPort;
szComPort.Format(TEXT("\\\\.\\COM%d"), iComIndex+1);
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//...
for (;;)
{
if (!ComIsAvailable(hComArray[iComIndex]))
{
CloseHandle(hComArray[iComIndex]);
hComArray[iComIndex] = INVALID_HANDLE_VALUE;
TerminateThread(hWatchThreadArray[iComIndex], 1);
CloseHandle(hWatchThreadArray[iComIndex]);
hWatchThreadArray[iComIndex] = INVALID_HANDLE_VALUE;
BOOL bLoop = TRUE;
while (bLoop)
{
hComArray[iComIndex] = CreateFile(szComPort, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);
if (hComArray[iComIndex] == INVALID_HANDLE_VALUE)
{
CloseHandle(hComArray[iComIndex]);
WaitForSingleObject(hEvent, 5000);
}
else
{
SetCommMask(hComArray[iComIndex], EV_RXCHAR|EV_TXEMPTY );
SetupComm(hComArray[iComIndex], 10240, 10240);
PurgeComm(hComArray[iComIndex], PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
COMMTIMEOUTS commTimeOuts;
commTimeOuts.ReadIntervalTimeout = MAXDWORD;
commTimeOuts.ReadTotalTimeoutConstant = 0;
commTimeOuts.ReadTotalTimeoutMultiplier = 0;
commTimeOuts.WriteTotalTimeoutConstant = 2000;
commTimeOuts.WriteTotalTimeoutMultiplier = 50;
SetCommTimeouts(hComArray[iComIndex], &commTimeOuts);
DCB dcb;
dcb.BaudRate = 115200;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fBinary = TRUE;
dcb.fParity = FALSE;
SetCommState(hComArray[iComIndex], &dcb);
DWORD dwThreadID = 0;
hWatchThreadArray[iComIndex] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CommWatchProc, lpPara, 0, &dwThreadID);
bLoop = FALSE;
}
}
}
//定期询问设备
}
CloseHandle(hEvent);
}
catch (...)
{
DWORD dwLastError = GetLastError();
}
return 0;
}


ComIsAvailable是用来看这个端口对应的设备是不是突然断电了的。
BOOL ComIsAvailable(HANDLE hCom)
{
BOOL bRet = TRUE;
DWORD dwLastError = 0, dwBytesWritten = 0;
BYTE byNothing[4] = {0};
DWORD dwSize = sizeof(byNothing);
OVERLAPPED overlapped = {0};
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
SetLastError(0);
if (!WriteFile(hCom, byNothing, dwSize, &dwBytesWritten, &overlapped))
{
dwLastError = GetLastError();
if (ERROR_IO_PENDING == dwLastError)
{
SetLastError(0);
while(!GetOverlappedResult(hCom, &overlapped, &dwBytesWritten, TRUE))
{
dwLastError = GetLastError();
if (dwLastError == ERROR_IO_INCOMPLETE)
continue;
else
{
bRet = FALSE;
break;
}
}
}
}
CloseHandle(overlapped.hEvent);
return bRet;
}




...全文
230 13 打赏 收藏 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
thundersung 2014-03-12
  • 打赏
  • 举报
回复
引用 12 楼 thundersung 的回复:
[quote=引用 10 楼 schlafenhamster 的回复:] 就是说 BOOL ComIsAvailable(HANDLE hCom) 没有问题, 是下位机的问题.
不过,现在有另外一个问题,有的时候,我的ProcessSndBuffer中GetOverlappedResult会卡顿一下,然后返回TRUE,而这个时候却发现我写进去的字符个数是0,也就是dwBytesWritten和m_osWrite.InternalHigh都等于0,但GetLastError却是0,我是根据m_osWrite.Internal等于258觉得这个函数超时了。我把GetOverlappedResult的最后一个等待的参数设定为FALSE,那么第一次循环时返回FALSE,LastError是Incomplete,第二次循环就返回TRUE了,但仍然写进去0个字符。[/quote] 这个问题要顶起来!
thundersung 2014-03-11
  • 打赏
  • 举报
回复
引用 8 楼 schlafenhamster 的回复:
"首先是WriteFile返回FALSE,LastError是PENDING" WriteFile返回FALSE时,能不能重新初始化comm
呵呵,原因大概不是我上位机的问题。 我在判断端口是否掉的时候,是通过WriteFile缩编写四个0然后看LastError是不是等于FileNotFound的。 好像是主板在接收到不能识别的数据时处理卡死了。俺把这四个用于探试的0换成实际的有CRC、头尾的命令就能够正常热插拔了。 结贴给分啦!
schlafenhamster 2014-03-11
  • 打赏
  • 举报
回复
"首先是WriteFile返回FALSE,LastError是PENDING" WriteFile返回FALSE时,能不能重新初始化comm
thundersung 2014-03-11
  • 打赏
  • 举报
回复
引用 6 楼 schlafenhamster 的回复:
// close Comm PurgeComm(m_idComDev,PURGE_TXABORT | PURGE_RXABORT| PURGE_TXCLEAR | PURGE_RXCLEAR); // if (ClearCommError(m_idComDev,&dwErrorFlags,&ComStat)) { //ComStat filled if (dwErrorFlags) { if (dwErrorFlags & CE_RXOVER) AfxMessageBox("Receive Queue overflow"); else if(dwErrorFlags & CE_OVERRUN) AfxMessageBox("Receive Overrun Error"); else if(dwErrorFlags & CE_RXPARITY) AfxMessageBox("Receive Parity Error"); else if(dwErrorFlags & CE_FRAME ) AfxMessageBox("Receive Framing error"); else if(dwErrorFlags & CE_BREAK) AfxMessageBox("Break Detected"); else AfxMessageBox("CE_OTHERS"); }
这些代码是放在Request线程的!ComIsAvailable判断后?我这么做了,ClearCommError返回的error是0,没有ce_break。 我昨个和设备debug发现,重新上电后我发的东西他收不到,而我的所有api返回值包括lasterror都“正确”,首先是WriteFile返回FALSE,LastError是PENDING,GetOverlappedResult返回TRUE,dwBytesWritten为具体数值,m_osWrite里Internal也是0,InternalHigh等于dwBytesWritten。一切正常。。。
thundersung 2014-03-11
  • 打赏
  • 举报
回复
引用 10 楼 schlafenhamster 的回复:
就是说 BOOL ComIsAvailable(HANDLE hCom) 没有问题, 是下位机的问题.
不过,现在有另外一个问题,有的时候,我的ProcessSndBuffer中GetOverlappedResult会卡顿一下,然后返回TRUE,而这个时候却发现我写进去的字符个数是0,也就是dwBytesWritten和m_osWrite.InternalHigh都等于0,但GetLastError却是0,我是根据m_osWrite.Internal等于258觉得这个函数超时了。我把GetOverlappedResult的最后一个等待的参数设定为FALSE,那么第一次循环时返回FALSE,LastError是Incomplete,第二次循环就返回TRUE了,但仍然写进去0个字符。
thundersung 2014-03-11
  • 打赏
  • 举报
回复
引用 10 楼 schlafenhamster 的回复:
就是说 BOOL ComIsAvailable(HANDLE hCom) 没有问题, 是下位机的问题.
感觉是的。我只是把这个函数里面写的字符串替换成有头有尾有校验的数据串了,然后就能正常收发了。
schlafenhamster 2014-03-11
  • 打赏
  • 举报
回复
就是说 BOOL ComIsAvailable(HANDLE hCom) 没有问题, 是下位机的问题.
schlafenhamster 2014-03-10
  • 打赏
  • 举报
回复
// close Comm PurgeComm(m_idComDev,PURGE_TXABORT | PURGE_RXABORT| PURGE_TXCLEAR | PURGE_RXCLEAR); // if (ClearCommError(m_idComDev,&dwErrorFlags,&ComStat)) { //ComStat filled if (dwErrorFlags) { if (dwErrorFlags & CE_RXOVER) AfxMessageBox("Receive Queue overflow"); else if(dwErrorFlags & CE_OVERRUN) AfxMessageBox("Receive Overrun Error"); else if(dwErrorFlags & CE_RXPARITY) AfxMessageBox("Receive Parity Error"); else if(dwErrorFlags & CE_FRAME ) AfxMessageBox("Receive Framing error"); else if(dwErrorFlags & CE_BREAK) AfxMessageBox("Break Detected"); else AfxMessageBox("CE_OTHERS"); }
schlafenhamster 2014-03-10
  • 打赏
  • 举报
回复
ClearCommError 或 Purge
thundersung 2014-03-10
  • 打赏
  • 举报
回复
引用 2 楼 schlafenhamster 的回复:
发生了“CE_BREAK错误” 需清除
哦!这个在哪里处理啊?是需要在ReadFile前SetCommMask然后当逻辑&CE_BREAK非0后清除吗?清除操作都包括什么呀?
thundersung 2014-03-10
  • 打赏
  • 举报
回复
另外,由于下位机没收到东西,所以把咱写的函数也贴上了。
void ProcessSndBuffer(BYTE *buffer, DWORD size, int comIndex)
{
	try
	{
		SetLastError(0);
		OVERLAPPED m_osWrite;
		COMSTAT ComStat;
		DWORD dwErrorFlags, dwBytesWritten, dwRes;
		BOOL bWriteStat;
		memset(&m_osWrite, 0, sizeof(m_osWrite));
		m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		ClearCommError(hComArray[comIndex], &dwErrorFlags, &ComStat);
		PurgeComm(hComArray[comIndex], PURGE_TXABORT | PURGE_TXCLEAR);
		bWriteStat = WriteFile(hComArray[comIndex], buffer, size, &dwBytesWritten, &m_osWrite);
		if(!bWriteStat)
		{
			DWORD dwLastError = GetLastError();
			if(GetLastError() == ERROR_IO_PENDING)
			{
				SetLastError(0);
				while(!GetOverlappedResult(hComArray[comIndex], &m_osWrite, &dwBytesWritten, TRUE))
				{
					DWORD dwError = GetLastError();
					if (dwError == ERROR_IO_INCOMPLETE)
						continue;
					else
						break;
				}
			}
		}
		dwRes = GetLastError();
		CloseHandle(m_osWrite.hEvent);
	}
	catch (...)
	{
	}
}
过程基本上都是bWriteStat等于FALSE,然后GetLastError等于PENDING,而GetOverlappedResult一次就返回TRUE了,dwBytesWritten也不等于零。m_osWrite.Internal等于零。看上去好像没什么不对的,但设备就特么没收到东西。。。重新启动软件,就能够写进去了。。。
schlafenhamster 2014-03-10
  • 打赏
  • 举报
回复
发生了“CE_BREAK错误” 需清除
thundersung 2014-03-10
  • 打赏
  • 举报
回复
这个程序,把设备断电了,再上电后,第一个readfile就只偶尔能读到两三次数据,然后就一直是返回TRUE而dwByteRead等于0。关了程序再重启(不动设备),就能一直读数据了。。。。。。
摘 要 针对高校教师教学业绩管理流程复杂、数据填报不规范、多级审核效率低、统计分析滞后等问题,本文设计并实现一套基于SpringBoot+Vue前后端分离架构的高校教师教学业绩综合管理系统。系统后端以SpringBoot处理业务逻辑与接口开发,前端用Vue构建交互界面,MySQL存储数据,MD5加密保障账号安全,具备低耦合、易扩展、易维护特性。 系统按权限划分为教师、学院管理员、学校管理员三级角色,构建闭环式业绩管理体系。教师可完成信息维护、业绩录入、成果申报、审核跟踪、档案导出、智能咨询与社区互动;学院管理员负责教师管理、业绩初审、数据汇总、通知发布与修正申请;学校管理员承担权限分配、数据维护、业绩终审、统计分析、公告发布与日志审计。 系统实现业绩填报、初审、终审、统计归档全流程线上化,支持批量导入、敏感词过滤、数据可视化、7×24小时AI咨询等功能,规范管理流程、减少统计误差、提升审核效率。测试表明,系统满足高校教学业绩精细化、规范化、信息化管理需求,为教师考核、绩效评定、教学评估提供数据支撑,提升高校教学管理智能化水平。 关键词: SpringBoot;Vue;教学业绩管理;三级权限;前后端分离
内容概要:本文围绕“基于雅可比伪逆迭代的双臂协同轨迹规划与跟踪误差收敛性研究”展开,通过Matlab代码实现双机械臂系统的协同运动控制与轨迹跟踪。研究采用雅可比伪逆法求解冗余机械臂的逆运动学问题,实现末端执行器在笛卡尔空间中的精确轨迹规划,并引入迭代优化机制提升双臂协同作业的精度与稳定性。重点分析了轨迹跟踪过程中误差的收敛特性,验证了所提控制算法在多自由度强耦合系统中的有效性和鲁棒性,适用于复杂环境下需要高精度配合的机器人协同操作任务。该研究属于科研仿真复现类工作,融合了机器人运动学理论、数值计算方法与控制算法设计,为多机械臂系统提供了可行的轨迹规划与控制策略参考。; 适合人群:具备扎实的机器人学基础、自动控制理论知识以及良好Matlab编程能力的科研人员或研究生,尤其适合从事多机械臂协同控制、运动规划、逆运动学求解及误差分析等方向的研究者。; 使用场景及目标:①用于多机械臂系统的协同轨迹规划与运动控制算法研究;②深入理解基于雅可比伪逆法的逆运动学求解原理及其在冗余机构中的应用;③分析轨迹跟踪误差的收敛行为,评估控制策略的稳定性与精度;④作为高质量论文复现资源,支撑相关课题的仿真验证、算法对比与改进创新。; 阅读建议:建议结合Matlab代码与机器人运动学经典理论同步学习,重点关注雅可比矩阵的构建、伪逆运算的实现方式、误差反馈机制的设计以及迭代过程中的数值稳定性处理,同时可进一步拓展至非线性优化、避免奇异位形及实时控制策略的改进研究。

15,465

社区成员

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

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