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

📄 adthread.cpp

📁 用于数据采集分析的对话框界面
💻 CPP
字号:
//*********************************************************************
//数据采集线程处理单元(ADThread.cpp)
//
//*********************************************************************
#include "stdAfx.h"
#include "CAITest.h"
#include "ADThread.h"
//#include "ADThread.h"

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


extern DWORD gPulseWidth;
extern DWORD gIgition;
extern DWORD gRPM;
extern DWORD gLoad;
extern DWORD gIgn;
extern int gSaveSelect;
extern CCAITestApp theApp;
//***********************************************************************
// 用于确定当前段数据是否为最新数据
BOOL bNewSegmentData[MAX_SEGMENT];
//数据采集线程
CWinThread* m_ReadThread;
//--------------------------------------------------
UINT ReadDataThread_NotEmpty(LPVOID 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;
	}
	theApp.m_Stand.m_DABoard.m_bDeviceADRun = TRUE;
	m_ReadThread->ResumeThread();  // 启动采集线程ReadDataThread_NotEmpty
	return TRUE;
}

UINT ReadDataThread_NotEmpty(LPVOID hWnd)  // 读数据线程
{
	//采集卡配置参数
	PCI2006_PARA_AD ADPara = theApp.m_Stand.m_DABoard.m_ADPara;
	// 复位段索引号
	//数据采集开始时,将自己的ReadIndex = 0;即用第一个缓冲区采集数据
	int	ReadIndex = 0;
	//确定采集时读入的数据长度
	ULONG ReadSizeWords = theApp.m_Stand.m_DABoard.GetReadSizeWords();

	for(int i=0; i<MAX_SEGMENT; i++) // 将缓冲队列标志复位
	{
		bNewSegmentData[i] = FALSE; // 置成FALSE,表示该缓冲单元为无效数据
	}
	
	theApp.m_pDoc->SetMciTimer(55);   // 启动多媒体定时器,让其开始等待绘图

	// 初始化后,启动设备
	HANDLE hADDevice= theApp.m_Stand.m_DABoard.m_hDevice;
	PCI2006_StartDeviceProAD(hADDevice); 

	//由StartDeviceAD_NotEmpty函数
	//设定循环采集AD数据的标志bDeviceADRun
	ULONG ReadCount, dwErrorCode;
	//存盘文件句柄
	HANDLE hFileObject;
	//存盘文件
	CString strFileName;
	//存盘时变化的文件数名
	ULONG FileNum = 0;
	while(theApp.m_Stand.m_DABoard.m_bDeviceADRun == TRUE)  // 循环采集AD数据
	{   
	
		ReadCount=PCI2006_ReadDeviceProAD_NotEmpty(hADDevice, 
								theApp.m_Stand.m_DABoard.m_ADBuffer[ReadIndex], 
								ReadSizeWords, 
								false);
		if(ReadCount==ReadSizeWords) // 如果返回数据量等于请求量,则处理数据
		{	
			SetDeviceAddress(hADDevice);
	
			if (theApp.m_bWriteFile) 
			{
				theApp.m_saveNum++;
				if(gSaveSelect == 0){
					if(theApp.m_saveNum>101){
						theApp.m_bWriteFile=false;
						theApp.m_pMonitorFrm->ADStopSave();
					}
				}
				CString strNum;
				strNum.Format("%d", theApp.m_saveNum);
				strFileName =  theApp.m_DataSavePath+"\\" + strNum + ".pci";
				//建立数据文件
				hFileObject =  PCI2006_CreateFileObject(hADDevice, 
									strFileName, 
									PCI2006_modeCreate|PCI2006_modeWrite ) ;
				if ( hFileObject == INVALID_HANDLE_VALUE )
				{
					theApp.m_bWriteFile = FALSE;
					AfxMessageBox("初始化文件对象失败...",MB_ICONSTOP,0);
					return false;
				}	
				//
				FILE_HEADER header;
				//喷油脉宽
				header.BusType =gPulseWidth;//PCI_BUS;  // 厂商ID号
				//
				header.DeviceID =gIgition;//0x2006;
				//
				header.HeaderSizeBytes =gRPM;//sizeof(FILE_HEADER);
				//
				header.ADMode=gLoad;//ADPara.ADMode ; // 连续采集和分组采集方式选择
				//
				header.ChannelCount=gIgn;//ADPara.ChannelCount;// 通道总数(1-32)
				header.VoltBottomRange =-5;
				header.VoltTopRange =5;
				for(int i=0; i<32; i++) 
				{
				header.ChannelArray[i].ADChannel = ADPara.ChannelArray[i].ADChannel;
				header.ChannelArray[i].ADGains = 1 ;//ADPara.ChannelArray[i].ADGains;
				}

				header.Frequency=ADPara.Frequency ;           // AD采集频率(Hz)
				header.GroupInterval=ADPara.GroupInterval ;	   // 分组采样时,相邻组的时间间隔(uS)
				header.TriggerSource=ADPara.TriggerSource ;	   // 内触发和外触发方式选择
				header.OutTriggerEdge=ADPara.OutTriggerEdge ;	   // 外触发上升沿和下降沿类型选择
				header.OutDigitAnalog=ADPara.OutDigitAnalog ;	   // 外触发数字和模拟方式选择
				header.ClockSource=ADPara.ClockSource ;         // 允许使用外部时钟
				header.FileEndFlag =0xAA55AA55;
				PCI2006_WriteFile(hFileObject,(SHORT*)&header,
									sizeof(FILE_HEADER)); 
				//
				
				// 将2000*2个字的数据存放在硬盘上
				// 将数据写入文件,起点:ADBuffer[ReadIndex],0,长度:ReadSizeWords*2
				PCI2006_WriteFile(hFileObject, 
					theApp.m_Stand.m_DABoard.m_ADBuffer[ReadIndex], 
							(ReadSizeWords)*2);

				//记录记录时间

				//释放文件句柄
				PCI2006_ReleaseFile( hFileObject);
			}
		}
		else // 如果返回数据量不等于请求量,则分析原因,再处理数据
		{
			dwErrorCode = GetLastError();
			CString str;
			switch(dwErrorCode)
			{
			case 0xE1000000:
				AfxMessageBox("FIFO溢出, 数据丢失,请注意溢出前返回的数据量...",MB_ICONERROR);
				str.Format("溢出前所返回的数据长度为 %d", ReadCount);
				AfxMessageBox(str,MB_ICONSTOP);
				
				// 将最后一次数据写入磁盘文件
				if (theApp.m_bWriteFile) 
				{
					PCI2006_WriteFile(hFileObject, 
						theApp.m_Stand.m_DABoard.m_ADBuffer[ReadIndex], 
						ReadCount*2); 
				}
				goto ExitReadThread;

			case 0xE2000000:
				if (theApp.m_bWriteFile)   // 数据存盘
				{
				PCI2006_WriteFile(hFileObject, 
					theApp.m_Stand.m_DABoard.m_ADBuffer[ReadIndex], 
					ReadCount*2); // 将最后一次数据写入磁盘文件
				}
				AfxMessageBox("数据丢失,将最后一次数据写入磁盘文件...",MB_ICONERROR);
				goto ExitReadThread;
			default:
				AfxMessageBox("读数据未知错误...",MB_ICONERROR);
				goto ExitReadThread;
			}
		}

		//数据采集完毕处理
		////表示该缓冲区已有数据,但还未处理
		////所以提示缓冲区溢出,即上次该缓冲区采集的数据还未处理
		
		if(bNewSegmentData[ReadIndex]==TRUE)
		{
			AfxMessageBox("缓冲区溢出...", MB_ICONERROR);
			goto ExitReadThread;
		}
		
		//设置缓冲区标志有效,表示已有数采集到
		bNewSegmentData[ReadIndex] = TRUE;

		//发送事件,告诉数据处理窗口线程,该批数据已采集完毕
		SetEvent(theApp.m_hEvent);
		//
		ReadIndex++;
		//MAX_SEGMENT:ADBuffer[MAX_SEGMENT][16384]; // 缓冲队列
		//当缓冲区到达最大时,复位段索引号
		//即下次采集用第一个缓冲区采集数据
		if(ReadIndex==MAX_SEGMENT) ReadIndex=0;
	
	}// 线程循环取样
	
	ExitReadThread:
	theApp.m_pDoc->KillMciTimer();
	SetEvent(theApp.m_hExitEvent); // 发出设备成功退出消息,让关闭设备的线程得此消息
	Beep(3000, 1); // 响铃通知用户,线程已终止
	return TRUE;
}

