SPI同步串行通信
UART串口通信中的数据只能一位一位的传输,如果数据量比较大的时候,传输速率会受到很大影响,此时我们就可以考虑使用同步串行通信了,比如SPI。

SPI通信原理

SPI,全称是Serial Peripheral Interface,也就是串行外设接口,同样是一种通信协议,在很多芯片中都有集成。


相比之前学习的UART串口通信,他多了两根线,其中一个是时钟信号,另一个是设备使能信号,用来控制设备是否启用,所以也产生了主从设备的概念。

  • MISO:Master Input Slave Output,主设备数据输入,从设备数据输出;
  • MOSI:Master Output Slave Input,主设备数据输出,从设备数据输入;
  • SCLK:Serial Clock,时钟信号,由主设备产生;
  • CS:Chip Select,从设备使能信号,由主设备控制。 这样,在一组SPI通信的系统中,可以连接多个设备,想要和哪个设备通信时,就使能这个设备,除能其他设备。
我们在开发中常见的SPI设备会有一些传感器,还有电阻屏之类的。

硬件连线

在SPI的通信中,有一个管脚负责发送,另外一个管脚负责接收,如果我们把同一组SPI的发送和接收接到一起,岂不是能接收到自己发送的数据吗
我们不妨来试一试,这里使用一个跳线帽直接把19,21两个SPI的通信管脚短接。

运行示例程序

大家来运行例程,看看会发生什么? 
 bash
$ sudo python3 test_spi.py
在旭日X3派的终端中,输入运行例程的指令,接下来我们就可以看到通过SPI传输并收到的数据啦,相当于是左手传递给右手,自己给自己循环传输数据了。

代码解析

test_spi.py:

python
#!/usr/bin/env python3

import sys
import os
import time

# 导入spidev模块
import spidev

def BytesToHex(Bytes):
    return ''.join(["0x%02X " % x for x in Bytes]).strip()

def spidevTest():
    # 设置spi的bus号(0, 1, 2)和片选(0, 1)
    spi_bus = input("Please input SPI bus num:")
    spi_device = input("Please input SPI cs num:")
    # 创建spidev类的对象以访问基于spidev的Python函数。
    spi=spidev.SpiDev()
    # 打开spi总线句柄
    spi.open(int(spi_bus), int(spi_device))

    # 设置 spi 频率为 12MHz
    spi.max_speed_hz = 12000000

    print("Starting demo now! Press CTRL+C to exit")

    # 发送 [0x55, 0xAA], 接收的数据应该也是 [0x55, 0xAA]
    try:
        while True:
            resp = spi.xfer2([0x55, 0xAA])
            print(BytesToHex(resp))
            time.sleep(1)

    except KeyboardInterrupt:
        spi.close()

if __name__ == '__main__':
    print("List of enabled spi controllers:")
    os.system('ls /dev/spidev*')

    spidevTest()
在python中使用spidev这个库,初始化X3Pi的SPI,之后使用xerf2发送数据,同时接收数据,并打印出来,会发现打印出来的就是我们发送的。