13. SPI通信

您所在的位置:网站首页 通信设备板卡 13. SPI通信

13. SPI通信

2024-07-11 00:41| 来源: 网络整理| 查看: 265

13. SPI通信¶

本章通过讲解在应用层中使用SPI总线与外部设备的通讯,讲解Linux系统总线类型设备驱动架构的应用,它与上一章的I2C 总线操作方法非常相似,可以对比学习。

在Linux内核文档的Documentation/SPI目录下有关于SPI驱动非常详细的说明。

本章的示例代码目录为:base_linux/spi

13.1. SPI通讯协议简介¶

SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface),即串行外围设 备接口,是一种高速全双工的通信总线。它被广泛地使用在 ADC、 LCD 等设备与 MCU 间,要求通讯速率较高的场合 学习本章时,可与 I2C 章节对比阅读,体会两种通讯总线的差异。下面我们分别对 SPI 协议的物理层及协议层进行讲解。

13.1.1. SPI物理层¶

SPI通讯设备之间的常用连接方式见下图。

SPI通讯使用3条总线及片选线,3条总线分别为SCK、MOSI、MISO,片选线为 ,它们的作用介绍如下:

(1) ( Slave Select):从设备选择信号线,常称为片选信号 线,也称为NSS、CS,以下用NSS表示。当有多个SPI从设备与SPI主机相连时,设备的其它信 号线SCK、MOSI及MISO同时并联到相同的SPI总线上,即无论有多少个从设备,都共同只使用这3条总线;而每个从设备都有独立的这一条 NSS信号线,本信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号线。I2C协议中通过设备地址来寻址、选中总线上的某个设备并与其进行通讯;而SPI协议中没有设备地址,它使用NSS信号线来寻址,当主机要选择从设备时,把该从设备的NSS信号线设置为低电平,该从设备即被选中,即片选有效,接着主 机开始与被选中的从设备进行SPI通讯。所以SPI通讯以NSS线置低电平为开始信号,以NSS线被拉高作为结束信号。

(2) SCK (Serial Clock):时钟信号线,用于通讯数据同步。它由通讯主机产生,决定了通讯的速率,不同的 设备支持的最高时钟频率不一样,如RT1052的SPI时钟频率最大为fpclk/2,两个设备之 间通讯时,通讯速率受限于低速设备。

(3) MOSI (Master Output, Slave Input):主设备输出/从设备输入引脚。主机的 数据从这条信号线输出,从机由这条信号线读入主机发送的数据,即这条线上数据的方向为主机到从机。

(4) MISO(Master Input,,Slave Output):主设备输入/从设备输出引脚。主机从这条信号线读 入数据,从机的数据由这条信号线输出到主机,即在这条线上数据的方向为从机到主机。

13.1.2. 协议层¶

与I2C的类似,SPI协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节。

13.1.2.1. SPI基本通讯过程¶

先看看SPI通讯的通讯时序,如下图所示。

这是一个主机的通讯时序。NSS、SCK、MOSI信号都由主机控制产生,而MISO的信号由从机产生,主机通过该信号线读取从机的数据。MOSI与MISO的信号只在NSS为低电平的时候才有效,在SCK的每个时钟周期MOSI和MISO传输一位数据。

以上通讯流程中包含的各个信号分解如下:

13.1.2.2. 通讯的起始和停止信号¶

在上图中的标号处,NSS信号线由高变低,是SPI通讯的起始信号。NSS是每个从机各自独 占的信号线,当从机检在自己的NSS线检测到起始信号后,就知道自己被主机选中了,开始准备与主机 通讯。在图中的标号处,NSS信号由低变高,是SPI通讯的停止信号,表示本次通讯结束,从机的选中状态被取消。

13.1.2.3. 数据有效性¶

SPI使用MOSI及MISO信号线来传输数据,使用SCK信号线进行数据同步。MOSI及MISO数据线在SCK的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时,MSB 先行或LSB先行并没有作硬性规定,但要保证两个SPI通讯设备之间使用同样的协定,一般都会采用上图中的MSB先行模式。

