增加读取数据的模式。

This commit is contained in:
TAO Cheng
2014-04-30 18:09:38 +08:00
parent 46b61ce1e0
commit 5aec9f2552
9 changed files with 490 additions and 140 deletions
+276 -116
View File
@@ -3,14 +3,20 @@
#include <WinBase.h>
#include "ART_PCI8622.h"
#define MAX_AD_CHANNELS 4
#define SEGMENT_COUNT 32
#define HALF_SIZE_WORDS 4096
CART_PCI8622::CART_PCI8622()
{
m_hDevice=INVALID_HANDLE_VALUE;
m_hDmaEvent=NULL;
m_AD_LSB_MAX=0.0;
m_AD_LSB_HALF=0.0;
m_AD_LSB_RANGE=65536;
m_InputRange=0;
m_StopedCapture=TRUE;
m_EnStartCapture=FALSE;
m_EnGetData=FALSE;
m_iCaptureMode=0;
}
CART_PCI8622::~CART_PCI8622()
@@ -20,139 +26,293 @@ CART_PCI8622::~CART_PCI8622()
//========================================
BOOL CART_PCI8622::Init()
{
return TRUE;
BOOL rStatus(TRUE);
#ifdef _RELEASE_FULL_VERSION
int DeviceLgcID(0);
m_hDevice = PCI8622_CreateDevice(DeviceLgcID); // 创建设备对象
if(m_hDevice == INVALID_HANDLE_VALUE)
{
rStatus=FALSE;
}
#endif //_RELEASE_FULL_VERSION
return rStatus;
}
//========================================
BOOL CART_PCI8622::Exit()
{
return TRUE;
BOOL rStatus(TRUE);
#ifdef _RELEASE_FULL_VERSION
if (!m_StopedCapture)
{
rStatus=StopCaptureData();
}
rStatus=PCI8622_ReleaseDevice(m_hDevice); // 释放设备对象
m_hDevice=INVALID_HANDLE_VALUE;
#endif //_RELEASE_FULL_VERSION
return rStatus;
}
//========================================
BOOL CART_PCI8622::GetData()
BOOL CART_PCI8622::SetCaptureMode(int _Mode)
{
BOOL rStatus(TRUE);
#ifdef _RELEASE_FULL_VERSION
int InputRange(0);
int SelectInputRange(void);
WORD ADBuffer[SEGMENT_COUNT][HALF_SIZE_WORDS]; // 分配缓冲区(存储原始数据)
ULONG SegmentID = 0;
m_iCaptureMode=_Mode;
memset(&m_ADPara, 0x00, sizeof(m_ADPara)); // 将各项参数复位至确定值0(强烈建议)
switch(_Mode)
{
case E_ART_PCI8622_CAPTURE_DMA_SEQ:
case E_ART_PCI8622_CAPTURE_NPT_SEQ:
{
// 预置硬件参数
m_ADPara.ADMode = PCI8622_ADMODE_SEQUENCE; // AD模式为连续模式
m_ADPara.FirstChannel = 1; // 首通道
m_ADPara.LastChannel = 2; // 末通道
m_ADPara.Frequency = 10000; // 采样频率(Hz)
m_ADPara.GroupInterval = 50; // 组间间隔(uS)
m_ADPara.LoopsOfGroup = 1; // 组内各通道点数
m_ADPara.Gains = PCI8622_GAINS_1MULT;
m_ADPara.InputRange = m_InputRange; // 模拟量输入量程范围
HANDLE hDevice;
int DeviceLgcID;
m_ADPara.TriggerMode = PCI8622_TRIGMODE_SOFT; // 触发模式为软件触发
m_ADPara.TriggerType = PCI8622_TRIGTYPE_EDGE; // 触发类型为边沿触发
m_ADPara.TriggerDir = PCI8622_TRIGDIR_NEGATIVE; // 触发方向为负向
m_ADPara.TrigWindow = 40; // 触发灵敏度
PCI8622_PARA_AD ADPara; // 硬件参数
PCI8622_STATUS_DMA DMAStatus; // DMA状态参数
m_ADPara.ClockSource = PCI8622_CLOCKSRC_IN; // 时钟源选用板内时钟源
m_ADPara.bClockOutput = FALSE; // 禁止时钟输出
m_ADPara.GroundingMode = PCI8622_GNDMODE_SE; // 单端方式(SE:Single end)
m_ADPara.TimeoutForNpt = 10; // 在非空方式下,设置超时时间为10秒钟(只在非空查询方式下有效)
break;
}
case E_ART_PCI8622_CAPTURE_NPT_TRIGCLK:
case E_ART_PCI8622_CAPTURE_DMA_TRIGCLK:
{
// 预置硬件参数
m_ADPara.ADMode = PCI8622_ADMODE_GROUP; // AD模式为连续模式
m_ADPara.FirstChannel = 1; // 首通道
m_ADPara.LastChannel = 2; // 末通道
m_ADPara.Frequency = 10000; // 采样频率(Hz)
m_ADPara.GroupInterval = 50; // 组间间隔(uS)
m_ADPara.LoopsOfGroup = 1; // 组内各通道点数
m_ADPara.Gains = PCI8622_GAINS_1MULT;
m_ADPara.InputRange = m_InputRange; // 模拟量输入量程范围
int Index(0);
m_ADPara.TriggerMode = PCI8622_TRIGMODE_SOFT; // 触发模式为软件触发
m_ADPara.TriggerType = PCI8622_TRIGTYPE_EDGE; // 触发类型为边沿触发
m_ADPara.TriggerDir = PCI8622_TRIGDIR_NEGATIVE; // 触发方向为负向
m_ADPara.TrigWindow = 40; // 触发灵敏度
m_ADPara.ClockSource = PCI8622_CLOCKSRC_OUT; // 时钟源选用板内时钟源
m_ADPara.bClockOutput = FALSE; // 禁止时钟输出
m_ADPara.GroundingMode = PCI8622_GNDMODE_SE; // 单端方式(SE:Single end)
m_ADPara.TimeoutForNpt = 10; // 在非空方式下,设置超时时间为10秒钟(只在非空查询方式下有效)
break;
}
default:
{
break;
}
}
switch(m_InputRange)
{
case PCI8622_INPUT_N10000_P10000mV: // -10V - +10V
{
m_AD_LSB_MAX=20000.0;
m_AD_LSB_HALF=10000.0;
m_AD_LSB_RANGE=65536.0;
break;
}
case PCI8622_INPUT_N5000_P5000mV: // -5V - +5V
{
m_AD_LSB_MAX=10000.0;
m_AD_LSB_HALF=5000.0;
m_AD_LSB_RANGE=65536.0;
break;
}
case PCI8622_INPUT_N2500_P2500mV: // -2.5V - +2.5V.
{
m_AD_LSB_MAX=5000.0;
m_AD_LSB_HALF=2500.0;
m_AD_LSB_RANGE=65536.0;
break;
}
break;
case PCI8622_INPUT_0_P10000mV: // 0V - +10V
{
m_AD_LSB_MAX=10000.0;
m_AD_LSB_HALF=0.0;
m_AD_LSB_RANGE=65536.0;
break;
}
case PCI8622_INPUT_0_P5000mV: // 0V - +5V
{
m_AD_LSB_MAX=5000.0;
m_AD_LSB_HALF=0.0;
m_AD_LSB_RANGE=65536.0;
break;
}
default:
{
m_AD_LSB_MAX=0.0;
m_AD_LSB_HALF=0.0;
m_AD_LSB_RANGE=65536.0;
break;
}
}
switch(_Mode)
{
case E_ART_PCI8622_CAPTURE_DMA:
case E_ART_PCI8622_CAPTURE_DMA_SEQ:
case E_ART_PCI8622_CAPTURE_DMA_TRIGCLK:
{
m_hDmaEvent = PCI8622_CreateSystemEvent();
if (!PCI8622_InitDeviceDmaAD(m_hDevice, m_hDmaEvent, &ADBuffer[0][0], 4096, SEGMENT_COUNT, HALF_SIZE_WORDS, &m_ADPara)) // 初始化硬件
{
rStatus=FALSE;
StopCaptureData();
}
break;
}
case E_ART_PCI8622_CAPTURE_NPT:
case E_ART_PCI8622_CAPTURE_NPT_SEQ:
case E_ART_PCI8622_CAPTURE_NPT_TRIGCLK:
{
if (!PCI8622_InitDeviceProAD(m_hDevice, &m_ADPara))
{
rStatus=FALSE;
StopCaptureData();
}
break;
}
}
if (rStatus)
{
m_StopedCapture=FALSE;
m_EnStartCapture=TRUE;
}
#endif //_RELEASE_FULL_VERSION
return rStatus;
}
//========================================
BOOL CART_PCI8622::StartCaptureData()
{
BOOL rStatus(TRUE);
#ifdef _RELEASE_FULL_VERSION
rStatus=PCI8622_StartDeviceDmaAD(m_hDevice); // 启动设备
m_StopedCapture=FALSE;
m_EnGetData=TRUE;
#endif //_RELEASE_FULL_VERSION
return rStatus;
}
//========================================
BOOL CART_PCI8622::StopCaptureData()
{
BOOL rStatus(TRUE);
#ifdef _RELEASE_FULL_VERSION
rStatus=PCI8622_ReleaseDeviceDmaAD(m_hDevice); // 释放AD
rStatus=PCI8622_ReleaseSystemEvent(m_hDmaEvent);
m_EnStartCapture=FALSE;
m_StopedCapture=TRUE;
m_EnGetData=FALSE;
#endif //_RELEASE_FULL_VERSION
return rStatus;
}
//========================================
BOOL CART_PCI8622::GetData(double (*_Data)[HALF_SIZE_WORDS],int* _DataNumber)
{
BOOL rStatus(TRUE);
#ifdef _RELEASE_FULL_VERSION
if(!m_EnGetData)
{
return FALSE;
}
int nADChannel = 0;
WORD ADData(0);
float fVolt(0);
DeviceLgcID = 0;
hDevice = PCI8622_CreateDevice(DeviceLgcID); // 创建设备对象
if(hDevice == INVALID_HANDLE_VALUE)
{
rStatus=FALSE;
return rStatus; // 如果创建设备对象失败,则返回
}
memset(&ADPara, 0x00, sizeof(ADPara)); // 将各项参数复位至确定值0(强烈建议)
// 预置硬件参数
ADPara.ADMode = PCI8622_ADMODE_SEQUENCE; // AD模式为连续模式
ADPara.FirstChannel = 1; // 首通道
ADPara.LastChannel = 2; // 末通道
ADPara.Frequency = 10000; // 采样频率(Hz)
ADPara.GroupInterval = 50; // 组间间隔(uS)
ADPara.LoopsOfGroup = 1; // 组内各通道点数
ADPara.Gains = PCI8622_GAINS_1MULT;
ADPara.InputRange = InputRange; // 模拟量输入量程范围
ADPara.TriggerMode = PCI8622_TRIGMODE_SOFT; // 触发模式为软件触发
ADPara.TriggerType = PCI8622_TRIGTYPE_EDGE; // 触发类型为边沿触发
ADPara.TriggerDir = PCI8622_TRIGDIR_NEGATIVE; // 触发方向为负向
ADPara.TrigWindow = 40; // 触发灵敏度
ADPara.ClockSource = PCI8622_CLOCKSRC_IN; // 时钟源选用板内时钟源
ADPara.bClockOutput = FALSE; // 禁止时钟输出
ADPara.GroundingMode = PCI8622_GNDMODE_SE; // 单端方式(SE:Single end)
ADPara.TimeoutForNpt = 10; // 在非空方式下,设置超时时间为10秒钟(只在非空查询方式下有效)
HANDLE hDmaEvent = PCI8622_CreateSystemEvent();
if(!PCI8622_InitDeviceDmaAD( hDevice, hDmaEvent, &ADBuffer[0][0], 4096, SEGMENT_COUNT, HALF_SIZE_WORDS, &ADPara)) // 初始化硬件
{
rStatus=FALSE;
goto ExitRead0;
}
PCI8622_StartDeviceDmaAD(hDevice); // 启动设备
bool bWait(true);
while(bWait) // 查询当前物理缓冲区数据是否已准备就绪
{
if(WaitForSingleObject (hDmaEvent, 100)==WAIT_OBJECT_0)
bWait=false; // 等待DMA事件
}
if(!PCI8622_GetDevStatusDmaAD(hDevice, &DMAStatus))
{
rStatus=FALSE;
goto ExitRead0;
}
if(DMAStatus.bBufferOverflow)
{
rStatus=FALSE;
}
for(SegmentID=0; SegmentID<SEGMENT_COUNT; SegmentID++)
{
if(DMAStatus.bSegmentSts[SegmentID])
{
nADChannel = ADPara.FirstChannel;
for(Index=0; Index<64; Index++)
double dVolt(0);
int Index(0);
switch(m_iCaptureMode)
{
case E_ART_PCI8622_CAPTURE_DMA:
case E_ART_PCI8622_CAPTURE_DMA_SEQ:
case E_ART_PCI8622_CAPTURE_DMA_TRIGCLK:
{
ADData = ((ADBuffer[SegmentID][Index]));
// 将原码转换为电压值
switch(InputRange)
bool bWait(true);
while(bWait) // 查询当前物理缓冲区数据是否已准备就绪
{
case PCI8622_INPUT_N10000_P10000mV: // -10V - +10V
fVolt = (float)((20000.0/65536) * ADData - 10000.0);
break;
case PCI8622_INPUT_N5000_P5000mV: // -5V - +5V
fVolt = (float)((10000.0/65536) * ADData - 5000.0);
break;
case PCI8622_INPUT_N2500_P2500mV: // -2.5V - +2.5V
fVolt = (float)((5000.0/65536) * ADData - 2500.0);
break;
case PCI8622_INPUT_0_P10000mV: // 0V - +10V
fVolt = (float)((10000.0/65536) * ADData);
break;
case PCI8622_INPUT_0_P5000mV: // 0V - +5V
fVolt = (float)((5000.0/65536) * ADData);
break;
default:
break;
if(WaitForSingleObject (m_hDmaEvent, 100)==WAIT_OBJECT_0)
bWait=false; // 等待DMA事件
}
nADChannel++;
if(nADChannel > ADPara.LastChannel)
PCI8622_STATUS_DMA DMAStatus; // DMA状态参数
if(!PCI8622_GetDevStatusDmaAD(m_hDevice, &DMAStatus))
{
nADChannel = ADPara.FirstChannel;
}
rStatus=FALSE;
StopCaptureData();
}
if(DMAStatus.bBufferOverflow)
{
rStatus=FALSE;
}
for(m_SegmentID=0; m_SegmentID<SEGMENT_COUNT; m_SegmentID++)
{
if(DMAStatus.bSegmentSts[m_SegmentID])
{
nADChannel = m_ADPara.FirstChannel;
for(Index=0; Index<64; Index++)
{
ADData = ((ADBuffer[m_SegmentID][Index]));
// 将原码转换为电压值
dVolt = static_cast<double>(((m_AD_LSB_MAX/m_AD_LSB_RANGE) * ADData - m_AD_LSB_HALF));
_Data[nADChannel][_DataNumber[nADChannel]]=dVolt;
_DataNumber[nADChannel]+=1;
nADChannel++;
if(nADChannel > m_ADPara.LastChannel)
{
nADChannel = m_ADPara.FirstChannel;
}
}
}
if(!PCI8622_SetDevStatusDmaAD(m_hDevice, m_SegmentID))
{
rStatus=FALSE;
StopCaptureData();
}
}
break;
}
}
case E_ART_PCI8622_CAPTURE_NPT:
case E_ART_PCI8622_CAPTURE_NPT_SEQ:
case E_ART_PCI8622_CAPTURE_NPT_TRIGCLK:
{
m_SegmentID=0;
LONG nReadSizeWords = 4096;
LONG nRetSizeWords(0);
PCI8622_ReadDeviceProAD_Npt(m_hDevice, ADBuffer[0], nReadSizeWords, &nRetSizeWords);
nADChannel = m_ADPara.FirstChannel;
TRACE1("[PCI8622_ReadDeviceProAD_Npt] Retsize:%d.\r\n",nRetSizeWords);
for(Index=0; Index<nRetSizeWords; Index++)
{
ADData = ((ADBuffer[m_SegmentID][Index]));
// 将原码转换为电压值
dVolt = static_cast<double>(((m_AD_LSB_MAX/m_AD_LSB_RANGE) * ADData - m_AD_LSB_HALF));
_Data[nADChannel][_DataNumber[nADChannel]]=dVolt;
_DataNumber[nADChannel]+=1;
nADChannel++;
if(nADChannel > m_ADPara.LastChannel)
{
nADChannel = m_ADPara.FirstChannel;
}
}
break;
}
}
if(!PCI8622_SetDevStatusDmaAD(hDevice, SegmentID))
{
rStatus=FALSE;
goto ExitRead0;
}
} // end of for(SegmentID=0; SegmentID<SEGMENT_COUNT; SegmentID++)
ExitRead0:
PCI8622_ReleaseDeviceDmaAD(hDevice); // 释放AD
PCI8622_ReleaseSystemEvent(hDmaEvent);
PCI8622_ReleaseDevice(hDevice); // 释放设备对象
m_StopedCapture=FALSE;
#endif //_RELEASE_FULL_VERSION
return rStatus;
+33 -2
View File
@@ -7,18 +7,49 @@
#endif // _MSC_VER > 1000
#include "PCI8622.h"
#define MAX_AD_CHANNELS 4
#define SEGMENT_COUNT 32
#define HALF_SIZE_WORDS 4096
enum E_ART_PCI8622_CAPTURE_MODE
{
E_ART_PCI8622_CAPTURE_DMA=0,
E_ART_PCI8622_CAPTURE_DMA_SEQ,
E_ART_PCI8622_CAPTURE_DMA_TRIGCLK,
E_ART_PCI8622_CAPTURE_NPT=10,
E_ART_PCI8622_CAPTURE_NPT_SEQ,
E_ART_PCI8622_CAPTURE_NPT_TRIGCLK,
E_ART_PCI8622_CAPTURE_HALF=20,
E_ART_PCI8622_CAPTURE_TOTAL=255
};
//======================================================================================
class CART_PCI8622
{
protected:
HANDLE m_hDevice;
HANDLE m_hDmaEvent;
int m_InputRange;
WORD ADBuffer[SEGMENT_COUNT][HALF_SIZE_WORDS];
ULONG m_SegmentID;
PCI8622_PARA_AD m_ADPara; // Ó²¼þ²ÎÊý
double m_AD_LSB_MAX;
double m_AD_LSB_HALF;
double m_AD_LSB_RANGE;
BOOL m_StopedCapture;
BOOL m_EnStartCapture;
BOOL m_EnGetData;
int m_iCaptureMode;
public:
CART_PCI8622();
~CART_PCI8622();
BOOL Init();
BOOL Exit();
BOOL GetData();
BOOL SetCaptureMode(int _Mode=0);
BOOL StartCaptureData();
BOOL StopCaptureData();
BOOL GetData(double (*_Data)[HALF_SIZE_WORDS],int* _DataNumber);
};
#endif