研华USB4711A采集卡高速中断模式采集总结

研华USB4711A采集卡是一款USB接口的采集卡,笔记本上就可以用,不用专门要ISA或者PCI插槽,价格上倒是比较贵,AI最多可以到150KS/s。这里记录高速中断模式采集使用方法。

windows平台:xp sp3 

框架:vs2010 MFC 单文档

采集速度:4通道,每通道200HZ

采集模式:使用FIFO

==============================================================

  1. 安装研华设备管理器、4711驱动,再装下研华光盘给的MFC例子,里面AD_INT和MAD_INT是官方给的高速采集demo。
  2. 将研华给的头文件及lib库文件添加到工程文件夹里。本站下载在这里,工程属性-linker-input-additinal dependencies里添加adsapi32.lib,工程属性-linker-general-additinal library dependencies里添加adsapi32.lib所在目录,工程.h文件里包含头文件#include "Driver.h"
  3. .h文件里添加变量声明
    LRESULT					m_ErrCode;  
    	LONG					m_DriverHandle;
    	ULONG					m_dwDeviceNum;  
    	DEVFEATURES				m_DevFeatures;
    	ULONG					m_gwActualBufSize;
    	USHORT					m_GainCode;
    	USHORT					m_gwActiveBuf;		// return by FAICheck
    	USHORT					m_gwOverrun;		// return by FAICheck, FAITransfer
    	USHORT					m_gwStopped;		// return by FAICheck
    	ULONG					m_gulRetrieved;     // return by FAICheck
    	USHORT					m_gwHalfReady;		// return by FAICheck
    	PT_DeviceGetFeatures	m_ptDevFeatures;
    	//	PT_FAIIntStart			m_ptFAIIntStart;     // FAIIntStart table
    	PT_FAIIntScanStart		m_ptFAIIntScanStart; // m_ptFAIIntScanStart table
    
    	PT_FAITransfer			m_ptFAITransfer;     // FAITransfer table
    	PT_FAICheck				m_ptFAICheck;        // FAICheck table
    	PT_AllocateDMABuffer	m_ptAllocateDMABuffer;  // buffer table
    	PT_EnableEvent			m_ptEnableEvent;     // Enable event
    	PT_CheckEvent			m_ptCheckEvent;      // Check event
    	USHORT					m_CyclicCount;
    	CWinThread*				m_pEventThread;
    	HGLOBAL					m_hUserBuf;
    	HGLOBAL					m_hBuf;
    	ULONG					m_ulInterruptCount;
    	ULONG					m_ulOverRunCount;
    	ULONG					m_ulBuffCount;
    	//OpenEvent dialog get follow par
    	bool	m_bGetParOk;
    	//int		m_GainOption;
    	USHORT	m_Gain[4];
    	int		m_Model;
    	int		m_Triggering;
    	int		m_Buffer;
    	int		m_DataType;
    	int		m_Event;
    	int		m_PacerRate;
    	int		m_Conv;
    	CString	m_InputRange;
    	int		m_ScanChannel;
    	int		m_FifoSize;
    	BOOL	m_EnableFifo;
    
    	LPVOID temp;
    	void adInterruptEvent();
    	void adBufChangeEvent();
    	void adOverrunEvent();
    	void adTerminateEvent();

  4. .cpp的构造函数里初始化参数,这里直接设定了,没用自带demo从对话框配置参数。
    m_gwActualBufSize	= 0;
    		m_ulBuffCount		= 0;
    		m_ulInterruptCount	= 0;
    		m_ulOverRunCount	= 0;
    
    
    		m_Conv			= 128 ;			//单次采集个数
    		m_Gain[0]		= 4 ;			//增益选项 10v-4   5v-0 
    		m_Gain[1]		= 0 ;
    		m_Gain[2]		= 0 ;
    		m_Gain[3]		= 0 ;
    
    		m_Model			= 1 ;			//是否循环模式
    		m_Triggering	= 0 ;			//内触发模式
    		m_Buffer		= 0 ;			
    		m_DataType		= 1 ;			//0-二进制值  1-电压值			
    		m_dwDeviceNum	= 0 ;			//管理器里设备编号
    		m_Event			= 1 ;			//事件使能
    		m_GainCode		= 0 ;			//内触发模式
    		m_PacerRate		= 800 ;			//采样频率单位 HZ  USB4711A form 1 Hz  to 150 kHz  但是是8个通道累积达到单通道最高150/8
    		m_InputRange	= _T("") ;		//
    
    		m_FifoSize		= 64 ;			//设定FIFO大小 7411为1024  buffer大小应该是FIFO/2 大小的整数倍(偶数),
    		m_EnableFifo	= TRUE ;		//使用FIFO
    		m_bGetParOk		= true ;

  5. 开启采集
    // Step 1: Open Device
    		m_ErrCode = DRV_DeviceOpen(m_dwDeviceNum, (LONG far *)&m_DriverHandle);
    		CString s;
    		if (m_ErrCode != SUCCESS)
    		{
    			DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    			s = m_szErrorMsg;
    			AfxMessageBox(s);
    			return;
    		}
    
    		// Step 2: Get device features
    		m_ptDevFeatures.buffer = (LPDEVFEATURES)&m_DevFeatures;
    		m_ptDevFeatures.size = sizeof(DEVFEATURES);
    		if ((m_ErrCode = DRV_DeviceGetFeatures(m_DriverHandle,
    			(LPT_DeviceGetFeatures)&m_ptDevFeatures)) != SUCCESS)
    		{
    			DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    			s = m_szErrorMsg;
    			AfxMessageBox(s);
    			DRV_DeviceClose((LONG far *)&m_DriverHandle);
    			return;
    		}
    		// Step 3: Allocate memory for driver
    		if((m_hBuf=(USHORT far *)GlobalAlloc(GHND,
    			sizeof(USHORT) * m_Conv)) == 0)
    		{		
    			AfxMessageBox(_T("高速缓存不足!"));
    			DRV_DeviceClose((LONG far *)&m_DriverHandle);
    			return;
    		}
    
    		// Step 4: Allocate memory for Voltage data or Raw data
    		if((m_hUserBuf=(FLOAT far *)GlobalAlloc(GHND,
    			sizeof(FLOAT) * m_Conv )) == 0)
    		{		
    			AfxMessageBox(_T("高速缓存不足!"));
    			DRV_DeviceClose((LONG far *)&m_DriverHandle);
    			return;
    		}
    		// Prepare some informations to run
    		m_ptFAIIntScanStart.buffer     = (USHORT far *)GlobalLock(m_hBuf);/*       */
    		m_ptFAITransfer.DataBuffer = (FLOAT far  *)GlobalLock(m_hUserBuf);
    
    
    		// Step 5: Enable event feature
    		m_ptEnableEvent.EventType = ADS_EVT_INTERRUPT  |
    			ADS_EVT_BUFCHANGE  |
    			ADS_EVT_TERMINATED |
    			ADS_EVT_OVERRUN;
    		m_ptEnableEvent.Enabled = m_Event;
    		m_ptEnableEvent.Count   = m_EnableFifo ? m_FifoSize : 1;
    		if ((m_ErrCode = DRV_EnableEvent(m_DriverHandle,
    			(LPT_EnableEvent)&m_ptEnableEvent)) != 0)
    		{
    			DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    			s = m_szErrorMsg;
    			AfxMessageBox(s);
    			GlobalUnlock(m_hBuf);
    			GlobalUnlock(m_hUserBuf);
    			GlobalFree(m_hBuf);
    			GlobalFree(m_hUserBuf);
    			DRV_DeviceClose((LONG far *)&m_DriverHandle);
    			return;
    		}
    		// Step 6: Start Interrupt transfer
    		m_ptFAIIntScanStart.TrigSrc		 = m_Triggering;
    		m_ptFAIIntScanStart.SampleRate	 = m_PacerRate;
    		m_ptFAIIntScanStart.StartChan	 = 0;
    		m_ptFAIIntScanStart.NumChans	 = 4;
    		m_ptFAIIntScanStart.GainList	 = &m_Gain[0];
    		m_ptFAIIntScanStart.count		 = m_Conv;
    		m_ptFAIIntScanStart.cyclic		 = m_Model;
    		if (m_EnableFifo && m_FifoSize)
    			m_ptFAIIntScanStart.IntrCount = m_FifoSize;
    		else
    			m_ptFAIIntScanStart.IntrCount = 1;
    
    		if ((m_ErrCode = DRV_FAIIntScanStart(m_DriverHandle,
    			(LPT_FAIIntScanStart32)&m_ptFAIIntScanStart)) != 0)
    		{
    			DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    			s = m_szErrorMsg;
    			AfxMessageBox(s);
    			GlobalUnlock(m_hBuf);
    			GlobalUnlock(m_hUserBuf);
    			GlobalFree(m_hBuf);
    			GlobalFree(m_hUserBuf);
    			DRV_DeviceClose((LONG far *)&m_DriverHandle);
    			return;
    		}
    		m_CyclicCount = 0;		
    
    		if (m_Event)
    		{
    			m_pEventThread = AfxBeginThread(EventThread,this);
    		}
    		m_ulInterruptCount=0;
    		m_ulBuffCount=0;           
    		m_ulOverRunCount=0;

  6. 几个配合函数照抄demo里的函数
    void CUSB4711AIINTView::adInterruptEvent()
    	{
    		return;
    	}
    
    
    
    	void CUSB4711AIINTView::adOverrunEvent()
    	{
    		// clear overrun
    		if ((m_ErrCode = DRV_ClearOverrun(m_DriverHandle)) != 0)
    		{
    			DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    			CString s;
    			s = m_szErrorMsg;
    			AfxMessageBox(s);
    			return ;
    		}
    
    		return;
    	}
    
    	void CUSB4711AIINTView::adTerminateEvent()
    	{
    
    		// Get real voltage of buffer from driver
    		m_ptFAITransfer.ActiveBuf = 0;   // single buffer
    		m_ptFAITransfer.DataType = m_DataType;
    		m_ptFAITransfer.start    = 0;
    		m_ptFAITransfer.count    = m_Conv;
    		m_ptFAITransfer.overrun  = &m_gwOverrun;
    
    		if ((m_ErrCode = DRV_FAITransfer(m_DriverHandle,
    			(LPT_FAITransfer)&m_ptFAITransfer)) != 0)
    		{
    			DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    			CString s;
    			s = m_szErrorMsg;
    			AfxMessageBox(s);
    			return ;
    		}
    
    		// Close driver
    		DRV_DeviceClose((LONG far *)&m_DriverHandle);
    
    		GlobalUnlock(m_hBuf);
    		GlobalUnlock(m_hUserBuf);
    		GlobalFree(m_hBuf);
    		GlobalFree(m_hUserBuf);
    
    		return;
    	}
    
    
    
    
    
    	UINT EventThread( LPVOID pParam )
    	{
    		USHORT usEventType;
    		LONG  ErrCde;
    
    
    		CUSB4711AIINTView*	pView = (CUSB4711AIINTView*)pParam;
    
    
    		pView->m_ulInterruptCount=0;
    		pView->m_ulBuffCount=0;           
    		pView->m_ulOverRunCount=0;
    
    		while(1)
    		{
    			// Check message
    			pView->m_ptCheckEvent.EventType = &usEventType;
    
    			if ((pView->m_Triggering) || (pView->m_Model) )
    			{
    				pView->m_ptCheckEvent.Milliseconds = INFINITE;
    			}
    			else
    			{
    				pView->m_ptCheckEvent.Milliseconds = 1000 * (pView->m_Conv / pView->m_PacerRate) + 1000;
    			}
    
    			if ((ErrCde = DRV_CheckEvent(pView->m_DriverHandle,
    				(LPT_CheckEvent)&pView->m_ptCheckEvent)) != 0)
    			{			
    				AfxMessageBox(_T("Check Event Error !"));
    				return 0;
    			}
    
    			// Process interrupt event
    			if (usEventType & ADS_EVT_INTERRUPT)
    			{
    				pView->adInterruptEvent();
    				pView->m_ulInterruptCount++;
    			}
    
    
    			// Process buffer change event
    			if (usEventType & ADS_EVT_BUFCHANGE)
    			{
    				pView->m_ulBuffCount++;           
    				pView->adBufChangeEvent();
    			}
    
    			// Process overrun event
    			if (usEventType & ADS_EVT_OVERRUN)
    			{
    				pView->m_ulOverRunCount++;
    				pView->adOverrunEvent();
    			}
    
    			// Process terminate event
    			if (usEventType & ADS_EVT_TERMINATED)
    			{
    				pView->adTerminateEvent();		
    				return 0;
    			}
    
    
    		}
    
    		AfxEndThread(0,true);
    		return 0;
    	}
    

  7. 最关键的步骤在函数
    	void CUSB4711AIINTView::adBufChangeEvent()
    	{
    		m_ptFAICheck.ActiveBuf = &m_gwActiveBuf;
    		m_ptFAICheck.stopped   = &m_gwStopped;
    		m_ptFAICheck.retrieved = &m_gulRetrieved;
    		m_ptFAICheck.overrun   = &m_gwOverrun;
    		m_ptFAICheck.HalfReady = &m_gwHalfReady;
    
    		if ((m_ErrCode = DRV_FAICheck(m_DriverHandle,
    			(LPT_FAICheck)&m_ptFAICheck)) != 0)
    		{
    			DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    
    			CString s;
    			s = m_szErrorMsg;
    			AfxMessageBox(s);
    			return ;
    		}
    
    		if( m_gwHalfReady == 1 )
    		{
    			m_ptFAITransfer.ActiveBuf = 0;   // single buffer
    			m_ptFAITransfer.DataType = m_DataType;
    			m_ptFAITransfer.start    = 0;
    			m_ptFAITransfer.count    = m_Conv/2;
    			m_ptFAITransfer.overrun  = &m_gwOverrun;
    
    			if ((m_ErrCode = DRV_FAITransfer(m_DriverHandle,
    				(LPT_FAITransfer)&m_ptFAITransfer)) != 0)
    			{
    				DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    				CString s;
    				s = m_szErrorMsg;
    				AfxMessageBox(s);
    				return ;
    			}
    			temp = (FLOAT far *)m_ptFAITransfer.DataBuffer;
    			for (int i=0;i<64;i++)
    			{ 					
    				x[i] = (i + 64 * m_CyclicCount * 2) * 1.0 ;
    				y[i] = ((FLOAT far *)temp)[i];
    			}
    			
    		}
    		else if( m_gwHalfReady == 2 )
    		{
    			m_ptFAITransfer.ActiveBuf = 0;   // single buffer
    			m_ptFAITransfer.DataType = m_DataType;
    			m_ptFAITransfer.start    = m_Conv/2;
    			m_ptFAITransfer.count    = m_Conv/2;
    			m_ptFAITransfer.overrun  = &m_gwOverrun;
    
    			if ((m_ErrCode = DRV_FAITransfer(m_DriverHandle,
    				(LPT_FAITransfer)&m_ptFAITransfer)) != 0)
    			{
    				DRV_GetErrorMessage(m_ErrCode,(LPSTR)m_szErrorMsg);
    				CString s;
    				s = m_szErrorMsg;
    				AfxMessageBox(s);
    				return ;
    			}
    			temp = (FLOAT far *)m_ptFAITransfer.DataBuffer;
    
    			for (int i=0;i<64;i++)
    			{
    
    				x[i+64] = (i + 64 * (m_CyclicCount * 2 + 1)) * 1.0 ;
    				y[i+64] = ((FLOAT far *)temp)[i];
    			}
    			
    			m_CyclicCount++;
    
    		}
    
    
    		return;
    	}
    这里涉及到FIFO工作模式,在这个程序里,一次采集128个数据,半个buffer就是64,buffer每半满,系统会产生一个HalfReady,此时读取driver缓存里的数据,不会产生错误。

 

你可能感兴趣的:(USB4711A,中断采集)