Click here to Skip to main content
13,866,944 members
Click here to Skip to main content
Add your own
alternative version


5 bookmarked
Posted 23 Jul 2015
Licenced CPOL

How to perform Serial Peripheral Interface (SPI) communication with a data acquisition device using C# and the National Instruments DAQmx API.

, 23 Jul 2015
Rate this:
Please Sign up or sign in to vote.
A class to implement SPI in C# using DAQmx C api and pInvoke.


While developing an automated testing platform that makes use of a National Instruments USB-6210 Data Acquisition device (DAQ) to perform measurements on a panel of devices; I wanted to employ some kind of test fixture command and control using the DAQ's digital output and input lines.



Figure 1: NI USB-6210 Data Acquisition device


The NI USB-6210 has 4 digital inputs and 4 outputs available so I decided to implement a four wire Serial Peripheral Interface (SPI) bus with the DAQ as the master and two slave select lines. While researching SPI I found a useful article on the topic along with some source code examples that I was able to adapt to a C# class that I could use in my project. Here [^] is a link to that article.

This SPI Class

The class constructor provides overloads for specifying the output port (the four output lines), the input line, clock phase, and clock polarity. In addition to this; the class exposes several Properties and methods.

Public Members

  • Constructor overloads
    • daqSPI() - Instantiate class with the following defaults:
    • ouputLines = "Dev0/port1"
    • inputLine = "Dev0/port0/line3"
    • cpol = ClockPolarity.ONE
    • cpha = ClockPhase.LOGICAL_ZERO
    • daqSPI(string outputLines, string inputLine) - Specify the output and input lines.
    • daqSPI(string outputLines, string inputLine, ClockPolarity cpol, ClockPhase cpha) - Specify the output and input lines, as well as the polarity and phase of the clock pulse.
  • Methods
    • Dispose() - Explicitly clean up unmanaged resources employed by the class.
    • Transfer(byte inByte) - Simultaneously write a byte to the bus and read a byte from the bus.
  • Properties
    • SCKPhase - Get or Set the edges of the clock on which a slave latches input-data bits and shifts out bits of output data.
    • SCKPolarity - Get or Set the level of the serial clock line before and after byte transfer.
    • SS0 - Get or Set the SS0 (slave 0 select) wire bit.
    • SS1 - Get or Set the SS1 (slave 1 select) wire bit.
    • Timeout - Get or Set the read and write operation timeout.
  • Enumerations
    • ClockPolarity - Specifies the level of the SCK line before and after byte transfer.
      • ZERO
      • ONE
    • ClockPhase - Specifies the edges of the clock on which a slave latches input-data bits and shifts out bits of output data.

Using the class

This class makes use of several NI-DAQmx C API calls. These are found in a Native wrapper class, containing PInvoke signatures, that I put together and included with this project (DAQmx.cs).

The code below instructs the DAQ to send some purple prose [^] to slave device 0, using the default SPI configuration, while simultaneously printing response bytes to the console.

static void Main(string[] args)
        daqSPI spi = new daqSPI("Dev1/port1", "Dev1/port0/line3", 
                                 daqSPI.ClockPolarity.ONE, daqSPI.ClockPhase.LOGICAL_ZERO);

        byte[] data = ASCIIEncoding.Default.
            GetBytes("It was a dark and stormy night; the rain fell in torrents, except at " +
        "occasional intervals, when it was checked by a violent gust of wind " +
        "which swept up the streets (for it is in London that our scene lies), " +
        "rattling along the house-tops, and fiercely agitating the scanty flame " +
        "of the lamps that struggled against the darkness. Through one of the " +
        "obscurest quarters of London, and among haunts little loved by the " +
        "gentlemen of the police, a man, evidently of the lowest orders, was " +
        "wending his solitary way.");

        spi.SS0 = true; //Selects SS0 deselects SS1

        foreach (byte b in data)
            Console.Write((char) spi.Transfer(b));
    catch (Exception ex)
        Console.WriteLine("DAQmx Error: {0}", ex.ToString());

    Console.WriteLine("End of program, press Enter key to quit");

Alas slave device 0 is illiterate and doesn't appreciate good verse. However my Tektronix TDS 420 captured one of the bytes being transmitted.



Figure 2: Byte transfer captured by the TDS 420 Oscilloscope (image obtained by means of Instrument Snap Shot [^] ).


  • Line 1 is the data line
  • Line 2 is the clock
  • Line 3 is SS0 (low = selected)
  • Line 4 is SS1 (unselected)

Notice the clock frequency: this is close to 300 baud and about as fast as I can drive the DAQ. It is fast enough to transfer short command strings, but a bit slow for moving a lot of data. It is however, good enough for my application.



Figure 3: Old fashioned 300 Baud data transfer.


The Demo

The demo is something that I put together to test the SPI class while creating it. The following figure shows the NI USB-6210 with the lines I use labeled. While testing I simply looped the MOSI line to the MISO line.



Figure 4: Lines used for the 4 wire bus plus power and ground.


This class and demo should work with any DAQ that has at least 4 digital output lines and one digital input line by simply supplying the appropriate addresses to the class constructor.


  • July. 23, 2015: Version


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

David MacDermot
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.190214.1 | Last Updated 23 Jul 2015
Article Copyright 2015 by David MacDermot
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid