65.9K
CodeProject 正在变化。 阅读更多。
Home

如何使用 C# 和 National Instruments DAQmx API 对数据采集设备执行串行外设接口 (SPI) 通信。

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2015年7月23日

CPOL

3分钟阅读

viewsIcon

19418

downloadIcon

524

一个使用 DAQmx C api 和 pInvoke 在 C# 中实现 SPI 的类。

引言

在开发一个自动化测试平台时,该平台使用 National Instruments USB-6210 数据采集设备 (DAQ) 来测量一组设备;我想使用 DAQ 的数字输出和输入线来实现某种测试夹具命令和控制。

Figure1

 

图 1:NI USB-6210 数据采集设备

 

NI USB-6210 有 4 个数字输入和 4 个数字输出可用,所以我决定实现一个四线串行外设接口 (SPI) 总线,DAQ 作为主设备,两个从设备选择线。 在研究 SPI 时,我找到了一篇关于该主题的有用文章以及一些源代码示例,我能够将其改编为 C# 类,以便在我的项目中使用。 此处 [^] 是该文章的链接。

这个 SPI 类

该类的构造函数提供了用于指定输出端口(四个输出线)、输入线、时钟相位和时钟极性的重载。 除此之外;该类还公开了几个属性和方法。

公共成员

  • 构造函数重载
    • daqSPI() - 使用以下默认值实例化类
    • ouputLines = "Dev0/port1"
    • inputLine = "Dev0/port0/line3"
    • cpol = ClockPolarity.ONE
    • cpha = ClockPhase.LOGICAL_ZERO
    • daqSPI(string outputLines, string inputLine) - 指定输出和输入线。
    • daqSPI(string outputLines, string inputLine, ClockPolarity cpol, ClockPhase cpha) - 指定输出和输入线,以及时钟脉冲的极性和相位。
  • 方法
    • Dispose() - 显式清理该类使用的非托管资源。
    • Transfer(byte inByte) - 同时向总线写入一个字节并从总线读取一个字节。
  • 属性
    • SCKPhase - 获取或设置从设备锁存输入数据位并移出输出数据位的时钟边沿。
    • SCKPolarity - 获取或设置字节传输前后串行时钟线的电平。
    • SS0 - 获取或设置 SS0(从设备 0 选择)线位。
    • SS1 - 获取或设置 SS1(从设备 1 选择)线位。
    • Timeout - 获取或设置读取和写入操作超时。
  • 枚举
    • ClockPolarity - 指定字节传输前后 SCK 线的电平。
      • ZERO
      • ONE
    • ClockPhase - 指定从设备锁存输入数据位并移出输出数据位的时钟边沿。
      • LOGICAL_ZERO
      • LOGICAL_ONE

使用该类

此类使用多个 NI-DAQmx C API 调用。 这些 API 调用可以在一个 Native 包装器类中找到,该类包含我放在一起并包含在此项目中的 PInvoke 签名 (DAQmx.cs)。

下面的代码指示 DAQ 使用默认 SPI 配置将一些 华丽辞藻 [^] 发送到从设备 0,同时将响应字节打印到控制台。

static void Main(string[] args)
{
    try
    {
        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));
        }
        Console.WriteLine();
    }
    catch (Exception ex)
    {
        Console.WriteLine("DAQmx Error: {0}", ex.ToString());
    }

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

唉,从设备 0 是文盲,并不欣赏好的诗句。 然而,我的 Tektronix TDS 420 捕获了正在传输的字节之一。

Figure2

 

图 2:TDS 420 示波器捕获的字节传输(图像通过 仪器快照 [^] 获得)。

 

  • Line 1 是数据线
  • Line 2 是时钟
  • Line 3 是 SS0(低电平 = 选中)
  • Line 4 是 SS1(未选中)

请注意时钟频率:这接近 300 波特,并且几乎是我可以驱动 DAQ 的最快速度。 它足以传输短命令字符串,但对于移动大量数据来说有点慢。 但是,对于我的应用程序来说,它已经足够了。

Figure3

 

图 3:老式 300 波特数据传输。

 

演示

该演示是我在创建 SPI 类时放在一起测试它的东西。 下图显示了带有我使用的线路标签的 NI USB-6210。 在测试时,我只是将 MOSI 线回环到 MISO 线。

Figure4

 

图 4:用于 4 线总线以及电源和接地的线路。

 

通过简单地将适当的地址提供给类构造函数,此类和演示应适用于任何具有至少 4 个数字输出线和一个数字输入线的 DAQ。

历史

  • 2015 年 7 月 23 日:版本 1.0.0.0。
© . All rights reserved.