我想知道是否有任何特别快速的方法可以在微控制器上使用 GPIO 调用(bitbanging)来读取或写入串行协议(例如 SPI)。最快的可能在某种程度上是特定于架构的,但在任何架构上,较少数量的操作可能会更快。假设端口读/写和任何按位整数操作发生在单个 cpu 时钟中是公平的;比较和跳转可能需要几个时钟。
举个简单的例子,考虑使用传统的 SPI 写入一个字节,给定一个带有串行时钟位掩码的端口(寄存器)、miso(输入)、mosi(输出)引脚。要在时钟的下降沿输出 1 位port |= CLOCK|OUTPUT; port &= ~CLOCK;
并写入一个字节,需要在循环中对该字节中的每个位执行此操作(输出 0 或 1)。
像这样的东西:
uint8_t data;
// for each bit, msb first
for (i = 7; i >= 0; i--)
{
if ((data >> i) & 0x01)
{
// set output pin to 1
port |= OUTPUT;
}
else
{
// set output pin to 0
port &= ~OUTPUT;
}
// strobe clock
port |= CLOCK;
port &= ~CLOCK;
}
对此的一些优化是显而易见的,例如展开循环。
一些优化可能不是那么明显:是否可以根据要写入的字节(或只是其中的一部分)进行切换,从而避免移位和屏蔽每一位?如何让这个分支免费?如何利用零或一的运行?(在这种情况下不需要改变输出,只需要改变时钟) 一次操作改变输出和时钟怎么样?
使用其中一些技巧的示例(尽可能在一个操作中更改输出和时钟,展开循环,但不是无分支): https ://github.com/FastLED/FastLED/blob/master/fastspi_bitbang.h