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

来源:互联网 发布:程序员三年薪资 编辑:程序博客网 时间:2024/04/29 05:42

研华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文件里添加变量声明
    LRESULTm_ErrCode;  LONGm_DriverHandle;ULONGm_dwDeviceNum;  DEVFEATURESm_DevFeatures;ULONGm_gwActualBufSize;USHORTm_GainCode;USHORTm_gwActiveBuf;// return by FAICheckUSHORTm_gwOverrun;// return by FAICheck, FAITransferUSHORTm_gwStopped;// return by FAICheckULONGm_gulRetrieved;     // return by FAICheckUSHORTm_gwHalfReady;// return by FAICheckPT_DeviceGetFeaturesm_ptDevFeatures;//PT_FAIIntStartm_ptFAIIntStart;     // FAIIntStart tablePT_FAIIntScanStartm_ptFAIIntScanStart; // m_ptFAIIntScanStart tablePT_FAITransferm_ptFAITransfer;     // FAITransfer tablePT_FAICheckm_ptFAICheck;        // FAICheck tablePT_AllocateDMABufferm_ptAllocateDMABuffer;  // buffer tablePT_EnableEventm_ptEnableEvent;     // Enable eventPT_CheckEventm_ptCheckEvent;      // Check eventUSHORTm_CyclicCount;CWinThread*m_pEventThread;HGLOBALm_hUserBuf;HGLOBALm_hBuf;ULONGm_ulInterruptCount;ULONGm_ulOverRunCount;ULONGm_ulBuffCount;//OpenEvent dialog get follow parboolm_bGetParOk;//intm_GainOption;USHORTm_Gain[4];intm_Model;intm_Triggering;intm_Buffer;intm_DataType;intm_Event;intm_PacerRate;intm_Conv;CStringm_InputRange;intm_ScanChannel;intm_FifoSize;BOOLm_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缓存里的数据,不会产生错误。

 

0 0
原创粉丝点击