📄 adthread.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 + -