SPI协议详解:从理论到实践
SPI协议详解:从理论到实践
1 前言
- 1 SPI(Serial Peripheral Interface)是 Motorola 公司提出的一种同步串行接口技术.
- 2 是一种高速(几十MHz)、全双工(同时发送和接收数据)、同步通信(主设备通过时钟控制传输)的总线.
- 3 只用四根信号线.
2 理论
2.1 SPI 的四条线
2.1.1 一对一 连接示意图
2.1.2 一对多 连接示意图
2.1.3 四条信号线的定义
信号线 方向 作用
SCLK(Serial Clock) 输出 主设备时钟
MOSI(Master Out, Slave In) 输出 主设备发数据,从设备收
MISO(Master In, Slave Out) 输入 从设备发数据给,主设备收
CS/SS(Chip Select/Slave Select) 输出 片选信号
2.2 SPI 的四种工作模式
从设备可能在出厂是就是配置为某种模式,所以我们需要选择相同的模式才能正常使用.
2.2.1 时钟极性(CPOL, Clock Polarity)
决定了 SCLK 在空闲状态时的电平
- 0=低电平
- 1=高电平
2.2.2 时钟相位(CPHA, Clock Phase)
决定了在 SCLK 哪个边沿采样
- 0=奇数
- 1=偶数
2.2.3 四种模式时序图
2.2.3.1 CPHA=0 时序图
2.2.3.1 CPHA=1 时序图
3 实践
参考野火f407霸天虎开发板 flash芯片为w25q128JV
3.1 引脚配置初始化
略
3.2 flash 指令与函数
// 状态寄存器
typedef struct {
uint8_t busy : 1; // 设备忙状态,1=正在擦除/写入,0=空闲
uint8_t wel : 1; // 写使能锁存 (WEL),只读,1=可写,0=不可写
uint8_t bp0 : 1; // 块保护位 (BP0)
uint8_t bp1 : 1; // 块保护位 (BP1)
uint8_t bp2 : 1; // 块保护位 (BP2)
uint8_t tb : 1; // 保护方向 (TB):0=顶部保护,1=底部保护
uint8_t sec : 1; // 扇区保护 (SEC),决定块保护单位:0=64KB,1=4KB
uint8_t srp : 1; // 状态寄存器保护位 (SRP)
} status_reg_1_t;
typedef struct {
uint8_t srl : 1; // 状态寄存器锁定 (SRL)
uint8_t qe : 1; // Quad Enable (QE) ,1=开启四通道SPI
uint8_t reserved : 1;
uint8_t lb1 : 1; // 安全锁定位 1 (LB1)
uint8_t lb2 : 1; // 安全锁定位 2 (LB2)
uint8_t lb3 : 1; // 安全锁定位 3 (LB3)
uint8_t cmp : 1; // 互补保护位 (CMP),0=TB 保护的部分不可写,1=TB 保护的部分可写
uint8_t sus : 1; // 擦除/编程挂起状态
} status_reg_2_t;
typedef struct {
uint8_t reserved : 1;
uint8_t reserved_1 : 1;
uint8_t wps : 1; // 写保护方案选择 (WPS)
uint8_t reserved_2 : 1;
uint8_t reserved_3 : 1;
uint8_t drv2 : 1; // 输出驱动强度控制 (DRV2)
uint8_t drv1 : 1; // 输出驱动强度控制 (DRV1)
uint8_t reserved_4 : 1;
} status_reg_3_t;
3.2.1 读取 spi 数据
- 全双工!!! 发送数据时才会同时接收数据.
- SPI_I2S_SendData 触发一次 SPI 时钟运行,此时数据发送了,同时数据也接收了.
- SPI_I2S_ReceiveData() 只是读取 SPI 数据寄存器,它不会触发 SPI 时钟.
- 所以在发送命令时接收到的数据没有实际作用.
- 要获取 flash 返回的数据,就要发送一个占位字节(Dummy Byte)来触发时钟.
3.2.2 打开写使能
3.2.3 等待 flash 空闲
3.2.4 擦除扇区
3.2.5 其他指令
注意写入数一次最多写入256字节,其他略
4 总结
- 4 根线
- 高速(几十兆)
- 全双工(同时收发)
- 同步(主设备控制时钟)
本文原文来自CSDN