BOOL StopDeviceAD_NotEmpty(HANDLE m_hDevice)
{	
	
	if(m_ReadThread)
	{	
		WaitForSingleObject(m_ReadThread->m_hThread, INFINITE);//1000);	
	}

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


//-------------------------------------------------------------------------------------------------------------------------------------
void SetDeviceAddress(HANDLE hDevice)
{
	//ADCNTL4	清外触发端口	2B0	可写	清外触发标志
	ULONG LinearAddr, PhysAddr; //OffsetBytes
	WORD Value;

	if (!PCI2006_GetDeviceAddr(hDevice,&LinearAddr,&PhysAddr, 0) )
	{
		AfxMessageBox ("取得设备地址失败…");
	}
	Value = 0;
	// 往指定映射寄存器单元写入8位的十六进制数据0
	PCI2006_WriteRegisterWord(hDevice, LinearAddr, 0x2B0, Value); 
	PCI2006_WriteRegisterWord(hDevice, LinearAddr, 0x2E0, Value); 
}

void GetDeviceAddress(HANDLE hDevice)
{ 
	ULONG LinearAddr,  PhysAddr, OffsetBytes;
	WORD Value;
	PCI2006_GetDeviceAddr(hDevice, &LinearAddr, &PhysAddr, 0);   // 取得PCI设备0号映射寄存器的线性基地址
	OffsetBytes=688;
	Value = PCI2006_ReadRegisterWord(hDevice, LinearAddr, OffsetBytes);  // 从指定映射寄存器单元读入8位数据
}

//-------------------------------------------------------------------------------------------

⌨️ 快捷键说明

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