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

news/2025/1/18 4:42:15/

研华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 FAICheckUSHORT					m_gwOverrun;		// return by FAICheck, FAITransferUSHORT					m_gwStopped;		// return by FAICheckULONG					m_gulRetrieved;     // return by FAICheckUSHORT					m_gwHalfReady;		// return by FAICheckPT_DeviceGetFeatures	m_ptDevFeatures;//	PT_FAIIntStart			m_ptFAIIntStart;     // FAIIntStart tablePT_FAIIntScanStart		m_ptFAIIntScanStart; // m_ptFAIIntScanStart tablePT_FAITransfer			m_ptFAITransfer;     // FAITransfer tablePT_FAICheck				m_ptFAICheck;        // FAICheck tablePT_AllocateDMABuffer	m_ptAllocateDMABuffer;  // buffer tablePT_EnableEvent			m_ptEnableEvent;     // Enable eventPT_CheckEvent			m_ptCheckEvent;      // Check eventUSHORT					m_CyclicCount;CWinThread*				m_pEventThread;HGLOBAL					m_hUserBuf;HGLOBAL					m_hBuf;ULONG					m_ulInterruptCount;ULONG					m_ulOverRunCount;ULONG					m_ulBuffCount;//OpenEvent dialog get follow parbool	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/8m_InputRange	= _T("") ;		//m_FifoSize		= 64 ;			//设定FIFO大小 7411为1024  buffer大小应该是FIFO/2 大小的整数倍(偶数),m_EnableFifo	= TRUE ;		//使用FIFOm_bGetParOk		= true ;

  5. 开启采集
    // Step 1: Open Devicem_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 featuresm_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 driverif((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 dataif((m_hUserBuf=(FLOAT far *)GlobalAlloc(GHND,sizeof(FLOAT) * m_Conv )) == 0){		AfxMessageBox(_T("高速缓存不足!"));DRV_DeviceClose((LONG far *)&m_DriverHandle);return;}// Prepare some informations to runm_ptFAIIntScanStart.buffer     = (USHORT far *)GlobalLock(m_hBuf);/*       */m_ptFAITransfer.DataBuffer = (FLOAT far  *)GlobalLock(m_hUserBuf);// Step 5: Enable event featurem_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 transferm_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;elsem_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 overrunif ((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 driverm_ptFAITransfer.ActiveBuf = 0;   // single bufferm_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 driverDRV_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 messagepView->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 eventif (usEventType & ADS_EVT_INTERRUPT){pView->adInterruptEvent();pView->m_ulInterruptCount++;}// Process buffer change eventif (usEventType & ADS_EVT_BUFCHANGE){pView->m_ulBuffCount++;           pView->adBufChangeEvent();}// Process overrun eventif (usEventType & ADS_EVT_OVERRUN){pView->m_ulOverRunCount++;pView->adOverrunEvent();}// Process terminate eventif (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 bufferm_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 bufferm_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://www.ppmy.cn/news/125566.html

相关文章

图像采集卡

图像采集卡的工作原理、发展历史及在机器视觉系统中的地位 ROC先生&#xff1a;目前常用的采集卡主要分图象采集卡和视频压缩卡&#xff1b;图像采集卡按照信号方式分为模拟卡和数字卡&#xff1b;模拟采集卡的 主要功能就是A/D转换和数据传输。国内开发公司主要是大恒、中自、…

LabVIEW编程LabVIEW开发研华PCI-1710 数据采集卡例程与相关资料

LabVIEW编程LabVIEW开发研华PCI-1710 数据采集卡例程与相关资料 PCI-1710是一款PCI总线的多功能数据采集卡。其先进的电路设计使得它具有更高的质量和更多的功能。这其中包括五种最常用的测量和控制功能:12位A/D转换,D/A转换,数字量输入,数字量输出及计数器/定时其功能。采集卡…

【ATE-同步采样】NI采集卡的RTSI同步技术及LabVIEW的实现方法

测试系统中&#xff0c;当对多路信号波形进行分析时&#xff0c;我们需要这些波形在时间轴上对其&#xff08;同时采样&#xff09;&#xff0c;数据分析起来才有意义。这种使多路信号的波形在时间轴上对齐的技术就叫做同步技术。 举个例子&#xff0c;比如测试系统需要采集电压…

视频采集卡都有哪些基本类型

视频采集卡又称视频捕捉卡&#xff0c;用它可以获取数字化视频信息&#xff0c;并将其存储和播放出来。很多视频采集卡能在捕捉视频信息的同时获得伴音&#xff0c;使音频部分和视频部分在数字化时同步保存、同步播放。 视频采集卡有以下几种基本类型&#xff1a; 软压缩卡和硬…

采集卡

选购采集卡的目的不外乎就是能更方便的更有效的监看&#xff0c;安防领域(视频采集卡)&#xff0c;各种各样的DVR卡琳琅满目&#xff0c;让很多的工程商和消费者特别是刚入行者无从下手&#xff0c;您应该需要关注一下几个大区。 视频采集卡的主要功能和技术 接口&#x…

机器视觉:接口扩展采集卡

机器视觉&#xff1a;接口扩展采集卡 数字相机接口主要包含USB2.0/3.0&#xff0c;IEEE 1394A/B&#xff0c;Cameralink以及GigE&#xff08;千兆网&#xff09;&#xff0c;由于传输带宽&#xff08;1000Mb&#xff09;、传输距离&#xff08;100米&#xff09;、通用性等方面…

计算机英语板卡,数据采集卡

数据采集是指对设备被测的模拟或数字信号,自动采集并送到上位机中进行分析、处理。数据采集卡,即实现数据采集功能的计算机扩展卡,可以通过USB、PXI、PCI、PCI Express、火线(1394)、PCMCIA、ISA、Compact Flash、485、232、以太网、各种无线网络等总线接入计算机。[1] 中文…

写一个bubble_sort实现库函数qsort冒泡排序

int cmp_int(const void* e1, const void* e2) { return *(int*)e1 - *(int*)e2;//e1 e2 调用前需要类型转换 } void swap(char* buf1, char* buf2, int width) { int i 0; for (i 0; i < width; i) { int tmp *buf1; *buf1 *buf2; *buf2 tmp;//交换了数组元素的第…