5. SPI通讯¶
在前面章节里,我们给大家讲到了I2C通讯协议使用相关的内容。
在本章里,我们接着为大家介绍另一种通讯协议的使用,SPI通讯协议。
SPI通讯协议同样也是在电子器件通讯中常见的一种通讯协议。
不过SPI通讯协议的通讯速率要更高,而且它采用的是全双工的通讯方式。
所以我们常常能在对通信速率有要求的电子器件上,发现SPI通讯协议下规定的接口。
比如一些 小尺寸的LCD屏幕
、 AD转换芯片
、 nRF系列射频模块
、 SPI-FLASH
等等。
关于SPI协议的具体内容,我们在此不作过多探究,大家可以自行搜索SPI通讯协议的相关知识学习。
本章中,我们的重点是使用前面介绍的 python-periphery 库, 来使用到我们鲁班猫板卡上的SPI主机。
5.1. SPI实验¶
由于SPI通讯协议支持全双工的方式进行通讯,所以我们可以通过回环测试来进行实验验证, 在实验中,我们将SPI接口的MOSI、MISO接口连接在一起即可。
5.2. 实验准备¶
5.2.1. 添加SPI资源¶
在板卡上的GPIO可能没有复用为I2C,可通过设置设备树插件来加载, LubanCat_RK系列板卡的引脚参考下: 《LubanCat-RK系列-40pin引脚对照图》
下面以LubanCat 2为例开启下SPI的设备树插件(LubanCat 2引出的引脚可使用spi3):
# 不同板卡的配置文件和i2c不同,以LubanCat 2为例,配置文件为uEnvLubanCat 2.txt,
# 登录系统终端,打开/boot/uEnv/uEnvLubanCat 2.txt文件
sudo vim /boot/uEnv/uEnvLubanCat 2.txt
#进入编辑模式,取消I2c3前面的注释,保存并退出文件,重启系统
重启后,查看板卡的SPI资源是否加载:
# 在终端中输入如下命令,可以查看到SPI资源:
ls -l /dev/spi*
板卡上的I2C资源示例,仅供参考:
关于在linux上的SPI测试,可以参考下 《SPI通讯》
5.3. 使用python-periphery¶
python-periphery 库支持的SPI功能是基于Linux的SPI系统实现的,所以要想利用该库使用到SPI的功能, 需要板卡提供支持。像鲁班猫板卡,就可以完美使用 python-periphery 库SPI通讯功能。 这样这样一来,就不需要我们在软件层面上利用GPIO模拟SPI主机功能了。
5.3.1. 安装 python-periphery¶
重要
如在前面小节中安装了此库,务必跳过此操作。
python-periphery 的安装方式如下:
# 在板卡使用如下命令安装
sudo pip3 install python-periphery
5.3.2. periphery使用SPI功能¶
使用 python-periphery 库进行SPI功能使用的示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | """ periphery spi 测试 """
from periphery import SPI
# 待发送数据列表
data_out = [0xAA, 0xBB, 0xCC, 0xDD]
try:
# 申请SPI资源,打开 spidev3.0 控制器,配置SPI主机为工作模式0、工作速率为1MHz
spi = SPI("/dev/spidev3.0", 0, 1000000)
# 发送数据,同时接收数据到data_in列表中
data_in = spi.transfer(data_out)
# 打印发送的数据内容
print("发送的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*data_out))
print("接收到的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*data_in))
finally:
# 关闭申请的SPI资源
spi.close()
|
代码说明:
第5行,申请SPI资源,占用SPI3主机,配置对应的工作模式
第9行,构造准备发送的消息列表
第12行,开启SPI传输,因为SPI为全双工通讯方式,发送数据的同时也可接收数据
第19行,释放SPI资源,释放SPI3主机
5.3.2.1. 实验操作¶
示例代码使用LubanCat 2板卡,操作如下:
# 在板卡spi_test.py所在的目录执行如下命令
sudo python3 spi_test.py
# 可看到终端打印出的接受到的数据与发送出去的一致
由于在硬件连接时,已经将SPI接口的MOSI、MISO接口连接, 所以SPI控制器发送出数据的同时也会将数据接收回来,这就是回环测试。
5.4. 方式二:使用Adafruit Blinka¶
Adafruit Blinka 与 python-periphery 功能类似,SPI通讯也是基于Linux的SPI子系统实现的。 只是在代码上的用法上有较大差异。
5.4.1. 安装Adafruit Blinka¶
重要
如在前面小节中安装了此库,务必跳过此操作。
Adafruit Blinka 的安装方式如下:
# 在板卡使用如下命令安装
sudo apt -y install python3-libgpiod python-periphery # 注:如已安装,忽略此步
sudo pip3 install Adafruit-Blinka
5.4.2. Adafruit-Blinka使用SPI主机¶
使用这个 Adafruit Blinka 进行输入输出的示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | """ blinka spi 测试 """
import busio
from board import *
# 数据发送、接受缓冲区
OutBuffer = [0xAA, 0xBB, 0xCC, 0xDD]
InBuffer = bytearray(4)
try:
# 申请spi资源
spi = busio.SPI(SCLK, MOSI, MISO)
# 配置时先锁定SPI
spi.try_lock()
# 配置SPI主机工作速率为1MHz、时钟极性为0、时钟相位为0、单个数据位数为8位
spi.configure(1000000, 0, 0, 8)
# 配置操作完成解锁
spi.unlock()
# SPI通讯,发送的同时也进行读取,发送的数据存放在OutBuffer,读取的数据存放在InBuffer
spi.write_readinto(OutBuffer, InBuffer)
print(
"(write_readinto)接收到的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(
*InBuffer
)
)
# SPI通讯,只写使用方法演示
spi.write(OutBuffer)
print(
"(OutBuffer)发送的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*OutBuffer)
)
InBuffer = [0, 0, 0, 0]
# SPI通讯,只读使用方法演示
spi.readinto(InBuffer)
print(
"(readinto)接收到的数据: [0x{:02x}, 0x{:02x}, 0x{:02x}, 0x{:02x}]".format(*InBuffer)
)
finally:
# 释放spi资源
spi.deinit()
|
代码说明:
第11行,申请SPI资源,占用SPI3主机
第14~18行,配置SPI3主机的工作模式,在配置前需要先锁定资源
第21行,使用SPI3主机发送字节数组OutBuffer里的数据,同时读取数据到InBuffer
第30行,使用SPI3仅发送数据,不读取
第37行,使用SPI3仅读取数据,不发送
运行后显示:
另外,还有一个配套例程io/spi/ssd1306_spi_status.py,将使用spi控制屏幕显示, 具体参考下前面i2c使用Adafruit_CircuitPython_SSD1306库控制屏幕显示的小节。
Adafruit Blinka 库未提供SPI对象的使用示例,相关的API功能大家可以参考: CircuitPython SPI 下给出的介绍。