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





5.00/5 (2投票s)
一个使用 DAQmx C api 和 pInvoke 在 C# 中实现 SPI 的类。
引言
在开发一个自动化测试平台时,该平台使用 National Instruments USB-6210 数据采集设备 (DAQ) 来测量一组设备;我想使用 DAQ 的数字输出和输入线来实现某种测试夹具命令和控制。
图 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 捕获了正在传输的字节之一。
图 2:TDS 420 示波器捕获的字节传输(图像通过 仪器快照 [^] 获得)。
- Line 1 是数据线
- Line 2 是时钟
- Line 3 是 SS0(低电平 = 选中)
- Line 4 是 SS1(未选中)
请注意时钟频率:这接近 300 波特,并且几乎是我可以驱动 DAQ 的最快速度。 它足以传输短命令字符串,但对于移动大量数据来说有点慢。 但是,对于我的应用程序来说,它已经足够了。
图 3:老式 300 波特数据传输。
演示
该演示是我在创建 SPI 类时放在一起测试它的东西。 下图显示了带有我使用的线路标签的 NI USB-6210。 在测试时,我只是将 MOSI 线回环到 MISO 线。
图 4:用于 4 线总线以及电源和接地的线路。
通过简单地将适当的地址提供给类构造函数,此类和演示应适用于任何具有至少 4 个数字输出线和一个数字输入线的 DAQ。
历史
- 2015 年 7 月 23 日:版本 1.0.0.0。