树莓派学习 26.SPI通讯

一、SPI简介

SPI全称是串行外设接口(Serial Peripheral Interface),是由Motorola提出的一种全双工同步串行通信接口,通信波特率可以高达5Mbps,但具体速度大小取决于SPI硬件。SPI接口具有全双工操作,操作简单,数据传输速率较高的优点,但也存在没有指定的流控制,没有应答机制确认是否接收到数据的缺点。SPI总线只需四条线就可以完成MCU与各种外围器件的通讯:

  • SCLK:Serial Clock,(串行)时钟
  • MISO:Master In Slave Out,主设备输入,从设备输出
  • MOSI:Master Out Slave In,主设备输出,从设备输入
  • SS: Slave Select,选中从设备,片选,片选的其他别称[① CS(Chip Select)芯片选择、②CE(Chip Enable)芯片使能]

二、SPI通讯

1. 串行读写

SPI是[单主设备(single-master )]通信协议,这意味着总线中的只有一支中心设备能发起通信。当SPI主设备想读/写[从设备]时,它首先拉低[从设备]对应的SS线(SS是低电平有效),接着开始发送工作脉冲到时钟线上,在相应的脉冲时间上,[主设备]把信号发到MOSI实现“写”,同时可对MISO采样而实现“读”。

树莓派学习 26.SPI通讯_片选

2. 数据交换

SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响,SPI主模块和与之通信的外设音时钟相位和极性应该一致。

  1. 如果CPOL=0,串行同步时钟的空闲状态为低电平;
  2. 如果CPOL=1,串行同步时钟的空闲状态为高电平;
  3. 时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。
  4. 如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;
  5. 如果CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样;

3. 数据传输

在一个SPI时钟周期内,会完成如下操作:

  1. 主设备通过MOSI线发送1位数据,从设备通过该线读取这1位数据;
  2. 从设备通过MISO线发送1位数据,主设备通过该线读取这1位数据。

这是通过移位寄存器来实现的。

4. 引脚

树莓派学习 26.SPI通讯_ide_02

  • VCC----1
  • GND----6
  • 19 MOSI – master output slave input
  • 21 MISO – master input slave output
  • 23 SCLK – clock
  • 24 CE0 – chip enable 0
  • 26 CE1 – chip enable 1

5. 启用SPI

在设置里启用SPI。
​​​sudo raspi-config​​ 启用后可输入命令查看:

pi@ventilator:~ $ ls /dev/spidev0.*
/dev/spidev0.0 /dev/spidev0.1

树莓派只引出来一组spi(引脚19、21、23、24),对应的设备文件为/dev/spidev0.0。

三、代码实现

1. 回声测试:将MOSI 和 MISO短接。

​源码地址​

运行效果:
树莓派学习 26.SPI通讯_数据_03

本文部分内容来源

2. 另一个测试代码:

wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-3.10.y/Documentation/spi/spidev_test.c
# 注意要将代码里的/dev/spidev1.1改为/dev/spidev0.1
gcc spidev_test.c
sudo ./a.out

输出:
树莓派学习 26.SPI通讯_数据_04

3. 安装spidev

官网说明:https://pypi.org/project/spidev/3.1/

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python-dev python3-dev
cd ~
git clone https://github.com/doceme/py-spidev.git
cd py-spidev
make
sudo make install

属性及方法

属性/函数

作用

bits_per_word

每个单词字节数

cshigh

片选信息,默认为False

lsbfirst

大小端,默认为False

max_speed_hz

最大总线速度

mode

spi的工作模式,用来确定时钟和片选信号是上升还是下降沿开始读写,这个可能跟具体的芯片有关

函数 open(bus, device)

打开设备,bus和device对应设备后面的数字:如图

xfer([values])

向spi设备发送命令,这个函数返回一个列表,存放接收到的数据

xfer2([values])

与上面函数作用相同,不同的是,xfer在当前片选引脚为高电平工作,xfer2在执行过程中将片选引脚保持低电平,在两次转换间让cs引脚保持为高电平。

使用spidev

python-spidev的使用方法:

# 导入库
import spidev

bus=0
device=0
# 打开spi设备,此处设备为/dev/spi-decv0.0
spi=SPI.SpiDev(bus,device)

# 从SPI设备读取n字节
spi.readbytes(n)

# 将列表的数据写到SPI设备
spi.writebytes(list of value)

# 执行SPI传输。
spi.xfer(list of values[, speed_hz, delay_usec, bits_per_word])

示例

import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 7629

# Split an integer input into a two byte array to send via SPI
def write_pot(input):
msb = input >> 8
lsb = input & 0xFF
spi.xfer([msb, lsb])

# Repeatedly switch a MCP4151 digital pot off then on
while True:
write_pot(0x1FF)
time.sleep(0.5)
write_pot(0x00)
time.sleep(0.5)

SPI 速度值列表

Speed spi.max_speed_hz

value

125.0 MHz

125000000

62.5 MHz

62500000

31.2 MHz

31200000

15.6 MHz

15600000

7.8 MHz

7800000

3.9 MHz

3900000

1953 kHz

1953000

976 kHz

976000

488 kHz

488000

244 kHz

244000

122 kHz

122000

61 kHz

61000

30.5 kHz

30500

15.2 kHz

15200

7629 Hz

7629

文章参考:http://hfwudao.cn/a/raspberry-learn-26-SPI