艹艹艹!!!耍帅自己用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;
}




...全文
223 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。关了程序再重启(不动设备),就能一直读数据了。。。。。。
内容概要:LTK8319是一款单通道H桥有刷直流电机驱动器,工作电压范围为2.5V至12V,支持最高3.9A的峰值电流和2.5A的平均电流驱动能力,适用于小家电、玩具、电子锁、机器人等小型电动设备。该芯片通过两个逻辑输入(INA和INB)控制电机的正转、反转、停止与刹车,并支持PWM调速控制。集成欠压锁定(UVLO)、过温保护(TSD)及自动故障恢复功能,确保系统安全可靠运行。当INA和INB持续为低电平时,芯片进入低功耗休眠模式,显著降低静态功耗。采用ESOP-8封装,符合环保无铅标准。; 适合人群:电子工程师、嵌入式系统开发者、电机控制技术人员,以及从事小型机电产品研发的设计人员;具备基本电路知识和电机控制经验者更佳。; 使用场景及目标:①用于驱动小型有刷直流电机或步进电机的一个绕组,实现精确的方向与速度控制;②适用于电池供电设备中对功耗敏感的应用,利用休眠模式延长续航时间;③在电机启停频繁、负载波动大的场合,发挥其电流控制与保护机制优势,提升系统稳定性。; 阅读建议:此文档提供了详细的电气特性、功能逻辑表、保护机制与时序参数,建议结合典型应用电路进行硬件设计,并重点关注电源去耦电容选型、散热布局及PWM频率设置(不超过100kHz),以确保系统可靠运行。
内容概要:本文研究了一种基于遗传算法(GA)与粒子群优化算法(PSO)融合的无人机三维路径规划方法,旨在解决复杂环境中无人机避障与路径优化的问题。通过构建三维空间环境模型,提一种结合GA全局搜索能力强与PSO收敛速度快优势的混合优化策略,并利用Matlab平台完成算法仿真与路径可视化。研究不仅实现了无人机在存在多个障碍物场景下的安全、高效飞行路径规划,还对GA与PSO两种算法在路径长度、计算耗时、收敛稳定性等方面进行了对比分析,评估其性能差异,为实际应用中算法选型提供依据。; 适合人群:具备一定算法设计基础和Matlab编程能力的科研人员、自动化与人工智能方向的研究生,以及从事无人机导航、智能控制等相关领域的工程技术人员。; 使用场景及目标:①应用于城市密集建筑区、山地森林等复杂地形中的无人机自主巡检与应急救援任务;②为智能交通、地理测绘、灾害监测等需要自主路径决策的无人系统提供算法支持与仿真验证;③通过对比不同智能优化算法的表现,辅助研究人员在特定应用场景下选择最优路径规划方案。; 阅读建议:建议读者结合提供的Matlab代码进行仿真实验,调整种群规模、迭代次数、障碍物分布等参数,深入理解算法运行机制与性能表现,并可进一步拓展至动态环境更新、多无人机协同避障等更复杂的研究方向。

15,465

社区成员

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

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