Introduction to 32-bit High Speed DLL Driver V1.xx for
Windows NT and Windows 95
How to install 32-bit DLL driver
Please follow below procedure to install Advantech 32-bit DLL Driver and setup a supported
device in the driver for your first time.
(1) When you download the 32-bit driver from Advantech WWW server,
www.advantech-usa.com/techhome/tech1.htm. In tech1.htm page, there is a list of driver
for each product. As you get any file from above server, please unzip the file before you install.
DLL3295.100
DLL32NT.100
: Advantech Driver for Windows 95 Ver 1.00
: Advantech Driver for Windows NT Ver 1.00
The driver supports 32-bit Operating System environment, Windows 95/NT, and 100 means
the version number of Advantech 32-bit DLL driver. It is in ZIP file format which needs to be
uncompressed by any available WINZIP utility. Because the default file type for WINZIP is ‘ZIP’, you
should use full filename in the command line. For example,
Pkunzip -d DLL32NT.100
(2) After you unzip the 32-bit DLL driver, please use SETUP.EXE on /DISK1 directory to install the
driver. When it comes to below diagram, you should select correct Operating System for your
current working PC.
1
(3) After you finish the driver installation, you should run Device Installation (DEVINST.EXE)
under Advantech Driver for NT (for Windows NT) / Advantech Driver for 95 folder to setup
supported devices. Please refer to DEVINST.HLP for more information.
New Device Installation Utility for Windows NT and 95
(4) The necessary files for programming:
Below files are located in \Program Files\Advantech\Adsapi\ directory after you install 32-bit
DLL driver for Windows 95/NT.
\DEVINST.EXE
\MANUAL.DOC
\Examples\VC\LIB\ADSAPI32.LIB
\Examples\BC\LIB\ADSAPIBC.LIB
\Examples\BCB\LIB\ADSAPIBC.LIB
\Include \DRIVER.H
\Include \OS.H
\Include \DRIVER.PAS
\Include \DRIVER.BAS
: To install any supported device for Advantech 32-bit
DLL driver.
: User’s Manual for Advantech 32-bit DLL driver.
: Header library of ADSAPI32.DLL for Visual C++.
: Header library of ADSAPI32.DLL for Borland C++.
: Header library of ADSAPI32.DLL for Borland C++
Builder.
: Header file for Visual C++, Borland C++ /Builder.
: Header file for Visual C++, Borland C++ /Builder.
: Header library of ADSAPI32.DLL for Borland Delphi.
: Header library of ADSAPI32.DLL for Visual Basic.
How to install device through Device Installation
Please follow below procedure to setup any Advantech DA&C products.
(1) Launch Device Installation to setup any supported device. You will see below diagram as you
launch it.
(2) Select Device... item from Setup menu, it will shows below I/O Device Installation dialog.
Press Add>> button to show lists of device and press Install button to add a device.
2
(3) Here is an example to setup PCL-818L. When you run into any trouble while setting the device,
please press Help button for advanced help.
(4) The Device Installation Utility will start up the device driver automatically under Windows NT.
But you must make sure that you don’t run any application program which is accessing the
Device Registry (using DRV_DeviceOpen () function to open any supported device) as you
launch this utility. For safety, please close any program using Advantech 32-bit DLL driver
before you launch Device Installation Utility. Now it is ready for coding.
(5) The Device Installation Utility will start up the device driver automatically.
Registry of Advantech 32-bit DLL driver
The following is the registry of Advantech 32-bit DLL driver, please take a look by using
REGEDIT utility to find its path:
Note: If you are not familiar with Windows NT device configuration, you are not adviced to
change registry data. Device installation will configure the default data for each registry. If
you want to change it, it will be better to save the default data at another file.
3
For the detailed information of DLL driver’s setup, you can refer to Windows NT Registry.
DLL Drivers create file associate “ADSxxx” in Registry. To access Registry information, please
execute “Regedit.exe” in Windows directory. After executing “Regedit.exe”, you can access DLL
drivers data through the following path:
Windows 95/NT Registry Keys Layout
HKEY_LOCAL_MACHINESYSTEM CurrentControlSet Services ADSDAQ
For example:
1. ADSDAQ key is used for all devices
Key location for Windows 95/NT:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ ADSDAQ
2. ADS818S key is used for PCL-818 series
Key location for Windows 95/NT:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ADS818S
Select hardware related Key Name in the listing at the left side of “REGEDIT” dialog, please refer to
the following figure:
4
How to compile in Mircosoft Visual C++ V2.0 or above?
(1) Please new a Project which you should set it in using class library.
(2) Import \Program Files\Advantech\Examples\VC\LIB\ADSAPI32.LIB.
(3) Add your filename of source code into this project.
How to compile in Borland C++ Builder, Borlanc C++ V5.0 or above?
(1) Please new a Project which you should set it in using class library, don’t use OWL.
(2) Import \Program Files\Advantech\Examples\BC\LIB\ADAPIBC.LIB for Borland C++ or
\Program Files\Advantech\Examples\BCB\LIB\ADAPIBC.LIB for Borland C++ Builder. The
Header Libraries for BC++/BC++ Builder are the same, but it is different from the .LIB file for
VC++. If you want to call to any DLL by BC++/BC++ Builder, you can apply IMPLIB utility to
create new .LIB files.
Syntax: IMPLIB [options] libname[.lib] dllname[.dll]
Example:
Δ C:\Program Files\Advantech\Adsapi\Examples\BC\LIB \ADSAPIBC.LIB
1) IMPLIBΔ
Δ
ΔC:\WinNT\ADSAPI32.DLL
Δ C:\Program Files\Advantech\Adsapi\Examples\BC\LIB \ADSAPIBC.LIB Δ
2) IMPLIBΔ
Δ
C:\Windows\ADSAPI32.DLL
(3) Add your filename of source code into this project.
(4) You configure the Data Alignment to Quad Word (8-Byte) in the Processor item of 32-bit
Compiler setup of Project Options. Because the default Data Alignment of Visual C++, Visual
Basic and Delphi are in Quad Word (8-Byte), you don’t have to change the configuration in
those programming language environment.
How to compile in Mircosoft Visual Basic V4.0 or above?
(1) Please new a Project which you should set it in using class library.
(2) Add \Include\DRIVER.BAS into this project.
(3) Add your filename of source code into this project.
How to compile in Borland Delphi V2.0 or above?
(1) Please Open a Project which you should set it in using class library.
(2) Add \Include\DRIVER.PAS into this project.
(3) Add your filename of source code into this project.
5
A table of DLL drivers filename and its supported devices.
No.
Supported Hardware
File Name
1
PCL-818 series
ADS818.DLL
2
PCL-711S
ADS711.DLL
3
PCL-812PG
ADS812.DLL
4
PCL-813B
ADS813.DLL
5
PCL-816
ADS816.DLL
6
PCL-1800
ADS1800.DLL
7
PCL-726/727/728
ADS726.DLL
8
PCL-720/722/724/725
ADSDIO.DLL
9
ADSDIO.DLL
12
PCL-730/731/733/734
/735
ADAM-4000 series
ADAM-5000/485
series
PCL-833
13
MIC-2000 series
ADSMIC.DLL
14
ADSPCM.DLL
16
17
PCM-3680/3718/3724/
3730
Virtual DEMO I/O
board
RS-232 COM Port
PCL-836
18
PCL-841
ADS841.DLL
19
ADAM-5000/DeviceNet
ADSDN5K.DLL
20
Direct I/O for
unlisted I/O Board
ADSIO.DLL
10
11
15
Device Driver
ADS818S.SYS
ADS818S.VxD
ADS711S.SYS
ADS711S.VxD
ADS812S.SYS
ADS812S.VxD
ADSIO.SYS
ADSIO.VxD
ADS816S.SYS
ADS816S.VxD
ADS1800S.SYS
ADS1800S.VxD
ADSIO.SYS
ADSIO.VxD
ADSIO.SYS
ADSIO.VxD
ADSIO.SYS
ADSIO.VxD
ADS4000.DLL
ADS5000.DLL
ADS833.DLL
ADS711S
ADS812S
ADSIO
ADS816S
ADS1800S
ADSIO
ADSIO
ADSIO
ADSDAQ
ADSDAQ
ADSIO.SYS
ADSIO.VxD
ADSMICS.SYS
ADSMICS.VxD
ADSPCMS.SYS
ADSPCMS.VxD
ADSDEMO.DLL
ADSCOMM.DLL
ADS836.DLL
Key Names in
Registry
ADS818S
ADSIO
ADSMICS
ADSPCMS
ADSDAQ
ADSIO.SYS
ADSIO.VxD
ADS841S.SYS
ADS841S.VxD
ADS841S.SYS
ADS841S.VxD
ADSIO.SYS
ADSIO.VxD
ADSDAQ
ADSIO
ADS841S
ADS841S
ADSIO
The files in .DLL type contains Advantech API functions for application program to call to. You
can find ADSAPI32.DLL in \Windows directory and the other .DLL files \Windows\System
directories for Windows 95, ADSAPI32.DLL in \WINNT directory and the other .DLL files
in \WINNT\SYSTEM32 directories for Windows NT.
The files in .SYS type are Device Driver for Windows NT. You can find the files in
\WINNT\SYSTEM32\Drivers.
The files in .VxD type are Device Driver for Windows 95. You can find the files in
\Windows\SYSTEM.
6
Report for Advantech 32-bit DLL Driver for Windows 95/NT Version 1.0
1. Functions of Polling mode method test (PC-Lab cards)
Functions
Analog Input
Analog Output
Digital Input
Product Name
DEMO Board
Sine Wave (0)
(Simulation)
Saw Tooth (1)
MIC-2718
MIC-2728
MIC-2730/2732
MIC-2750/2752
PCIA-71A/B
No Solution(NT)
No Solution(NT)
PCIA-71C
No Solution(NT)
No Solution(NT)
PCL-1800
(TTL)
PCL-711/711B
(TTL)
PCL-718/818
(TTL)
PCL-720
(TTL)
PCL-721
?
?
?
PCL-722
(8255 Mode 0)
PCL-723
?
?
?
PCL-724
(8255 Mode 0)
PCL-725
(Photo Couple)
PCL-726
PCL-727
PCL-728
PCL-730
(Isolation)
(TTL)
PCL-731
(8255 Mode 0)
PCL-733
(Isolation)
PCL-734
PCL-735
PCL-812/812P
(TTL)
G
Counter /
Qcounter
Digital Output
Frequency
Pulse Output
(Simulation)
(Isolation)
No Solution(NT)
No Solution(NT)
(TTL)
(TTL)
(TTL)
(TTL)
?
(8255 Mode 0)
?
(8255 Mode 0)
(Relay Out)
?
?
?
?
?
?
(Isolation )
(TTL)
(8255 Mode 0)
(Isolation)
(Relay Out)
(TTL)
7
Functions
Analog Input
Product Name
PCL-813B/813
PCL-816
PCL-818H
PCL-818HD
PCL-818HG
PCL-818L
PCL-830
PCL-833
PCL-836
PCM-3718
PCM-3724
PCM-3730
Analog Output
Digital Input
Digital Output
(TTL on board)
(8255 Mode)
(TTL)
(TTL)
(TTL)
(TTL)
(TTL on board)
(8255 Mode)
(TTL)
(TTL)
(TTL)
(TTL)
Counter /
Qcounter
Frequency
Pulse Output
(Isolation,
Differential) #1
(TTL)
(8255 Mode)
(Isolation)
(TTL)
(TTL)
(8255 Mode)
(Isolation )
(TTL)
How to test the functions of Polling mode method:
Analog Input (Single or Multiple channels, +/-10V, +/-5V, +/-2.5V and 0V)
Analog Output (+/-10V, +/-5V, +/-2.5V and 0V)
Digital Input (Isolation / TTL mode / 8255 mode)
Digital Output (Isolation / TTL mode / 8255 mode)
Counter / QCounter
Frequency
Pulse Output
Perform multiple functions on one specific card at the same time
Test AI/AO, DI/DO and Counter/Frequency/Pulse Out functions on each card of different I/O address (Hex 200 or Hex 300)
Test AI/AO, DI/DO and Counter/Frequency/Pulse Out functions on two card of same model with different I/O address (Hex 200 and Hex 300)
Test AI/AO, DI/DO and Counter/Frequency/Pulse Out functions on two cards of different model with different I/O address (Hex 200 and Hex
300)
1 Differential Mode (same with RS-485)
If VCDI0+ - VCDI0- > 200mV Active High Status
If VCDI0+ - VCDI0- < -200mV Active Low Status
Single Ended
Minimal input voltage for Active High Signal
2.5 Volt
Maximize input voltage for Active Low Signal > 200mV 2.0 Volt
8
2. Functions of Polling mode method test (ADAM /RS-485 modules)
Functions
Analog Input
Analog Output
Digital Input
Product Name
ADAM-4011
ADAM-4012
ADAM-4013
ADAM-4014D
ADAM-4016
ADAM-4017
(Strain Gauge)
Digital Output
Counter
Temp/RTD
(T/C)
Alarm
(T/C and RTD)
ADAM-4018(M)
(T/C)
ADAM-4021
ADAM-4050
ADAM-4052
ADAM-4053
ADAM-4060
ADAM-4080(D)
ADAM-5017
ADAM-5018
(T/C)
ADAM-5024
ADAM-5050
ADAM-5051
ADAM-5052
ADAM-5056
ADAM-5060
How to test the functions of Polling mode method:
Analog Input
Analog Output
Digital Input (Isolation / Relay Output)
Digital Output (Isolation )
Counter / Frequency
Thermocouple (Temperature)
Alarm
Perform multiple functions on one specific ADAM module at the same time
Test AI/AO, DI/DO, Counter, Temp/RTD and Alarm functions on different ADAM modules with different I/O address (Hex 01, Hex 02)
Test AI/AO, DI/DO, Counter, Temp/RTD and Alarm functions on different ADAM modules with different I/O address (Hex 01, Hex 02)
Test AI/AO, DI/DO, Counter, Temp/RTD and Alarm functions on different ADAM modules with different I/O address (Hex 01, Hex 02)
9
Test ADAM module in different BAUD rate, 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600 or 115200. (the 57600 and 115200 BAUD
rate can be used for ADAM-5000 serial module only)
10
3. Functions of Interrupt/DMA mode method test
Functions
INT/AI
INT/AI
DMA/AI
DMA/MAI
INT with
INT/AO
Product Name
FIFO/AI
PCL-711
PCL-812PG
PCL-718/818
PCL-816
PCL-818H
PCL-818HD
PCL-818HG
PCL-818L
How to test the functions of Interrupt/DMA mode method:
INT/AI Analog Input (+/-10V, +/-5V, +/-2.5V and 0V)
INT/AI Analog Output (+/-10V, +/-5V, +/-2.5V and 0V)
DMA/AI Digital Input (+/-10V, +/-5V, +/-2.5V and 0V)
DMA/MAI Digital Output (+/-10V, +/-5V, +/-2.5V and 0V)
Test INT/AI or INT/MAI Analog Input on each card of different I/O address (Hex 200 or Hex 300).
Test DMA/AI or DMA/MAI Analog Input on each card of different I/O address (Hex 200 or Hex 300).
Test INT/AI or INT/MAI Analog Input function by launch one identical program twice on two identical devices at the same time (test the INT
detection while one INT is busy, one cannot access the INT once more)
Test INT/AI or INT/MAI Analog Input function by launch two programs on two identical or different devices of different IRQ at the same time
(test the INT detection while one INT is busy, one cannot access the INT once more)
Test DMA/AI or DMA/MAI Analog Input function by launch one identical program twice on two identical devices at the same time (test the INT
detection while one INT is busy, one cannot access the INT once more)
Test DMA/AI or DMA/MAI Analog Input function by launch two programs on two identical or different devices of different IRQ and DMA
channel on two identical devices at the same time (test if use can use two DMA at the same time)
11
4. Functions of Interrupt/DMA mode method test
Functions
INT/AI
INT/AI
DMA/AI
DMA/MAI
Conditional/
Dual DMA/
INT/AO
DMA/AO
Product Name
AI
AI
PCL-1800
How to test the functions of Interrupt/DMA mode method:
INT/AI Analog Input (+/-10V, +/-5V, +/-2.5V and 0V)
INT/AI Analog Output (+/-10V, +/-5V, +/-2.5V and 0V)
DMA/AI Digital Input (+/-10V, +/-5V, +/-2.5V and 0V)
DMA/MAI Digital Output (+/-10V, +/-5V, +/-2.5V and 0V)
Test INT/AI or INT/MAI Analog Input on each card of different I/O address (Hex 200 or Hex 300).
Test DMA/AI or DMA/MAI Analog Input on each card of different I/O address (Hex 200 or Hex 300).
Test INT/AI or INT/MAI Analog Input function by launch one identical program twice on two identical devices at the same time (test the INT
detection while one INT is busy, one cannot access the INT once more)
Test INT/AI or INT/MAI Analog Input function by launch two programs on two identical or different devices of different IRQ at the same time
(test the INT detection while one INT is busy, one cannot access the INT once more)
Test DMA/AI or DMA/MAI Analog Input function by launch one identical program twice on two identical devices at the same time (test the INT
detection while one INT is busy, one cannot access the INT once more)
Test DMA/AI or DMA/MAI Analog Input function by launch two programs on two identical or different devices of different IRQ and DMA
channel on two identical devices at the same time (check if user can use two DMA at the same time)
Watchdog Timer test
12
5. Functions of INT/DI test
Functions
INT/DI
Product Name
PCL-722
PCL-724
PCL-731
PCL-733
PCL-833
PCL-836
Unlisted Board
I/O range:
0000~FFFF
How to test the functions of Interrupt mode method:
Digital with interrupt
Test Digital with interrupt on each card of different I/O address (Hex 200 or Hex 300).
Test Digital with interrupt by launch one identical program twice on two identical devices at the same time (test the INT detection while one
INT is busy, one cannot access the INT once more)
13
6. Functions of CAN-Open and Device-Net protocol test for ADAM/CAN module through MIC-2630, PCL-841 or PCM-3680 CAN interface card
Functions
Polling
Analog Input
Analog
Digital Input
Digital
Event AI
Event DI
Multiple
Product Name
Event
Temp/RTD
Output
Output
Event
ADAM-5050
ADAM-5052
How to test the functions of Interrupt/DMA mode method:
14
7. MAX speed for INT/DMA functions on Advantech product
Functions
INT/AI
DMA/AI
INT with
INT/AO
DMA/AO
INT/DI
Product Name
FIFO/AI
MIC-2718
40KHz
100KHz
100KHz
PCL-711
25KHz
PCL-812PG
30KHz
30KHz
PCL-718/818
40KHz
100KHz
PCL-816
40KHz
100KHz
40KHz
100KHz
PCL-818H
40KHz
100KHz
PCL-818HD
40KHz
100KHz
100KHz
PCL-818HG
40KHz
100KHz
100KHz
PCL-818L
40KHz
40KHz
PCL-1800
40KHz
200KHz
330KHz
40KHz
200KHz
PCL-722
35KHz
PCL-724
35KHz
PCL-731
35KHz
PCL-733
35KHz #2
PCL-833
35KHz
PCL-836
35KHz
PCM-3718
40KHz
40KHz
PCM-3724
35KHz
PCM-3730
35KHz
Unlisted Board
35KHz
The hardware for above test
CPU
Pentium MMX 200
RAM
64 Mbytes
Mother Board
Advantech MIC-2350 (A) / ASUS TX-97 (B)
Test Utility
(1) INT/AI, DMA/AI and INT with FIFO/AI functions are tested by MDIAPP.EXE program
(2) INT/AO and DMA/AO functions are tested by \Examples\VC\AO.INT\DAINT and
\Examples\VC\AO.DMA\DADMA program. This test should apply a Oscilloscope to check the Analog output.
(3) INT/DI function is tested by \Examples\VC\FDIGIN\Fdigin.EXE program
How can we check the Analog Input with Interrupt/DMA transfer?
2 To check the Digital Input with interrupt of PCL-733 by using two IRQ setup, you should set it into two device number, for example
001 : PCL-733 I/O=300H IRQ = 5
001 : PCL-733 I/O=300H IRQ = 7
When we run two Fdigin.EXE, the processing input interrupt speed can be up to 18.5KHz for each Fdigin.EXE.
15
We try to increase the frequency of TTL signal from Function Generator step by step to make the CPU usage in 50%, then record the frequency
of TTL signal.
For those card with Isolation features, you can connect the TTL signal to IRQ jumper directly.
To get the MAX Analog Input Sampling rate, you should set GAIN = 1.
You should set the CLK = 10MHz when check PCL-1800 at 200KHz sampling rate or above.
How can we check the Analog Output with Interrupt/DMA transfer?
Connect the Analog Output signal to one Oscilloscope to check the waveform and amplitude of signal directly, there are SINE, TRIANGLE and
SQUARE waveform in the example program.
How can we check the Digital Input with Interrupt?
We try to increase the frequency of TTL signal from Function Generator step by step to make the CPU usage in 50%, then record the frequency
of TTL signal. Please also refer to the Performance Monitor diagram on next page.
For those cards with Isolation feature, you can connect the TTL signal to IRQ jumper directly or the input signal should be enough (5V ~ 40V) to
produce an Interrupt.
16
You can find below utility from Start Administrative Tools (Common) Performance Monitor
17
The functions must be called in order, as shown in the following flow charts.
Function Flow Chart
All device-specific drivers flow chart
Analog input flow chart
Analog output flow chart
Digital I/O flow chart
Event counter flow chart
Frequency measurement flow chart
Pulse output flow chart
Quadratic counter flow chart
Alarm operations flow chart
Analog input for single channel data acquisition with interrupt
transfer
Analog input for single channel data acquisition with interrupt
transfer and event function
Analog input for single channel data acquisition with DMA transfer
Analog input for single channel data acquisition with DMA transfer
and event function
Analog input for multiple channel data acquisition with interrupt
transfer
Analog input for multiple channel data acquisition with interrupt
transfer and event function
Analog input for multiple channel data acquisition with DMA
transfer
Analog input for multiple channel data acquisition with DMA
transfer and event function
Analog input for multiple channel watchdog with interrupt transfer
Analog input for multiple channel watchdog with interrupt transfer
and event function
Analog input for multiple channel watchdog with DMA transfer
Analog input for multiple channel watchdog with DMA transfer
and event function
Analog output for single channel with DMA transfer
Analog output for single channel with DMA transfer and event
function
Analog output for single channel with interrupt transfer
Analog output for single channel with interrupt transfer and event
function
18
Fig 2-3
Fig 2-4
Fig 2-5
Fig 2-6
Fig 2-7
Fig 2-8
Fig 2-9
Fig 2-10
Fig 2-11
Fig 2-12
P.19
P.20~21
P.22
P.23~24
P.19
P.20~21
P.22
P.23~24
P.19
P.20~21
Fig 2-12-A P.22
Fig 2-13 P.23~24
Fig 2-13-A P.19
Fig 2-14
P.20~21
Fig 2-14-A P.22
Fig 2-15
P.23~24
Fig 2-15-A P.19
Fig 2-16 P.20~21
Fig 2-16-A P.22
Fig 2-17 P.23~24
Fig 2-17-A P.19
Fig 2-18 P.20~21
Fig 2-18-A P.22
Fig 2-19 P.23~24
Fig 2-19-A P.23~24
The structure of the Demo Program
All device-specific drivers flow chart:
put it in the
memory
DRV_DeviceConfig
DRV_DeviceOpen
Configuration
Data
(DeviceHandle)
retrieve the configuration data
Configuration Data
(Registry/Config. File)
Function Group
ref erred by
other functions
DRV_DeviceClose
Fig 2-3. Function Flow Overview
DRV_DeviceGetList() Get the configuration information of device, not including the attached devices
on COM port or CAN, from Windows System Registry, and the Device Number (The number in the first column
which you can see through Device Installation utility) can be applied for DRV_DeviceOpen().This function,
DRV_DeviceOpen(), retrieves parameters pertaining to the device’s operation from the Registry or configuration
file, and allocate memory to store it for quick reference. This function returns a Driver Handle (second parameter)
which pointers to the configuration for calling any other functions before it calls the DRV_DeviceClose() function.
After the I/O operations, user has to call DRV_DeviceClose to release the memory allocated by
DRV_DeviceOpen.
In the Function Group, you can call any supported function which is necessary for your application, please
also refer to the following Flow Diagram for each feature for your applied board. If you cannot make sure that if the
calling function is supported for the specific card or not, you can refer to MANUAL.DOC for more information.
When your program call to those functions in Function Group, it will call to the function in specific .DLL file.
For example, when you open a PCL-818HG device
The calling flow in your program
DRV_DeviceOpen DRV_AIConfig DRV_AIVoltageIn DRV_DeviceClose
The calling flow inside the DLL driver
DRV_DeviceOpen() (ADSAPI32.DLL) DeviceOpen() (ADS818.DLL) DRV_AIConfig() (ADSAPI32.DLL)
AIConfig() (ADS818.DLL) ADS818.SYS Access the register on Hardware DRV_AIVoltageIn()
(ADSAPI32.DLL) AIVoltageIn() (ADS818.DLL) ADS818.SYS Access the register on Hardware
DRV_DeviceClose() (ADSAPI32.DLL) DeviceClose() (ADS818.DLL)
19
Analog Input Flow Chart:
multiple channel /
external trigger
yes
single channel /
sof tw are trigger
DRV_MAIConfig
DRV_AIConfig
DRV_MAIVoltageIn
DRV_AIVoltageIn
one reading
External
Trigger
Complete?
no
no
exit f ailure
yes
exit success
another reading
Repeat?
no / exit
Fig 2-4. Function Flow Overview
For Single Channel
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *)&DriverHandle);
// Configures the gain for the specific analog input channel
// Gain Code or Input Range, Please refer to Hardware User’s Manual for more information
ptAIConfig.DasGain = usGainCde;
ptAIConfig.DasChan = gwChannel;
// 2nd Step: Call to DRV_AIConfig() function to configure the Analog input channel and its Gain Code
if ((ErrCde = DRV_AIConfig(DriverHandle, (LPT_AIConfig) &ptAIConfig)) != 0)
{
// If any error happen, please call below function to get the error message for the Error Code, ErrCde.
DRV_GetErrorMessage(ErrCde, (LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Driver Message",MB_OK);
// You should call the DRV_DeviceClose() function whenever it exits the appliaction
DRV_DeviceClose((LONG far *) &DriverHandle);
return 0;
}
// Analog Iiput channel
ptAIVoltageIn.chan = gwChannel;
// Gain Code or Input Range, Please refer to Hardware User’s Manual for more information
ptAIVoltageIn.gain = usGainCde;
// 0 for internal trigger, 1 for external trigger
ptAIVoltageIn.TrigMode = 0;
20
// ptAIVoltageIn.voltage keeps the address of fVoltage where the driver store the analog input value.
// In Delphi, you can use @ operator.
// In Visual Basic, please use DRV_GetAddress(parameter) function to return the parameter’s
// address.
ptAIVoltageIn.voltage = (FLOAT far *) &fVoltage;
// 3rd Step: Call to DRV_AIVoltageIn () function to get analog input value
if ((ErrCde = DRV_AIVoltageIn(DriverHandle, (LPT_AIVoltageIn) &ptAIVoltageIn)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
KillTimer(hWnd, 1);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Driver Message",MB_OK);
// You should call the DRV_DeviceClose() function whenever it exits the appliaction
DRV_DeviceClose((LONG far *)&DriverHandle);
return 0;
}
// 4th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
For Multiple Channels
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *)&DriverHandle);
// Gain Code or Input Range, Please refer to Hardware User’s Manual for more information
ptMAIConfig.NumChan = usStopChan - usStartChan + 1;
ptMAIConfig.StartChan = usStartChan;
// Configures the gain list for the each analog input channel
for (i=0 ; i< ptMAIConfig.NumChan ; i++)
usGainCode[i+usStartChan] = DevFeatures.glGainList[usGainIndex[i+usStartChan]].usGainCde;
ptMAIConfig.GainArray = (USHORT far *) &usGainCode[usStartChan];
// 2nd Step: Call to DRV_MAIConfig() function to configure the multiple Analog input channels and its
// Gain Code
if ((ErrCde = DRV_MAIConfig(DriverHandle, (LPT_MAIConfig) &ptMAIConfig)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Driver Message",MB_OK);
DRV_DeviceClose((LONG far *)&DriverHandle);
return 0;
}
ptMAIVoltageIn.NumChan = usStopChan - usStartChan + 1;
ptMAIVoltageIn.StartChan = usStartChan;
for (i=0 ; i< ptMAIVoltageIn.NumChan ; i++)
usGainCode[i+usStartChan] = DevFeatures.glGainList[usGainIndex[i+usStartChan]].usGainCde;
ptMAIVoltageIn.GainArray = (USHORT far *) &usGainCode[usStartChan];
ptMAIVoltageIn.TrigMode = 0;
// internal trigger
ptMAIVoltageIn.VoltageArray = (FLOAT far *)&fVoltage[usStartChan];
// 3rd Step: Call to DRV_MAIVoltageIn () function to get analog input value
21
if ((ErrCde = DRV_MAIVoltageIn(DriverHandle, (LPT_MAIVoltageIn)&ptMAIVoltageIn)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Driver Message",MB_OK);
KillTimer(hWnd, 1);
DRV_DeviceClose((LONG far *)&DriverHandle);
return 0;
}
// 4th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
22
Analog Output Flow Chart:
DRV_AOConfig
DRV_AOConfig
DRV_AOVoltageOut
DRV_AOScale
DRV_AOBinaryOut
Fig 2-5. Function Flow Overview
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *)&DriverHandle);
ptAOConfig.chan = gwChannel;
ptAOConfig.MaxValue = 5.0;
// Identical to the jumper setting on board
ptAOConfig.MinValue = 0.0;
// 2nd Step: Call to DRV_AOConfig() function to configure the analog output channel
// Please don’t call to DRV_AOConfig() for ADAM modules, or it will return Error Message
if ((ErrCde = DRV_AOConfig(DeviceHandle, ptAOConfig)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR)szErrMsg);
MessageBox(hWnd, (LPCSTR)szErrMsg, "Driver Message",MB_OK);
DRV_DeviceClose((LONG far *) &DriverHandle);
return 0;
}
ptAOVoltageOut.chan = gwChannel;
ptAOVoltageOut.OutputValue = fData;
// The output voltage value
// 3rd Step: Call to DRV_ AOVoltageOut () function to perform analog output
if((ErrCde = DRV_AOVoltageOut(DriverHandle, (LPT_AOVoltageOut) &ptAOVoltageOut)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
KillTimer(hWnd, 1);
MessageBox(hWnd, (LPCSTR)szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
23
// 4th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
24
Digital Input /Output Flow Chart:
Digital Input
Digital Ouput
DRV_DioSetPortM ode
DRV_DioSetPortM ode
DRV_DioRea dPortByte
DRV_DioWritePortByte
(DRV_Di oGetCurrentDOByte)
Fig 2-6. Function Flow Overview
For Digital Input
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
// For those digital I/O cards in 8255 Mode 0, such as PCL-722, PCL-724 and so on, to set up I/O
// direction dynamically. If you don’t execute the DRV_DioSetPortMode function for above cards, it
// works as the setup in Device Installation utility.
// Bit 0 ~ Bit 7 Port 0
// Bit 8 ~ Bit 15 Port 1
// Bit 16 ~ Bit 31 Port 2
// ….
lpDioPortMode.port := gwPort;
lpDioPortMode.dir := INPORT; // Set the specific port as Input Port
// 2nd Step: Call to DRV_DioSetPortMode() function to configure the mode of Digital I/O channel
// dynamically. This function affect those digital I/O cards in 8255 Mode 0 only.
// If you don’t call to DRV_DioSetPortMode() function, the mode of Digital I/O channel will be identical to
// the setup in Device Installation utility.
if ((ErrCde = DRV_DioSetPortMode(DeviceHandle, lpDioPortMode)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR)szErrMsg);
KillTimer(hWnd, 1);
MessageBox(hWnd, (LPCSTR)szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
ptDioReadPortByte.port = gwPort;
ptDioReadPortByte.value = (USHORT far *) &gwValue;
// 3rd Step: Read the digital input status
if ((ErrCde = DRV_DioReadPortByte(DriverHandle,
(LPT_DioReadPortByte) &ptDioReadPortByte)) != 0)
{
25
DRV_GetErrorMessage(ErrCde, (LPSTR) szErrMsg);
KillTimer(hWnd, 1);
MessageBox(hWnd, (LPCSTR) szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
// 4th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
For Digital Output
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
// For those digital I/O cards in 8255 Mode 0, such as PCL-722, PCL-724 and so on, to set up I/O
// direction dynamically. If you don’t execute the DRV_DioSetPortMode function for above cards, it
// works as the setup in Device Installation utility.
lpDioPortMode.port := gwPort;
lpDioPortMode.dir := OUTPORT;
// Set the specific port as Output Port
// 2nd Step: Call to DRV_DioSetPortMode() function to configure the mode of Digital I/O channel
// dynamically. This function affect those digital I/O cards in 8255 Mode 0 only.
// If you don’t call to DRV_DioSetPortMode() function, the mode of Digital I/O channel will be identical to
// the setup in Device Installation utility.
if ((ErrCde = DRV_DioSetPortMode(DeviceHandle, lpDioPortMode)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR)szErrMsg);
KillTimer(hWnd, 1);
MessageBox(hWnd, (LPCSTR)szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
ptDioWritePortByte.port = gwPort;
// Only those bits in 1 can be set ON/OFF. For example, you have mask equal 0x0F, then you can turn
// on Bit 0 ~ Bit 3
ptDioWritePortByte.mask = gwMask;
ptDioWritePortByte.state = gwData;
// 3rd Step: Write the digital output status
if((ErrCde = DRV_DioWritePortByte(DriverHandle,
(LPT_DioWritePortByte)&ptDioWritePortByte)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hDlg,(LPCSTR)szErrMsg,"Driver Message",MB_OK);
return 0;
}
// 4th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
26
Event Counter Flow Chart:
General counter
DRV_CounterEventStart
Another reading
DRV_CounterEventRead
DRV_CounterReset
Fig 2-7. Function Flow Overview
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptCounterEventStart.counter = gwChannel;
// The GateMode parameter is for PCL-830 only.
ptCounterEventStart.GateMode = gwGateMode;
// 2nd Step: Call to DRV_CounterEventStart() to configure the specific counter channel of 8253/8254 on
// board for reading input pulse.
if((ErrCde = DRV_CounterEventStart(DriverHandle,
(LPT_CounterEventStart) &ptCounterEventStart)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
ptCounterEventRead.counter = gwChannel;
// the overflow state of the counter, 1 means overflow, otherwise 0
ptCounterEventRead.overflow = (USHORT far *) &gwOverflow;
ptCounterEventRead.count = (ULONG far *) &gdwReading;
// 3rd Step: Call to function DRV_CounterEventRead() to read the input pulse number.
if ((ErrCde = DRV_CounterEventRead(DriverHandle,
(LPT_CounterEventRead) &ptCounterEventRead)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
27
KillTimer(hWnd, 1);
MessageBox(hWnd,(LPCSTR) szErrMsg, "Driver Message", MB_OK);
DRV_DeviceClose((LONG far *) &DriverHandle);
return TRUE;
}
// 4th Step: Call to DRV_CounterReset() function to turns off the specified counter operation. This
// function supports boards with the timer/counter chip (i.e. Intel 8254 or AMD Am9513A) and PCL-833.
if( (ErrCde = DRV_CounterReset(DriverHandle,
(LPARAM) gwChannel)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR) szErrMsg);
MessageBox(hWnd,(LPCSTR) szErrMsg, "Driver Message", MB_OK);
}
// 5th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
28
Frequency Measurement Flow Chart:
General Counter
DRV_CounterFreqStart
Another reading
DRV_CounterFreqRead
DRV_CounterReset
Fig 2-8. Function Flow Overview
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptCounterFreqStart.counter = gwChannel;
// gating period in seconds unit
ptCounterFreqStart.GatePeriod = gwGatePeriod;
// gating mode to be used for AMD Am9513A only
ptCounterFreqStart.GateMode = gwGateMode;
// 2nd Step: Call to DRV_CounterFreqStart() function to configure the specific counter channel of
// 8253/8254 on board for measuring the frequency of input signal.
if ((ErrCde = DRV_CounterFreqStart(DriverHandle,
(LPT_CounterFreqStart)&ptCounterFreqStart)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR) szErrMsg);
MessageBox(hWnd,(LPCSTR) szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
ptCounterFreqRead.counter = gwChannel;
ptCounterFreqRead.freq = (FLOAT far *)&gfFreq;
// 3rd Step: Call to DRV_CounterFreqRead() function to read the frequency of input signal
if ((ErrCde = DRV_CounterFreqRead(DriverHandle,
(LPT_CounterFreqRead)&ptCounterFreqRead)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
29
MessageBox(hWnd,(LPCSTR)szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
// 4th Step: Call to DRV_CounterReset() function to turns off the specified counter operation. This
// function supports boards with the timer/counter chip (i.e. Intel 8254 or AMD Am9513A) and PCL-833.
if( (ErrCde = DRV_CounterReset(DriverHandle,
(LPARAM) gwChannel)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR) szErrMsg);
MessageBox(hWnd,(LPCSTR) szErrMsg, "Driver Message", MB_OK);
}
// 5th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
30
Pulse Output Flow Chart:
General Counter
DRV_CounterPulseStart
DRV_CounterReset
Fig 2-9. Function Flow Overview
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptCounterPulseStart.counter = gwChannel;
// total period in seconds
ptCounterPulseStart.period = gfGatePeriod;
// the first 1/2 cycle length in seconds
ptCounterPulseStart.UpCycle = gfUpCycle;
ptCounterPulseStart.GateMode = gwGateMode;
// 2nd Step: Call to DRV_CounterPulseStart() function to configure the specific counter channel of
// 8253/8254 on board and perform pulse output.
if((ErrCde = DRV_CounterPulseStart(DriverHandle,
(LPT_CounterPulseStart)&ptCounterPulseStart)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
// 3rd Step: Call to DRV_CounterReset() function to turns off the specified counter operation. This
// function supports boards with the timer/counter chip (i.e. Intel 8254 or AMD Am9513A) and PCL-833.
if( (ErrCde = DRV_CounterReset(DriverHandle, (LPARAM) gwChannel)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR) szErrMsg);
MessageBox(hWnd, (LPCSTR) szErrMsg, "Driver Message", MB_OK);
}
// 4th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
31
Quadratic Counter Flow Chart:
Quadratic counter
DRV_QCounterConfigSys
DRV_QCounterConfig
DRV_QCounterStart
Another reading
DRV_QCounterRead
DRV_CounterReset
Fig 2-10. Function Flow Overview
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptCounterPulseStart.counter = gwChannel;
// total period in seconds
ptCounterPulseStart.period = gfGatePeriod;
// the first 1/2 cycle length in seconds
ptCounterPulseStart.UpCycle = gfUpCycle;
ptCounterPulseStart.GateMode = gwGateMode;
// 2nd Step: Call to DRV_CounterPulseStart() function to configure the specific counter channel of
// 8253/8254 on board and perform pulse output.
if((ErrCde = DRV_CounterPulseStart(DriverHandle,
(LPT_CounterPulseStart)&ptCounterPulseStart)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
32
MessageBox(hWnd,(LPCSTR)szErrMsg, "Driver Message", MB_OK);
return TRUE;
}
// 3rd Step: Call to DRV_CounterReset() function to turns off the specified counter operation. This
// function supports boards with the timer/counter chip (i.e. Intel 8254 or AMD Am9513A) and PCL-833.
if( (ErrCde = DRV_CounterReset(DriverHandle, (LPARAM) gwChannel)) != 0)
{
DRV_GetErrorMessage(ErrCde, (LPSTR) szErrMsg);
MessageBox(hWnd, (LPCSTR) szErrMsg, "Driver Message", MB_OK);
}
// 4th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
33
Alarm Operations Flow Chart:
DRV_AlarmConfig
DRV_AlarmEnable
Another check
DRV_AlarmCheck
DRV_AlarmReset
Fig 2-11. Function Flow Overview
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
// 2nd Step: Configures the alarm limits
ptAlarmConfig.chan = gwChannel;
ptAlarmConfig.LoLimit = gfLoLimit;
ptAlarmConfig.HiLimit = gfHiLimit;
// 2nd Step: Configures the alarm limits
ErrCde = DRV_AlarmConfig(DriverHandle, (LPT_AlarmConfig) &ptAlarmConfig);
// enable alarm
ptAlarmEnable.chan = gwChannel;
ptAlarmEnable.LatchMode = gwLatchMode;
ptAlarmEnable.enabled = 1;
// 3rd Step: Enable alarm, this function will take some seconds (about 7 seconds) to re-program the
// High/Low Alarm setting of ADAM module.
ErrCde = DRV_AlarmEnable(DriverHandle, (LPT_AlarmEnable) &ptAlarmEnable);
// check alarm status
ptAlarmCheck.chan = gwChannel;
ptAlarmCheck.LoState = (USHORT far *)&gwLoState;
34
ptAlarmCheck.HiState = (USHORT far *)&gwHiState;
// 4th Step: Check the Alarm status
ErrCde = DRV_AlarmCheck(DriverHandle, (LPT_AlarmCheck) &ptAlarmCheck);
// 5th Step: Resets the alarm monitoring of the specified channel, send @AACA command to
// ADAM-4000 module, chan channel of ADAM module
ErrCde = DRV_AlarmReset(DriverHandle, chan);
// 6th Step : When you want to exit the I/O, please call to DRV_DeviceClose() function
DRV_DeviceClose((LONG far *) &DriverHandle);
35
Single Analog Input Channel Acquisition with Interrupt Transfer:
Single channel
DRV_FAIIntStart
DRV_FAICheck
No
Buffer Full
(complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
Fig 2-12. The Call Flow for Single-channel Data Acquisition with interrupt transfer
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptFAIIntStart.TrigSrc = gwExtTrig;
ptFAIIntStart.SampleRate = gdwPacerRate;
ptFAIIntStart.chan = gwStartChl;
ptFAIIntStart.gain = DevFeatures.glGainList[gwGainCode].usGainCde;
ptFAIIntStart.count = gulConvNum;
ptFAIIntStart.cyclic = gwCyclicMode;
if (gwFifoEnable)
ptFAIIntStart.IntrCount = FIFO_SIZE;
else
ptFAIIntStart.IntrCount = 1;
// FIFO no enable
// 2nd Step: Start Interrupt transfer
36
ErrCde = DRV_FAIIntStart(DriverHandle, (LPT_FAIIntStart)&ptFAIIntStart);
ptFAICheck.ActiveBuf = &gwActiveBuf;
ptFAICheck.stopped = &gwStopped;
ptFAICheck.retrieved = &gulRetrieved;
ptFAICheck.overrun = &gwOverrun;
// FAICheck.HalfReady = 0 not ready, 1 first half ready, 2 second half ready
ptFAICheck.HalfReady = &gwHalfReady;
// 3rd Step: Checks if the current data acquisition is complete and return current status
// Get Interrupt transfer status
ErrCde = DRV_FAICheck(DriverHandle, (LPT_FAICheck) &ptFAICheck);
// 4th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 3 and 4 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
gwCyclicCount ++;
}
// 5th Step: Cancels the current data acquisition operation and resets the hardware and software
ErrCde = DRV_FAIStop(DriverHandle)
// 6th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
37
Single Analog Input Channel Acquisition with Interrupt Transfer (with event):
Single channel
DRV_EnableEvent
DRV_FAIIntStart
DRV_CheckEvent
No
Buffer Full
(complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
Fig 2-12-A. The Call Flow for Single-channel Data Acquisition with interrupt transfer and event function
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptEnableEvent.EventType = ADS_EVT_INTERRUPT | ADS_EVT_BUFCHANGE |
ADS_EVT_TERMINATED | ADS_EVT_OVERRUN;
ptEnableEvent.Enabled = gwEvtFlag;
ptEnableEvent.Count = 512;
// 1.5th Step: Enable Event, then it calls to DRV_CheckEvent() instead of
// DRV_FAICheck()
ErrCde = DRV_EnableEvent(DriverHandle, (LPT_EnableEvent) &ptEnableEvent);
38
ptFAIIntStart.TrigSrc = gwExtTrig;
ptFAIIntStart.SampleRate = gdwPacerRate;
ptFAIIntStart.chan = gwStartChl;
ptFAIIntStart.gain = DevFeatures.glGainList[gwGainCode].usGainCde;
ptFAIIntStart.count = gulConvNum;
ptFAIIntStart.cyclic = gwCyclicMode;
if (gwFifoEnable)
ptFAIIntStart.IntrCount = FIFO_SIZE;
else
ptFAIIntStart.IntrCount = 1;
// FIFO no enable
// 2nd Step: Start Interrupt transfer
ErrCde = DRV_FAIIntStart(DriverHandle, (LPT_FAIIntStart)&ptFAIIntStart);
// Implement User’s Thread
void UserThread()
{
USHORT usEventType;
LONG ErrCde;
DWORD TickValue;
TickValue = GetTickCount();
TickValue = TickValue + 500000;
while(TickValue > GetTickCount())
{
// Check message
ptCheckEvent.EventType = &usEventType;
ptCheckEvent.Milliseconds = 5000;
// 3 th Step: Clear event and read current status
if ((ErrCde = DRV_CheckEvent(DriverHandle,
(LPT_CheckEvent)&ptCheckEvent)) != 0)
{
MessageBox(hWnd,"Check Event Error !","Thread Message",MB_OK);
return ;
}
// Process interrupt event
if (usEventType & ADS_EVT_INTERRUPT)
adInterruptEvent();
// Process buffer change event
if (usEventType & ADS_EVT_BUFCHANGE)
adBufChangeEvent();
// Process overrun event
if (usEventType & ADS_EVT_OVERRUN)
adOverrunEvent();
// Process terminate event
if (usEventType & ADS_EVT_TERMINATED)
{
adTerminateEvent();
return ;
39
}
}
MessageBox(hWnd,"Never Get Any Event !","Thread Message",MB_OK);
}
// 4th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 3 and 4 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
gwCyclicCount ++;
}
// 5th Step: Cancels the current data acquisition operation and resets the hardware and software
ErrCde = DRV_FAIStop(DriverHandle);
// 6th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
40
Single Analog Input Channel Acquisition with DMA Transfer:
Single channel
DRV_AllocateDMABuffer
DRV_FAIDmaStart
DRV_FAICheck
No
Buffer Full
(complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
DRV_FreeDMABuffer
Fig 2-13. The Call Flow for Single-channel Data Acquisition with DMA transfer
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptAllocateDMABuffer.CyclicMode = gwCyclicMode;
ptAllocateDMABuffer.RequestBufSize = gulConvNum * 2;
ptAllocateDMABuffer.ActualBufSize = &gwActualBufSize;
41
ptAllocateDMABuffer.buffer = &pBuffer;
// 2nd Step: Allocate DMA buffer for DMA transfer
ErrCde = DRV_AllocateDMABuffer(DriverHandle, (LPT_AllocateDMABuffer) &ptAllocateDMABuffer);
ptFAIDmaStart.TrigSrc = gwExtTrig;
ptFAIDmaStart.SampleRate = gdwPacerRate;
ptFAIDmaStart.chan = gwStartChl;
ptFAIDmaStart.gain = DevFeatures.glGainList[gwGainCode].usGainCde;
ptFAIDmaStart.count = gulConvNum;
ptFAIDmaStart.buffer = (USHORT far *) pBuffer;
// 3th Step: Start DMA transfer
ErrCde = DRV_FAIDmaStart(DriverHandle, (LPT_FAIDmaStart)&ptFAIDmaStart);
// Get Interrupt transfer status
ptFAICheck.ActiveBuf = &gwActiveBuf;
ptFAICheck.stopped = &gwStopped;
ptFAICheck.retrieved = &gulRetrieved;
ptFAICheck.overrun = &gwOverrun;
ptFAICheck.HalfReady = &gwHalfReady;
// 4th Step: Checks if the current data acquisition is complete and return current status
ErrCde = DRV_FAICheck(DriverHandle, (LPT_FAICheck) &ptFAICheck);
// 5th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 4 and 5 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
42
}
gwCyclicCount ++;
}
// 6th Step: Cancels the current data acquisition operation and resets the hardware and software
ErrCde = DRV_FAIStop(DriverHandle);
// 7th Step: Releases the buffer allocated by DRV_AllocateDMABuffer
ErrCde = DRV_FreeDMABuffer(DriverHandle, (LPARAM)&pBuffer);
// 8th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
43
Single Analog Input Channel Acquisition with DMA Transfer (with Event):
Single channel
DRV_AllocateDMABuffer
DRV_EnableEvent
DRV_FAIDmaStart
DRV_CheckEvent
No
Buffer Full
(complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
DRV_FreeDMABuffer
Fig 2-13-A. The Call Flow for Single-channel Data Acquisition with DMA transfer and event function
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
44
ptEnableEvent.EventType = ADS_EVT_INTERRUPT | ADS_EVT_BUFCHANGE |
ADS_EVT_TERMINATED | ADS_EVT_OVERRUN;
ptEnableEvent.Enabled = gwEvtFlag;
ptEnableEvent.Count = 512;
// 1.5th Step: Enable Event, then it calls to DRV_CheckEvent() instead of
// DRV_FAICheck()
ErrCde = DRV_EnableEvent(DriverHandle, (LPT_EnableEvent) &ptEnableEvent);
ptAllocateDMABuffer.CyclicMode = gwCyclicMode;
ptAllocateDMABuffer.RequestBufSize = gulConvNum * 2;
ptAllocateDMABuffer.ActualBufSize = &gwActualBufSize;
ptAllocateDMABuffer.buffer = &pBuffer;
// 2nd Step: Allocate DMA buffer for DMA transfer
ErrCde = DRV_AllocateDMABuffer(DriverHandle, (LPT_AllocateDMABuffer) &ptAllocateDMABuffer);
ptFAIDmaStart.TrigSrc = gwExtTrig;
ptFAIDmaStart.SampleRate = gdwPacerRate;
ptFAIDmaStart.chan = gwStartChl;
ptFAIDmaStart.gain = DevFeatures.glGainList[gwGainCode].usGainCde;
ptFAIDmaStart.count = gulConvNum;
ptFAIDmaStart.buffer = (USHORT far *) pBuffer;
// 3th Step: Start DMA transfer
ErrCde = DRV_FAIDmaStart(DriverHandle, (LPT_FAIDmaStart)&ptFAIDmaStart);
// Implement User’s Thread
void UserThread()
{
USHORT usEventType;
LONG ErrCde;
DWORD TickValue;
TickValue = GetTickCount();
TickValue = TickValue + 500000;
while(TickValue > GetTickCount())
{
// Check message
ptCheckEvent.EventType = &usEventType;
ptCheckEvent.Milliseconds = 5000;
// 4 th Step: Clear event and read current status
if ((ErrCde = DRV_CheckEvent(DriverHandle,
(LPT_CheckEvent)&ptCheckEvent)) != 0)
{
MessageBox(hWnd,"Check Event Error !","Thread Message",MB_OK);
return ;
}
// Process interrupt event
if (usEventType & ADS_EVT_INTERRUPT)
adInterruptEvent();
45
// Process buffer change event
if (usEventType & ADS_EVT_BUFCHANGE)
adBufChangeEvent();
// Process overrun event
if (usEventType & ADS_EVT_OVERRUN)
adOverrunEvent();
// Process terminate event
if (usEventType & ADS_EVT_TERMINATED)
{
adTerminateEvent();
return ;
}
}
MessageBox(hWnd,"Never Get Any Event !","Thread Message",MB_OK);
}
// 5th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 4 and 5 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
gwCyclicCount ++;
}
// 6th Step: Cancels the current data acquisition operation and resets the hardware and software
46
ErrCde = DRV_FAIStop(DriverHandle);
// 7th Step: Releases the buffer allocated by DRV_AllocateDMABuffer
ErrCde = DRV_FreeDMABuffer(DriverHandle, (LPARAM)&pBuffer);
// 8th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
47
Multiple Analog Input Channel Acquisition with Interrupt Transfer:
Multiple Channel
DRV_FAIIntScanStart
DRV_FAICheck
No
Buffer Full
(complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
Fig 2-14. The Call Flow for Multiple-channel Data Acquisition with interrupt transfer
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptFAIIntScanStart.TrigSrc = gwExtTrig;
ptFAIIntScanStart.StartChan = gwStartChl;
ptFAIIntScanStart.NumChans = gwNumChl;
ptFAIIntScanStart.GainList = &gwGainCde[0];
ptFAIIntScanStart.SampleRate = gdwPacerRate;
ptFAIIntScanStart.count
= gulConvNum;
ptFAIIntScanStart.cyclic = gwCyclicMode;
if (gwFifoEnable)
48
ptFAIIntScanStart.IntrCount = FIFO_SIZE;
else
ptFAIIntScanStart.IntrCount = 1;
// 2nd Step: Start Interrupt transfer
ErrCde = DRV_FAIIntScanStart(DriverHandle, (LPT_FAIIntScanStart)&ptFAIIntScanStart);
ptFAICheck.ActiveBuf = &gwActiveBuf;
ptFAICheck.stopped = &gwStopped;
ptFAICheck.retrieved = &gulRetrieved;
ptFAICheck.overrun = &gwOverrun;
// FAICheck.HalfReady = 0 not ready, 1 first half ready, 2 second half ready
ptFAICheck.HalfReady = &gwHalfReady;
// 3rd Step: Checks if the current data acquisition is complete and return current status
// Get Interrupt transfer status
ErrCde = DRV_FAICheck(DriverHandle, (LPT_FAICheck) &ptFAICheck);
// 4th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 3 and 4 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
gwCyclicCount ++;
}
// 5th Step: Cancels the current data acquisition operation and resets the hardware and software
ErrCde = DRV_FAIStop(DriverHandle)
49
// 6th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
50
Multiple Analog Input Channel Acquisition with Interrupt Transfer (with Event):
Multiple Channel
DRV_EnableEvent
DRV_FAIIntScanStart
DRV_CheckEvent
No
Buffer Full
(complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
Fig 2-14-A. The Call Flow for Multiple-channel Data Acquisition with interrupt transfer and event function
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptEnableEvent.EventType = ADS_EVT_INTERRUPT | ADS_EVT_BUFCHANGE |
ADS_EVT_TERMINATED | ADS_EVT_OVERRUN;
ptEnableEvent.Enabled = gwEvtFlag;
ptEnableEvent.Count = 512;
// 1.5th Step: Enable Event, then it calls to DRV_CheckEvent() instead of
// DRV_FAICheck()
ErrCde = DRV_EnableEvent(DriverHandle, (LPT_EnableEvent) &ptEnableEvent);
51
ptFAIIntScanStart.TrigSrc = gwExtTrig;
ptFAIIntScanStart.StartChan = gwStartChl;
ptFAIIntScanStart.NumChans = gwNumChl;
ptFAIIntScanStart.GainList = &gwGainCde[0];
ptFAIIntScanStart.SampleRate = gdwPacerRate;
ptFAIIntScanStart.count
= gulConvNum;
ptFAIIntScanStart.cyclic = gwCyclicMode;
if (gwFifoEnable)
ptFAIIntScanStart.IntrCount = FIFO_SIZE;
else
ptFAIIntScanStart.IntrCount = 1;
// 2nd Step: Start Interrupt transfer
ErrCde = DRV_FAIIntScanStart(DriverHandle, (LPT_FAIIntScanStart)&ptFAIIntScanStart);
ptFAICheck.ActiveBuf = &gwActiveBuf;
ptFAICheck.stopped = &gwStopped;
ptFAICheck.retrieved = &gulRetrieved;
ptFAICheck.overrun = &gwOverrun;
// FAICheck.HalfReady = 0 not ready, 1 first half ready, 2 second half ready
ptFAICheck.HalfReady = &gwHalfReady;
// Implement User’s Thread
void UserThread()
{
USHORT usEventType;
LONG ErrCde;
DWORD TickValue;
TickValue = GetTickCount();
TickValue = TickValue + 500000;
while(TickValue > GetTickCount())
{
// Check message
ptCheckEvent.EventType = &usEventType;
ptCheckEvent.Milliseconds = 5000;
// 3 th Step: Clear event and read current status
if ((ErrCde = DRV_CheckEvent(DriverHandle,
(LPT_CheckEvent)&ptCheckEvent)) != 0)
{
MessageBox(hWnd,"Check Event Error !","Thread Message",MB_OK);
return ;
}
// Process interrupt event
if (usEventType & ADS_EVT_INTERRUPT)
adInterruptEvent();
// Process buffer change event
if (usEventType & ADS_EVT_BUFCHANGE)
adBufChangeEvent();
52
// Process overrun event
if (usEventType & ADS_EVT_OVERRUN)
adOverrunEvent();
// Process terminate event
if (usEventType & ADS_EVT_TERMINATED)
{
adTerminateEvent();
return ;
}
}
MessageBox(hWnd,"Never Get Any Event !","Thread Message",MB_OK);
}
// 4th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 3 and 4 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
gwCyclicCount ++;
}
// 5th Step: Cancels the current data acquisition operation and resets the hardware and software
ErrCde = DRV_FAIStop(DriverHandle)
// 6th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
53
Multiple Analog Input Channel Acquisition with DMA Transfer:
Multiple Channel
DRV_AllocateDMABuffer
DRV_FAIDmaScanStart
DRV_FAICheck
No
Buffer Full
(complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
DRV_FreeDMABuffer
Fig 2-15. The Call Flow for Multiple-channel Data Acquisition with DMA transfer
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
ptAllocateDMABuffer.CyclicMode = gwCyclicMode;
ptAllocateDMABuffer.RequestBufSize = gulConvNum * 2;
ptAllocateDMABuffer.ActualBufSize = &gwActualBufSize;
54
ptAllocateDMABuffer.buffer = &pBuffer;
// 2nd Step: Allocate DMA buffer for DMA transfer
ErrCde = DRV_AllocateDMABuffer(DriverHandle, (LPT_AllocateDMABuffer) &ptAllocateDMABuffer);
ptFAIDmaScanStart.TrigSrc = gwExtTrig;
ptFAIDmaScanStart.StartChan = gwStartChl;
ptFAIDmaScanStart.NumChans = gwNumChl;
ptFAIDmaScanStart.GainList = &gwGainCde[0];
ptFAIDmaScanStart.SampleRate = gdwPacerRate;
ptFAIDmaScanStart.count = gulConvNum;
ptFAIDmaScanStart.buffer = (USHORT far *)pBuffer;
// 3th Step: Start DMA transfer
ErrCde = DRV_FAIDmaScanStart(DriverHandle, (LPT_FAIDmaScanStart) &ptFAIDmaScanStart);
// Get Interrupt transfer status
ptFAICheck.ActiveBuf = &gwActiveBuf;
ptFAICheck.stopped = &gwStopped;
ptFAICheck.retrieved = &gulRetrieved;
ptFAICheck.overrun = &gwOverrun;
ptFAICheck.HalfReady = &gwHalfReady;
// 4th Step: Checks if the current data acquisition is complete and return current status
ErrCde = DRV_FAICheck(DriverHandle, (LPT_FAICheck) &ptFAICheck);
// 5th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 4 and 5 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
55
return ;
}
gwCyclicCount ++;
}
// 6th Step: Cancels the current data acquisition operation and resets the hardware and software
ErrCde = DRV_FAIStop(DriverHandle);
// 7th Step: Releases the buffer allocated by DRV_AllocateDMABuffer
ErrCde = DRV_FreeDMABuffer(DriverHandle, (LPARAM)&pBuffer);
// 8th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
56
Multiple Channel
DRV_AllocateDMABuffer
DRV_EnableEvent
DRV_FAIDmaScanStart
DRV_CheckEvent
No
Buffer Full (complete)
Yes
Yes
DRV_FAITransfer
Repeated?
No
DRV_FAIStop
DRV_FreeDMABuffer
Fig 2-15-A. The Call Flow for Multiple-channel Data Acquisition with DMA transfer and event function
// 1st Step: Call to DRV_DeviceOpen() function get a DriverHandle which can be applied for the other
// funcitons.
ErrCde = DRV_DeviceOpen(DeviceNum, (LONG far *) &DriverHandle);
57
ptEnableEvent.EventType = ADS_EVT_INTERRUPT | ADS_EVT_BUFCHANGE |
ADS_EVT_TERMINATED | ADS_EVT_OVERRUN;
ptEnableEvent.Enabled = gwEvtFlag;
ptEnableEvent.Count = 512;
// 1.5th Step: Enable Event, then it calls to DRV_CheckEvent() instead of
// DRV_FAICheck()
ErrCde = DRV_EnableEvent(DriverHandle, (LPT_EnableEvent) &ptEnableEvent);
ptAllocateDMABuffer.CyclicMode = gwCyclicMode;
ptAllocateDMABuffer.RequestBufSize = gulConvNum * 2;
ptAllocateDMABuffer.ActualBufSize = &gwActualBufSize;
ptAllocateDMABuffer.buffer = &pBuffer;
// 2nd Step: Allocate DMA buffer for DMA transfer
ErrCde = DRV_AllocateDMABuffer(DriverHandle, (LPT_AllocateDMABuffer) &ptAllocateDMABuffer);
ptFAIDmaScanStart.TrigSrc = gwExtTrig;
ptFAIDmaScanStart.StartChan = gwStartChl;
ptFAIDmaScanStart.NumChans = gwNumChl;
ptFAIDmaScanStart.GainList = &gwGainCde[0];
ptFAIDmaScanStart.SampleRate = gdwPacerRate;
ptFAIDmaScanStart.count = gulConvNum;
ptFAIDmaScanStart.buffer = (USHORT far *)pBuffer;
// 3th Step: Start DMA transfer
ErrCde = DRV_FAIDmaScanStart(DriverHandle, (LPT_FAIDmaScanStart) &ptFAIDmaScanStart);
// Implement User’s Thread
void UserThread()
{
USHORT usEventType;
LONG ErrCde;
DWORD TickValue;
TickValue = GetTickCount();
TickValue = TickValue + 500000;
while(TickValue > GetTickCount())
{
// Check message
ptCheckEvent.EventType = &usEventType;
ptCheckEvent.Milliseconds = 5000;
// 4 th Step: Clear event and read current status
if ((ErrCde = DRV_CheckEvent(DriverHandle,
(LPT_CheckEvent)&ptCheckEvent)) != 0)
{
MessageBox(hWnd,"Check Event Error !","Thread Message",MB_OK);
return ;
}
// Process interrupt event
if (usEventType & ADS_EVT_INTERRUPT)
adInterruptEvent();
58
// Process buffer change event
if (usEventType & ADS_EVT_BUFCHANGE)
adBufChangeEvent();
// Process overrun event
if (usEventType & ADS_EVT_OVERRUN)
adOverrunEvent();
// Process terminate event
if (usEventType & ADS_EVT_TERMINATED)
{
adTerminateEvent();
return ;
}
}
MessageBox(hWnd,"Never Get Any Event !","Thread Message",MB_OK);
}
// 5th Step: Transfers the data from the buffer being used for the data acquisition operation to the
// specified data buffer
// If your program want to acquire data continusly, please put the Step 4 and 5 in a loop
if (gwHalfReady == 1) // first ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = 0;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer)&ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
}
else if (gwHalfReady == 2) // second half ready
{
ptFAITransfer.ActiveBuf = 0; // single buffer
ptFAITransfer.DataType = gwDataType;
ptFAITransfer.start = gulConvNum/2;
ptFAITransfer.count = gulConvNum/2;
ptFAITransfer.overrun = &gwOverrun;
if ((ErrCde = DRV_FAITransfer(DriverHandle, (LPT_FAITransfer) &ptFAITransfer)) != 0)
{
DRV_GetErrorMessage(ErrCde,(LPSTR)szErrMsg);
MessageBox(hWnd,(LPCSTR)szErrMsg,"Thread Message",MB_OK);
return ;
}
gwCyclicCount ++;
}
59
// 6th Step: Cancels the current data acquisition operation and resets the hardware and software
ErrCde = DRV_FAIStop(DriverHandle);
// 7th Step: Releases the buffer allocated by DRV_AllocateDMABuffer
ErrCde = DRV_FreeDMABuffer(DriverHandle, (LPARAM)&pBuffer);
// 8th Step: When you want to exit the I/O, please call to DRV_DeviceClose() function
ErrCde = DRV_DeviceClose((LONG far *) &DriverHandle);
60
© Copyright 2026 Paperzz