观察图中的标号处,MOSI及MISO的数据在SCK的上升沿期间变化输出,在SCK的下降沿时被采样。即在SCK的下降沿时刻,MOSI及MISO的数据有效,高电平时表示数据“1”,为低电 平时表示数据“0”。在其它时刻,数据无效,MOSI及MISO为下一次表示数据做准备。

SPI每次数据传输可以8位或16位为单位,每次传输的单位数不受限制。

13.1.2.4. CPOL/CPHA及通讯模式¶

上面讲述的图中的时序只是SPI中的其中一种通讯模式,SPI一共有四种通讯 模式,它们的主要区别是总线空闲时SCK的时钟状态以及数据采样时刻。为方便说明,在此 引入“时钟极性CPOL”和“时钟相位CPHA”的概念。

时钟极性CPOL是指SPI通讯设备处于空闲状态时,SCK信号线的电平 信号(即SPI通讯开始前、 NSS线为高电平时SCK的状态)。CPOL=0时, SCK在空闲状态时 为低电平,CPOL=1时,则相反。

时钟相位CPHA是指数据的采样的时刻,当CPHA=0时,MOSI或MISO数据线上的信号 将会在SCK时钟线的“奇数边沿”被采样。当CPHA=1时,数据线在SCK的“偶数边沿”采样。

如下图:

我们来分析这个CPHA=0的时序图。首先,根据SCK在空闲状态时的电平,分为两种情况。SCK信号线在空闲状态为低电平时,CPOL=0;空闲状态为高电平时,CPOL=1。

无论CPOL=0还是=1,因为我们配置的时钟相位CPHA=0,在图中可以看到,采样时刻都是在SCK的奇数边沿。注意当CPOL=0的时候,时钟的奇数边沿是上升沿,而CPOL=1的时候,时钟的奇数边沿是下降沿。所以SPI的采样时刻不是由上升/下降沿决定的。MOSI和MISO数据线的有效信号在SCK的奇数 边沿保持不变,数据信号将在SCK奇数边沿时被采样,在非采样时刻,MOSI和MISO的有效信号才发生切换。

类似地,当CPHA=1时,不受CPOL的影响,数据信号在SCK的偶数边沿被采样。

如下图:

由CPOL及CPHA的不同状态,SPI分成了四种模式,见下表,主机与 从机需要工作在相同的模式下才可以正常通讯,实际中采用较多的是“模式0”与“模式3”。

表 SPI的四种模式

SPI模式

CPOL

CPHA

空闲时SCK时钟

采样时刻

0

0

0

低电平

奇数边沿

1

0

1

低电平

偶数边沿

2

1

0

高电平

奇数边沿

3

1

1

高电平

偶数边沿

13.1.3. 扩展SPI协议(Single/Dual/Quad/Octal SPI)¶

以上介绍的是经典SPI协议的内容,这种也被称为标准SPI协议(Standard SPI)或单 线SPI协议(Single SPI),其中的单线是指该SPI协议中使用单根数据线MOSI进行发送数据,单根数据线MISO进行接收数据。

为了适应更高速率的通讯需求,半导体厂商扩展SPI协议,主要发展出了Dual/Quad/Octal SPI协议,加上 标准SPI协议(Single SPI),这四种协议的主要区别是数据线的数量及通讯方式,具体见下表。

表 四种SPI协议的区别

协议

数据线数量及功能

通讯方式

Single SPI(标准SPI)

1根发送,1根接收

全双工

Dual SPI(双线SPI)

收发共用2根数据线

半双工

Quad SPI(四线SPI)

收发共用4根数据线

半双工

Octal SPI(八线SPI)

收发共用8根数据线

半双工

