博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
研华USB4711A采集卡高速中断模式采集总结
阅读量:4153 次
发布时间:2019-05-25

本文共 9675 字,大约阅读时间需要 32 分钟。

研华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缓存里的数据,不会产生错误。

 

转载地址:http://ifwxi.baihongyu.com/

你可能感兴趣的文章
RunTime.getRuntime().exec()
查看>>
Oracle 分组排序函数
查看>>
VMware Workstation 14中文破解版下载(附密钥)(笔记)
查看>>
日志框架学习
查看>>
日志框架学习2
查看>>
SVN-无法查看log,提示Want to go offline,时间显示1970问题,error主要是 url中 有一层的中文进行了2次encode
查看>>
NGINX
查看>>
Qt文件夹选择对话框
查看>>
DeepLearning tutorial(7)深度学习框架Keras的使用-进阶
查看>>
第三方SDK:JPush SDK Eclipse
查看>>
第三方开源库:imageLoader的使用
查看>>
Android studio_迁移Eclipse项目到Android studio
查看>>
转载知乎-前端汇总资源
查看>>
JavaScript substr() 方法
查看>>
JavaScript slice() 方法
查看>>
JavaScript substring() 方法
查看>>
HTML 5 新的表单元素 datalist keygen output
查看>>
(转载)正确理解cookie和session机制原理
查看>>
jQuery ajax - ajax() 方法
查看>>
将有序数组转换为平衡二叉搜索树
查看>>