研华USB4711A采集卡是一款USB接口的采集卡,笔记本上就可以用,不用专门要ISA或者PCI插槽,价格上倒是比较贵,AI最多可以到150KS/s。这里记录高速中断模式采集使用方法。
windows平台:xp sp3
框架:vs2010 MFC 单文档
采集速度:4通道,每通道200HZ
采集模式:使用FIFO
==============================================================
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();
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 ;
// 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;
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; }
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缓存里的数据,不会产生错误。