Mizar32/SPI
另一个常用的总线,用于连接同一电路板上的芯片或在同一箱体中有多个电路板的模块化设计中的芯片,是 SPI 总线,它代表串行外设接口,有时也称为“四线”接口。
SPI 是一种同步串行数据链路,可以同时传输和接收数据,并且可以实现比 I2C 高得多的数据速率。它非常适合流数据应用程序,例如读写 SD 卡或发送/接收音频。正常频率为数十兆赫兹,例如,一个常见的 8 引脚 32Mbit Atmel 数据闪存连接到 SPI 总线,可以在 66MHz 下工作。
没有正式的 SPI 标准。该总线由摩托罗拉于 1985 年首次推出,并首次使用 M68HC11 微控制器进行了详细说明。从那时起,它已被许多其他硅制造商采用,并且广泛应用于嵌入式行业中许多不同的应用。例如,所有 SD 存储卡都可以使用 SPI 接口。
SPI 总线实际应用的其他示例包括与模数转换器、数模转换器、数字传感器、EEPROM、闪存、触摸屏控制器、数字电位器、实时时钟、开关、串行端口控制器和 USB 控制器连接,或者简单地在同一电路板中的不同微控制器之间建立点对点通信。
SPI 是一种非常简单的通信协议,几乎没有高级协议,这意味着开销非常小,并且数据可以以高速率双向传输。
与 I2C 一样,SPI 设备也使用主从关系进行通信,但不是通过在数据中发送从设备地址来选择从设备,而是使用一条额外线来选择从设备,这条线连接到每个从设备,称为芯片选择信号。
与 I2C 不同,每个 SPI 总线上只能有一个主设备。
与 I2C 一样,主设备是发送时钟脉冲的设备,但在每个脉冲期间,从主设备到从设备发送 1 位数据,并且从从设备到主设备发送 1 位数据。
SPI 使用 4 根线在主设备和从设备之间进行通信。
- 时钟 (SCLK)
- 主输出从输入 (MOSI)
- 主输入从输出 (MISO)
- 芯片选择 (CS)
前三根线对总线上的所有设备都是通用的,并且总线上的每个从设备都有单独的芯片选择线。
例如,一个带有单个从设备的主设备需要四根线:三根用于 SCLK、MOSI、MISO 和一根用于芯片选择。
在独立从设备配置中,每个额外的从设备都需要另一个 GPIO 引脚作为芯片选择,以从主设备选择另一个从设备。
除了以 MHz 为单位的时钟频率(对应于比特率)之外,您还必须相对于数据定义时钟极性 (CPOL) 和时钟相位 (CPHA)。
SPI 通信有 4 种模式,所选模式必须在任何时刻进行通信的主设备和从设备之间保持一致。
- 模式 0,CPOL=0,CPHA=0
- 模式 1,CPOL=0,CPHA=1
- 模式 2,CPOL=1,CPHA=0
- 模式 3,CPOL=1,CPHA=1
通信由主设备启动。它将其时钟频率配置为等于或小于它要与之通信的从设备支持的最大频率。然后,使用芯片选择线选择所需的从设备,将其拉低,然后主设备开始发出时钟脉冲。
在每个时钟周期内,两个移位寄存器上都会进行全双工数据传输。这意味着主设备在 MOSI 线上发送一个位;从设备从该线读取它,并且从设备在 MISO 线上发送一个位,并且主设备从该线读取它。
如果需要交换更多数据,则将移位寄存器加载新数据,并重复此过程。然后,当不再需要传输数据时,主设备停止时钟。
这基本上是 SPI 协议定义的所有内容。SPI 没有定义任何最大数据速率,也没有定义任何特定的寻址方案;它没有确认机制来确认数据接收,并且不提供任何流控制。
主板上的 AT32UC3A 片上系统包含两个 SPI 接口,SPI0 和 SPI1,其中 SPI0 在左侧总线上,SPI1 在右侧。每个接口都有四个芯片选择线,最多允许八个 SPI 设备;其中一个 (SPI1 CS0) 用于与 SD/MMC 卡通信,三个 (SPI0 CS0 和 SPI1 CS1 和 CS2) 可在总线连接器上使用。
信号 | GPIO | 总线引脚 | eLua 名称 | PicoLisp |
---|---|---|---|---|
SPI0_CS0 | PA10 | BUS1&3 引脚 12 | pio.PA_10 |
'PA_10
|
SPI0_MISO | PA11 | BUS1&3 引脚 13 | pio.PA_11 |
'PA_11
|
SPI0_MOSI | PA12 | BUS1&3 引脚 14 | pio.PA_12 |
'PA_12
|
SPI0_SCK | PA13 | BUS1&3 引脚 15 | pio.PA_13 |
'PA_13
|
SPI1_CS1 | PA18 | BUS3 引脚 11 | pio.PA_18 |
'PA_18
|
SPI1_CS2 | PA19 | BUS4 引脚 12 | pio.PA_19 |
'PA_19
|
SPI1_MISO | PA17 | BUS4 引脚 11 | pio.PA_17 |
'PA_17
|
SPI1_MOSI | PA16 | BUS4 引脚 10 | pio.PA_16 |
'PA_16
|
SPI1_SCK | PA15 | BUS4 引脚 9 | pio.PA_15 |
'PA_15
|
eLua 通过 SPI 读取和写入 SD 卡,并使用以 "/mmc/
" 开头的文件名,通过 Lua 的 io
模块访问卡上的文件。
在 PicoLisp 中,load
函数可用于从 SD 卡加载 Lisp 代码并在读取评估循环中执行它。示例:(load "/mmc/lib.l" "/mmc/pilog.l")
Alcor6L 中包含一个 SPI
模块,用于进行低级 SPI 协议通信,并假定它可以工作,但尚未测试。
可用函数列表
函数 | 返回值 | 描述 |
---|---|---|
spi.setup(id, type, clock, cpol, cpha, databits) |
clock |
设置 SPI 接口 |
spi.sson(id) |
nil |
选择 SPI 接口的 SS 线 (从机选择) |
spi.ssoff(id) |
nil |
取消选择 SPI 接口的 SS 线 (从机选择) |
spi.write(id, data1, [data2], ..., [datan]) |
nil |
向 SPI 接口写入一个或多个字符串/数字 |
spi.readwrite(id, data1, [data2], ..., [datan]) |
一个数组 | 执行 spi.write 并返回从同一接口读取的数据 |
可用函数列表
函数 | 返回值 | 描述 |
---|---|---|
(spi-setup id type clock cpol cpha databits) |
clock |
设置 SPI 接口 |
(spi-sson id) |
Nil |
选择 SPI 接口的 SS 线 (从机选择) |
(spi-ssoff id) |
Nil |
取消选择 SPI 接口的 SS 线 (从机选择) |
(spi-write id 'any) |
最后写入的值 | 向 SPI 接口写入一个或多个字符串/数字 |
(spi-readwrite id 'any) |
不适用 | 尚未实现:请参阅 问题 #13 |
- 串行外设接口简介,David Kalinsky 和 Roee Kalinsky,在 Embedded 的电子博客中,2002 年 2 月 1 日。
- EEHerald 的嵌入式系统在线课程,第 12 模块:SPI 总线接口
- 第 23 节中 Atmel AT32UC3A 数据手册:“串行外设接口”
- 维基百科 - 串行外设接口
- 第 eLua SPI 模块参考手册;