⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adthread.cpp

📁 AD 数据采集卡基本的采集界面
💻 CPP
字号:
#include "stdAfx.h"
#include "Sys.h"
#include "ADThread.h"

#define FIFO_HALF_LENGTH 4096  // FIFO半满长度  中断使用
#define FIFO_FULL_LENGTH FIFO_HALF_LENGTH*2  // FIFO全满长度

extern SHORT ADBuffer[MAX_SEGMENT][16384]; // 缓冲队列
extern int ReadIndex;    // AD数据采集线程当前缓冲区索引号
extern HANDLE hFileObject;
extern BOOL bNewSegmentData[MAX_SEGMENT]; // 用于确定当前段数据是否为最新数据
extern HANDLE hEvent;  // 采集线程与绘制线程的同步信号
extern HANDLE hExitEvent;
extern PCI2006_PARA_AD ADPara;
extern BOOL bDeviceADRun;
extern BOOL bCheckOverflow;
extern BOOL bCreateDevice;
extern int nProcessMode;
extern ULONGLONG FileLenghtWords;
CWinThread* m_ReadThread;
//-------------------------------------------------------------------------------------------------------------------------------------
UINT ReadDataThread_NotEmpty(PVOID hWnd);//非空方式读取数据线程
BOOL StartDeviceAD_NotEmpty(HANDLE hDevice, PCI2006_PARA_AD ADPara)
{
	m_ReadThread=AfxBeginThread(ReadDataThread_NotEmpty,NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
	m_ReadThread->m_bAutoDelete=false;

	if(!PCI2006_InitDeviceProAD(hDevice, &ADPara))
	{
		AfxMessageBox("不明的初始化错误.....", MB_ICONERROR);
		return FALSE;
	}
	bDeviceADRun=TRUE;  // 告之采集线程可以工作了
	m_ReadThread->ResumeThread();  // 启动采集线程ReadDataThread_NotEmpty
	return TRUE;
}
UINT ReadDataThread_NotEmpty(PVOID hWnd)  // 读数据线程
{
	CSysApp *pApp=(CSysApp *)AfxGetApp();
	CADDoc* pDoc=pApp->m_pADDoc; 
	// 在线程中取得视图指针
	ULONG Wrote8KWCounter=0;
	ULONG WroteMB=0; 
	
	BOOL bFirst=TRUE;
	pDoc->m_Wrote8KWCounter=0;
	pDoc->m_WroteMB=0;
	// 复位段索引号
	ReadIndex = 0;
	int nChannelCount,nRemainder;
	nChannelCount = ADPara.ChannelCount ;
	nRemainder = 8192 % nChannelCount;
	ReadSizeWords = 8192 - nRemainder;

	for(int i=0; i<MAX_SEGMENT; i++) // 将缓冲队列标志复位
	{
		bNewSegmentData[i] = FALSE; // 置成FALSE,表示该缓冲单元为无效数据
	}

	CString str1;
	ULONG ReadCount, dwErrorCode;
	PCI2006_StartDeviceProAD(pApp->m_hDevice);  // 初始化后,启动设备
	while(bDeviceADRun)  // 循环采集AD数据
	{
		ReadCount=PCI2006_ReadDeviceProAD_NotEmpty(pApp->m_hDevice, ADBuffer[ReadIndex], ReadSizeWords, bCheckOverflow);
		if(ReadCount==ReadSizeWords) // 如果返回数据量等于请求量,则处理数据
		{
			/*
			if(nProcessMode==3)  // 数据存盘
			{				
				if(WroteMB>=(pDoc->m_RemainMB-2))
				{
					AfxMessageBox("对不起,当前磁盘已满,不能再存盘",MB_ICONSTOP,0);
					return FALSE;
				}
				PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadSizeWords*2); // 将8192*2个字的数据存放在硬盘上
				FileLenghtWords+=ReadSizeWords;// 递加写入8K数据的计数器,以便存盘视图推进存盘进度条				
			}*/
		}
		else // 如果返回数据量不等于请求量,则分析原因,再处理数据
		{
			dwErrorCode = GetLastError();
			switch(dwErrorCode)
			{
			case 0xE1000000:
				AfxMessageBox("FIFO溢出, 数据丢失,请注意溢出前返回的数据量...",MB_ICONERROR);
				str1.Format("溢出前所返回的数据长度为 %d", ReadCount);
				AfxMessageBox(str1,MB_ICONSTOP);
				if(nProcessMode==3)  // 数据存盘
				{
					PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadCount*2); // 将最后一次数据写入磁盘文件
				}
				goto ExitReadThread;
			case 0xE2000000:
				//AfxMessageBox("用户故意停止,请注意最一次读操作返回的数据点数...",MB_ICONSTOP);
				//str1.Format("中断前所返回的数据长度为 %d", ReadCount);
				//AfxMessageBox(str1,MB_ICONSTOP);
				if(nProcessMode==3)  // 数据存盘
				{
					PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadCount*2); // 将最后一次数据写入磁盘文件
				}
				goto ExitReadThread;
			default:
				AfxMessageBox("读数据未知错误...",MB_ICONERROR);
				goto ExitReadThread;
			}
			goto ExitReadThread;
		}
		// 发送事件,告诉绘制窗口线程,该批数据已采集完毕
		if(bNewSegmentData[ReadIndex]==TRUE)
		{
			AfxMessageBox("缓冲区溢出...", MB_ICONERROR);
			goto ExitReadThread;
		}
		bNewSegmentData[ReadIndex] = TRUE;
		SetEvent(hEvent);		
		ReadIndex++;
		if(ReadIndex==MAX_SEGMENT) ReadIndex=0;
	}// 线程循环取样	
	ExitReadThread:
	SetEvent(hExitEvent); // 发出设备成功退出消息,让关闭设备的线程得此消息
	Beep(3000, 1); // 响铃通知用户,线程已终止
	return TRUE;
}