扩展的三种SPI协议都是半双工的通讯方式,也就是说它们的数据线是分时进行收发 数据的。例如,标准SPI(Single SPI)与双线SPI(Dual SPI)都是两根数据线,但 标准SPI(Single SPI)的其中一根数据线只用来发送,另一根数据线只用来接收,即全双工;而双线SPI(Dual SPI)的两根线都具有收发功能,但在同一时刻只能是发送或者是接收,即半 双工,四线SPI(Quad SPI)和 八线SPI(Octal SPI)与双线SPI(Dual SPI)类似,只是数据线量的区别。

13.1.3.1. SDR和DDR模式¶

扩展的SPI协议还增加了SDR模式(单倍速率Single Data Rate)和DDR模式(双倍速率Double Data Rate)。例如在标准SPI协议的SDR模式下,只在SCK的单边沿进行数据传输,即一个SCK时钟只传输一位数据;而在它的DDR模式下,会在SCK的上升沿和下降沿都进行数据传输,即一个SCK时钟能传输两位数据,传输速率提高一倍。

13.2. SPI相关数据结构与ioctl函数¶

编写应用程序需要使用到spi_ioc_transfer结构体,如下所示

linux/spi/spidev.h¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15struct spi_ioc_transfer { __u64 tx_buf; //发送数据缓存 __u64 rx_buf; //接收数据缓存 __u32 len; //数据长度 __u32 speed_hz; //通讯速率 __u16 delay_usecs; //两个spi_ioc_transfer之间的延时,微秒 __u8 bits_per_word; //数据长度 __u8 cs_change; //取消选中片选 __u8 tx_nbits; //单次数据宽度(多数据线模式) __u8 rx_nbits; //单次数据宽度(多数据线模式) __u16 pad; };

在编写应用程序时还需要使用ioctl函数设置spi相关配置,其函数原型如下

1 2 3 #include int ioctl(int fd, unsigned long request, ...);

其中对于终端request的值常用的有以下几种

SPI_IOC_RD_MODE32

设置读取SPI模式(对应上文的SPI的四种模式的表格,SPI_MODE_x)

SPI_IOC_WR_MODE32

设置写入SPI模式(对应上文的SPI的四种模式的表格,SPI_MODE_x)

SPI_IOC_RD_LSB_FIRST

设置SPI读取数据模式(LSB先行返回1)

SPI_IOC_WR_LSB_FIRST

设置SPI写入数据模式。(0:MSB,非0:LSB)

SPI_IOC_RD_BITS_PER_WORD

设置SPI读取设备的字长

SPI_IOC_WR_BITS_PER_WORD

设置SPI写入设备的字长

SPI_IOC_RD_MAX_SPEED_HZ

设置读取SPI设备的最大通信频率。

SPI_IOC_WR_MAX_SPEED_HZ

设置写入SPI设备的最大通信速率

SPI_IOC_MESSAGE(N)

一次进行双向/多次读写操作

提示

SPI的读取和写入可以设置为不同的参数。

13.3. LubanCat板卡spi接口¶

本章主要围绕带有40Pin引脚的LubanCat-RK系列的板子,如下

LubanCat-Zero W

LubanCat-Zero N

LubanCat-1

LubanCat-1N

LubanCat-2

LubanCat-2N

LubanCat-4

40pin引脚中只有一组spi接口SCK,MOSI,MISO,有两个默认片选信号CS0,CS1

其中SPI3的引脚关系如下表所示

SPI

物理引脚

功能

MOSI

19

主设备输出/从设备输入

MISO

21

主设备输入/从设备输出

CLOCK

23

时钟信号线

CS0

24

片选信号线0

CS1

26

片选信号线1

LubanCat0-2系列使用spi3。spidev3.0控制CS0,spidev3.1控制CS1

LubanCat4使用spi0。spidev0.0控制CS0,spidev0.1控制CS1

如下图:

对应实物的40pin接口

13.3.1. 使能SPI通信接口¶

SPI接口在默认情况是关闭状态的,需要使能才能使用, 如果要开启spi需要配置两项,一个是spi通信引脚,一个是spi-cs引脚

13.3.1.1. 方法一¶ 1 2 3 4 5#进入工具配置 sudo fire-config #移动光标到下图的位置 #按确认键进入配置

打开SPI通信接口和SPI片选接口

使用方向键移动光标到 SPI

按 “空格键” 选中SPI(出现 “*” ),如下图

使用方向键移动光标到 SPI-CS

按 “空格键” 选中SPI-CS(出现 “*” ),如下图

按 “确认键” 进行设置

按 “Esc键” 退出到终端,运行 sudo reboot 进行重启应用

13.3.1.2. 方法二¶ LubanCat各设备的配置文件¶

板子名称

配置文件名称

说明

当前使用的板卡

uEnv.txt

系统会自动把板卡的配置文件链接到该文件

LubanCat-RK

uEnvLubanCat-series.txt

通用板卡的配置文件,用于第一次启动配置系统

Lubancat-Zero-N

uEnvLubanCatZN.txt

适用于EBF410068 EBF410068V1

Lubancat-Zero-W

uEnvLubanCatZW.txt

适用于EBF410067 EBF410067V1

Lubancat-1

uEnvLubanCat1.txt

适用于EBF410077 EBF410077V1 EBF410077V2

Lubancat-1N

uEnvLubanCat1N.txt

适用于EBF410052 EBF410052V1

Lubancat-1金手指/BTB

uEnvLubanCat1IO.txt

适用于EBF410090 EBF410132

Lubancat-2

uEnvLubanCat2.txt

适用于EBF410044

Lubancat-2V1

uEnvLubanCat2-V1.txt

适用于EBF410044V1

Lubancat-2V2

uEnvLubanCat2-V2.txt

适用于EBF410044V2

Lubancat-2-n

uEnvLubanCat2N.txt

适用于EBF410076 EBF410076V1

Lubancat-2金手指/BTB

uEnvLubanCat2IO.txt

适用于EBF410298 EBF410297

Lubancat-4

uEnvLubanCat4.txt

适用于EBF410116

可以通过打开 /boot/uEnv/board.txt (board是你所用的板子的名称),一般第一次启动已经初始化将板级uEnv.txt软连接到了/boot/uEnv/uEnv.txt,可以直接修改该文件。

查看是否启用了spi相关设备设备树插件。

编辑文件,将带有 spi 和 spi-cs 的两行的注释符号去掉 如下图:

然后重启激活设备

注解

如果是直接拔电源的方式重启,会有可能出现文件没能做出修改 (原因:文件未能及时从内存同步到存储设备中,解决方法,在终端上输入 “sync” 再拔电关机)

13.3.2. 检查SPI设备¶

使能spi设备树插件之后重新启动板卡,通过SPI设备文件来判断spi驱动是否加载成功。 SPI_3对应的设备文件是spidev3.0和spidev3.1

如下所示

1 2 3root@lubancat:~# ls /dev/spi* /dev/spidev3.0 /dev/spidev3.1 root@lubancat:~#

spidev3.0和spidev3.1的区别在于片选信号的不同,spidev3.0使用CS0 , spidev3.1使用CS1

13.4. SPI回环通讯测试实验¶ 13.4.1. 硬件连接:¶

只需要将SPI3的 MIOS与MOSI引脚(板卡上的19和21)使用跳线帽短接即可。

如下图所示

13.4.2. 编写程序¶ base_linux/spi/spi_selftest/spi_selftest.c¶ 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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88#include #include #include #include #include #include #include #include #include #define SPI_DEV_PATH "/dev/spidev3.0" /*SPI 接收 、发送 缓冲区*/ unsigned char tx_buffer[100] = "hello the world !"; unsigned char rx_buffer[100]; int fd; // SPI 控制引脚的设备文件描述符 static unsigned mode = SPI_MODE_2; //用于保存 SPI 工作模式 static uint8_t bits = 8; // 接收、发送数据位数 static uint32_t speed = 10000000; // 发送速度 static uint16_t delay; //保存延时时间 void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len) { int ret; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, .len = len, .delay_usecs = delay, .speed_hz = speed, .bits_per_word = bits, .tx_nbits = 1, .rx_nbits = 1 }; ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3