第6章 Linux SPI开发
6.1 SPI协议介绍
SPI(Serial Peripheral Interface,串行外设接口)是由摩托罗拉(Motorola)在1980前后提出的一种全双工同步串行通信接口,它用于MCU与各种外围设备以串行方式进行通信以交换信息,通信速度最高可达25MHz以上。
SPI接口主要应用在EEPROM、FLASH、实时时钟、网络控制器、OLED显示驱动器、AD转换器,数字信号处理器、数字信号解码器等设备之间。
SPI通常由四条线组成,一条主设备输出与从设备输入(Master Output Slave Input,MOSI),一条主设备输入与从设备输出(Master Input Slave Output,MISO),一条时钟信号(Serial Clock,SCLK),一条从设备使能选择(Chip Select,CS)。假设现在主控芯片要传输一个0x56数据给SPI Flash,时序如下:
首先拉低CS0选中SPI Flash,0x56的二进制就是0b0101 0110,因此在每个SCK时钟周期,DO输出对应的电平。SPI Flash 会在每个时钟周期的上升沿读取D0上的电平。
SPI和I2C对比如下表所示。SPI可以同时发出和接收数据,因此SPI的理论传输速度比I2C更快。SPI通过片选引脚选择从机,一个片选一个从机,因此在多从机结构中,需要占用较多引脚,而I2C通过设备地址选择从机,只要设备地址不冲突,始终只需要两个引脚。
6.1.1 SPI的物理拓扑结构
SPI可以一个主机连接单个或多个从机,每个从机都使用一个引脚进行片选,物理连接示意图如图所示:
6.1.2 SPI的数据交互
在SCK时钟周期的驱动下,主机把数据驱动到MOSI上传给从机,从机把数据驱动到MISO上传给主机,如下图所示。
主机发送N字节给从机时,必定能接收到N字节,至于接收到的N字节是否有意义由从机决定。如果主机只想对从机进行写操作,主机只需忽略接收的从机数据即可。如果主机只想读取从机数据,它也要发送数据给从机(发送的数据可以是空数据)。
6.1.3 SPI的数据传输模式
SPI有四种传输模式,如下表所示,主要差别在于CPOL和CPHA的不同。
⚫ CPOL(Clock Polarity,时钟极性)表示SCK在空闲时为高电平还是低电平。当CPOL=0,SCK空闲时为低电平,当CPOL=1,SCK空闲时为高电平。
⚫ CPHA(Clock Phase,时钟相位)表示SCK在第几个时钟边缘采样数据。当CPHA=0,在SCK第一个边沿采样数据,当CPHA=1,在SCK第二个边沿采样数据。
SPI 模式 | CPOL | CPHA | 说明 |
θ | θ | θ | 时钟空闲状态为低电平;在时钟第一个边沿(上升沿)采样数据 |
1 | θ | 1 | 时钟空闲状态为低电平;在时钟第二个边沿(下降沿)采样数据 |
2 | 1 | θ | 时钟空闲状态为高电平;在时钟第一个边沿(下降沿)采样数据 |
3 | 1 | 1 | 时钟空闲状态为高电平;在时钟第二个边沿(上升沿)采样数据 |
如下图所示,CPHA=0时,表示在时钟第一个时钟边沿采样数据。当CPOL=1,即空闲时为高电平,从高电平变为低电平,第一个时钟边沿(下降沿)即进行采样。当CPOL=0,即空闲时为低电平,从低电平变为高电平,第一个时钟边沿(上升沿)即进行采样。
⚫ CPHA=1时,表示在时钟第二个时钟边沿采样数据。
⚫ 当CPOL=1,即空闲时为高电平,从高电平变为低电平再变为高电平,第二个时钟边沿(上升沿)即进行采样。
⚫ 当CPOL=0,即空闲时为低电平,从低电平变为高电平再变为低电平,第二个时钟边沿(下降沿)即进行采样,如图所示:
6.2 Linux SPI设备的两种访问方法
应用程序怎么访问SPI设备?有两种方法:
① 使用驱动程序:SPI设备有对应的驱动程序,应用程序根据这个驱动程序的规范,使用普通的open/read/write等接口函数即可。
② 使用用户态接口:没有为SPI设备编写驱动程序时,应用程序根据芯片规范,直接操作SPI Controller的驱动程序进行数据收发。
要理解这两种方式,先看如下图的结构:
① SPI Device1接入SPI控制器1,SPI Device2接入SPI控制器2。
② 对于SPI Device1,有对应的驱动程序“Device1 Driver”。
③ 对于SPI Device2,没有对应的驱动程序。
④ 对于SPI控制器1、SPI控制器2,有一个驱动“spidev.c”,它把控制器的接口暴露给用户。
访问SPI Device1有两种方法:
① APP1通过“Device1 driver”访问:这个驱动封装好了芯片内部操作细节,用户无需查看芯片手册。
② APP2通过“spidev_fdx.c”的库函数进而调用“spidev.c”驱动来操作“控制器1”:用户需要查看芯片手册,才能知道收发什么数据才能操作设备。
为了访问“I2C Deivce2”,只有1种方法:APP2通过“spidev_fdx.c”的库函数进而调用“spidev.c”驱动来操作“控制器2”:用户需要查看芯片RemiPiSoftware Development Manual手册,才能知道收发什么数据才能操作设备。
APP2通过“spidev_fdx.c”的库函数访问SPI 设备时,也需要指定:使用哪个SPI控制器?使用哪个片选引脚?这通过设备树来指定,它会导致spidev.c驱动程序生成诸如“/dev/spidevB.D”的设备节点。B表示总线号,D表示它是这个SPI Master下第几个设备(对应第几个片选引脚)。
如您在使用瑞萨MCU/MPU产品中有任何问题,可识别下方二维码或复制网址到浏览器中打开,进入瑞萨技术论坛寻找答案或获取在线技术支持。
https://community-ja.renesas.com/zh/forums-groups/mcu-mpu/
未完待续
推荐阅读
RS485应用编程&USB串口编程 - RZ MPU工业控制教程连载(7)
Linux串口应用编程 - RZ MPU工业控制教程连载(6)
赢瑞米派 | 瑞萨RZ/G通用MPU研讨会火热报名中