BOOL StopDeviceAD_NotEmpty(HANDLE m_hDevice)
{
	bCreateDevice = FALSE;	
	bDeviceADRun = FALSE;
	if(m_ReadThread)
	{	
		WaitForSingleObject(m_ReadThread->m_hThread, 1000);//INFINITE);	// 等待子线程停止
	}

	if(m_ReadThread)
	{
		m_ReadThread->ExitInstance();
		m_ReadThread=NULL;
	}

	if(!PCI2006_ReleaseDeviceProAD(m_hDevice))
	{
		AfxMessageBox("关闭AD设备出错.....",MB_ICONSTOP,0);
	}	
	return TRUE;
}


//-------------------------------------------------------------------------------------------------------------------------------------
UINT ReadDataThread_Half(PVOID hWnd);//半满方式读取数据线程
BOOL StartDeviceAD_Half(HANDLE hDevice, PCI2006_PARA_AD ADPara)
{
	m_ReadThread=AfxBeginThread(ReadDataThread_Half,NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
	m_ReadThread->m_bAutoDelete=false;

	if(!PCI2006_InitDeviceProAD(hDevice, &ADPara))
	{
		AfxMessageBox("不明的初始化错误.....", MB_ICONERROR);
		return FALSE;
	}
	bDeviceADRun=TRUE;  // 告之采集线程可以工作了
	m_ReadThread->ResumeThread();  // 启动采集线程ReadThread
	return TRUE;
}
UINT ReadDataThread_Half(PVOID hWnd)  // 读数据线程
{
	CSysApp *pApp=(CSysApp *)AfxGetApp();
	CADDoc* pDoc=pApp->m_pADDoc; 
	// 在线程中取得视图指针
	
	BOOL bFirst=TRUE;    
	ULONG Wrote8KWCounter=0;
	ULONG WroteMB=0;  
	
	pDoc->m_Wrote8KWCounter=0;
	pDoc->m_WroteMB=0;
	// 复位段索引号
	ReadIndex = 0;
	int nChannelCount,nRemainder;
	nChannelCount = ADPara.ChannelCount ;
	nRemainder = FIFO_HALF_LENGTH % nChannelCount;
	ReadSizeWords = FIFO_HALF_LENGTH - nRemainder;//计算读取点数 半满读取 一次读取最佳点数位 FIFO/2 个点

	for(int i=0; i<MAX_SEGMENT; i++) // 将缓冲队列标志复位
	{
		bNewSegmentData[i] = FALSE; // 置成FALSE,表示该缓冲单元为无效数据
	}

	CString str1;	
	ULONG ReadCount;

	PCI2006_StartDeviceProAD(pApp->m_hDevice);  // 初始化后,启动设备
	BOOL bNotEmpty,bHalf,bOverflow;
	while(bDeviceADRun)  // 循环采集AD数据
	{
		while(bDeviceADRun) // 
		{
			PCI2006_GetDevStatusProAD(pApp->m_hDevice,&bNotEmpty,&bHalf,&bOverflow);//取得标志
			if(!bHalf)
			{
				PCI2006_DelayTime(pApp->m_hDevice, 1); // 延时100纳秒(如果在98下,则延时1毫秒)
			}
			else
				break;
		}
		ReadCount=PCI2006_ReadDeviceProAD_Half(pApp->m_hDevice, ADBuffer[ReadIndex], ReadSizeWords);
		
		if(ReadCount) // 如果返回数据量等于请求量,则处理数据
		{
			/*
			if(nProcessMode==3)  // 数据存盘
			{
				
				if(WroteMB>=(pDoc->m_RemainMB-2))
				{
					AfxMessageBox("对不起,当前磁盘已满,不能再存盘",MB_ICONSTOP,0);
					return FALSE;
				}
				PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], ReadSizeWords*2); // 将8192*2个字的数据存放在硬盘上
				FileLenghtWords+=ReadSizeWords;// 递加写入8K数据的计数器,以便存盘视图推进存盘进度条				
			}*/
		}
		else // 如果返回数据量不等于请求量,则分析原因,再处理数据
		{
			AfxMessageBox("读取数据错误");
			goto ExitReadThread;
		}
		// 发送事件,告诉绘制窗口线程,该批数据已采集完毕
		if(bNewSegmentData[ReadIndex]==TRUE)
		{
			AfxMessageBox("缓冲区溢出...", MB_ICONERROR);
			goto ExitReadThread;
		}
		bNewSegmentData[ReadIndex] = TRUE;
		// 建议:不要在数据采集线程中操作窗口,因为窗口操作(如放大、缩小、重绘)会花掉
		// CPU很多时间,处理不当,会引起采集线程的严重堵塞,使数据被丢掉。详细情况请参考
		// 软件说明书,在那里会告诉您很多解决方案。
		SetEvent(hEvent);		
		ReadIndex++;
		if(ReadIndex==MAX_SEGMENT) ReadIndex=0;
	}// 线程循环取样	
	ExitReadThread:
	SetEvent(hExitEvent); // 发出设备成功退出消息,让关闭设备的线程得此消息
	Beep(3000, 1); // 响铃通知用户,线程已终止
	return TRUE;
}

BOOL StopDeviceAD_Half(HANDLE m_hDevice)
{
	bCreateDevice = FALSE;	
	bDeviceADRun = FALSE;
	if(m_ReadThread)
	{	
		WaitForSingleObject(m_ReadThread->m_hThread, 1000);//INFINITE);	// 等待子线程停止
	}

	if(m_ReadThread)
	{
		m_ReadThread->ExitInstance();
		m_ReadThread=NULL;
	}

	if(!PCI2006_ReleaseDeviceProAD(m_hDevice))
	{
		AfxMessageBox("关闭AD设备出错.....",MB_ICONSTOP,0);
	}
	return TRUE;
}



//-------------------------------------------------------------------------------------------------------------------------------------
int m_IntReadSizeWords;
UINT ReadDataThread_Int(PVOID hWnd);
HANDLE hReadEventInt;
BOOL StartDeviceAD_Int(HANDLE hDevice, PCI2006_PARA_AD ADPara)
{
	int nChannelCount,nRemainder;
	nChannelCount = ADPara.ChannelCount ;
	nRemainder = FIFO_HALF_LENGTH % nChannelCount;
	m_IntReadSizeWords = FIFO_HALF_LENGTH - nRemainder;//计算读取点数 半满读取 一次读取最佳点数位 FIFO/2 个点
	
	m_ReadThread=AfxBeginThread(ReadDataThread_Int,NULL, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
	m_ReadThread->m_bAutoDelete=false;
	hReadEventInt=PCI2006_CreateSystemEvent();
	if(!PCI2006_InitDeviceIntAD(hDevice,hReadEventInt,m_IntReadSizeWords,&ADPara))
	{
		AfxMessageBox("不明的初始化错误.....", MB_ICONERROR);
		return FALSE;
	}
	bDeviceADRun=TRUE;  // 告之采集线程可以工作了
	m_ReadThread->ResumeThread();  // 启动采集线程ReadThread
	return TRUE;
}
UINT ReadDataThread_Int(PVOID hWnd)  // 读数据线程
{
	CSysApp *pApp=(CSysApp *)AfxGetApp();
	CADDoc* pDoc=pApp->m_pADDoc; 
	// 复位段索引号
	ReadIndex = 0;
	ReadSizeWords=FIFO_HALF_LENGTH;
	for(int i=0; i<MAX_SEGMENT; i++) // 将缓冲队列标志复位
	{
		bNewSegmentData[i] = FALSE; // 置成FALSE,表示该缓冲单元为无效数据
	}
	ULONG WroteMB=0;
	CString str1;	
	ULONG Remaining;

	PCI2006_StartDeviceIntAD(pApp->m_hDevice);  // 初始化后,启动设备
	while(bDeviceADRun)  // 循环采集AD数据
	{
		do{
			if(!bDeviceADRun) goto ExitReadThread;
		}while(WaitForSingleObject (hReadEventInt, 100)!=WAIT_OBJECT_0); 

		do
		{
			Remaining=PCI2006_ReadDeviceIntAD(pApp->m_hDevice, ADBuffer[ReadIndex], m_IntReadSizeWords);  	
			if(bNewSegmentData[ReadIndex]==TRUE)
			{
				AfxMessageBox("二级缓冲区溢出...", MB_ICONERROR);
				goto ExitReadThread;
			}
			if(Remaining!=0xe1000000)
			{
				/*
				if(nProcessMode==3)  // 数据存盘
				{
					if(WroteMB>=(pDoc->m_RemainMB-2))
					{
						AfxMessageBox("对不起,当前磁盘已满,不能再存盘",MB_ICONSTOP,0);
						goto ExitReadThread;
					}
					PCI2006_WriteFile(hFileObject, ADBuffer[ReadIndex], m_IntReadSizeWords*2);
					FileLenghtWords+=m_IntReadSizeWords;// 递加写入8K数据的计数器,以便存盘视图推进存盘进度条				
				}*/
				bNewSegmentData[ReadIndex] = TRUE;
				// 建议:不要在数据采集线程中操作窗口,因为窗口操作(如放大、缩小、重绘)会花掉
				// CPU很多时间,处理不当,会引起采集线程的严重堵塞,使数据被丢掉。详细情况请参考
				// 软件说明书,在那里会告诉您很多解决方案。
				SetEvent(hEvent);// 发送事件,告诉绘制窗口线程,该批数据已采集完毕
				ReadIndex++;
				if(ReadIndex==MAX_SEGMENT) ReadIndex=0;
			}		
			else
			{
				// 如果您需要容错处理,防止缓冲区溢出,数据丢失,请加入下列代码				
				AfxMessageBox("系统很忙,整个一级缓冲区已满,建议您在数据采集时,关闭所有不必要的应用程序,或缩小波形窗口等...",MB_ICONSTOP);
				goto ExitReadThread; 
			}
		}while(Remaining&&bDeviceADRun);		
	}// 线程循环取样	
ExitReadThread:
	SetEvent(hExitEvent); // 发出设备成功退出消息,让关闭设备的线程得此消息
	Beep(3000, 1); // 响铃通知用户,线程已终止
	return TRUE;
}

BOOL StopDeviceAD_Int(HANDLE m_hDevice)
{
	bCreateDevice = FALSE;	
	bDeviceADRun = FALSE;
	if(m_ReadThread)
	{	
		WaitForSingleObject(m_ReadThread->m_hThread, 1000);//INFINITE);	// 等待子线程停止
	}

	if(m_ReadThread)
	{
		m_ReadThread->ExitInstance();
		m_ReadThread=NULL;
	}

	if(!PCI2006_ReleaseDeviceIntAD(m_hDevice))
	{
		AfxMessageBox("关闭AD设备出错.....",MB_ICONSTOP,0);
	}
	PCI2006_ReleaseSystemEvent(hReadEventInt);//中断读数据消息
	return TRUE;
}





⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -