一、SPI通信基础与四种模式解析
SPI(Serial Peripheral Interface)是一种高速全双工同步串行通信协议,广泛应用于微控制器与外设之间的数据传输。其核心特性由时钟极性(CPOL)和时钟相位(CPHA)决定,衍生出四种通信模式。
1.1 SPI四种模式原理
- CPOL(Clock Polarity):定义时钟线(SCK)的空闲状态。
- CPOL=0:空闲时SCK为低电平
- CPOL=1:空闲时SCK为高电平
- CPHA(Clock Phase):定义数据采样的时钟边沿。
- CPHA=0:数据在第一个时钟边沿(上升沿或下降沿,取决于CPOL)采样
- CPHA=1:数据在第二个时钟边沿采样
四种组合构成SPI的四种模式:
模式 | CPOL | CPHA | 时钟特征 | 数据采样边沿 |
---|---|---|---|---|
0 | 0 | 0 | 空闲低 | 第一个上升沿 |
1 | 0 | 1 | 空闲低 | 第二个下降沿 |
2 | 1 | 0 | 空闲高 | 第一个下降沿 |
3 | 1 | 1 | 空闲高 | 第二个上升沿 |
1.2 时序波形示意图
图片来源(软件模拟SPI接口程序代码(4种模式))
- 模式0:SCK空闲低电平,数据在第一个上升沿采样
- 模式1:SCK空闲低电平,数据在第二个下降沿采样
- 模式2:SCK空闲高电平,数据在第一个下降沿采样
- 模式3:SCK空闲高电平,数据在第二个上升沿采样
二、SPI驱动模块接口设计
以下是模块的核心接口分类与说明:
2.1 时钟与复位接口
信号名 | 方向 | 说明 |
---|---|---|
clk_sys | 输入 | 系统时钟(建议SPI速率的2倍以上) |
rst_n | 输入 | 低电平复位 |
2.2 配置参数接口
信号名 | 方向 | 说明 |
---|---|---|
baud_en | 输入 | 波特率使能(单周期高脉冲,用于时钟分频) |
msb_en | 输入 | 高位优先使能(1=MSB先传) |
cpol | 输入 | 时钟极性配置(0/1) |
cpha | 输入 | 时钟相位配置(0/1) |
2.3 数据读写接口
信号名 | 方向 | 说明 |
---|---|---|
user_wr_en | 输入 | 用户写使能 |
user_cmd[2:0] | 输入 | 控制命令(bit0:启动 bit1:停止 bit2:读(0)/ 写) |
user_wr_data[7:0] | 输入 | 写入数据 |
user_rd_data[7:0] | 输出 | 读取数据 |
user_rd_data_valid | 输出 | 读数据有效标志 |
drv_done | 输出 | 传输完成标志 (单周期脉冲) |
2.4 SPI物理接口
信号名 | 方向 | 说明 |
---|---|---|
spi_csn | 输出 | 片选信号(低有效) |
spi_sck | 输出 | 时钟信号 |
spi_sdi | 输入 | 串行数据输入 |
spi_sdo | 输出 | 串行数据输出 |
三、模块功能架构与工作流程
3.1 状态机控制
localparam IDLE = 2'b00;
localparam START = 2'b01;
localparam WR_DATA = 2'b11;
localparam END = 2'b10;
- IDLE:空闲状态,等待传输指令
- START:发送起始信号(拉低片选)
- WR_DATA:数据传输阶段
- END:传输结束(拉高片选)
3.2 数据处理流程
-
数据锁存:
if(msb_en == 1'b1) latch_data <= {user_cmd,user_wr_data[0],...user_wr_data[7]}; else latch_data <= {user_cmd,user_wr_data};
- 根据MSB/LSB模式选择数据排列顺序
-
时钟生成:
if(c_state == WR_DATA) spi_sck <= ~spi_sck; else spi_sck <= cpol;
- 根据当前状态和CPOL生成时钟信号
-
数据移位:
if(msb_en == 1'b1) rd_shift <= {rd_shift[6:0],spi_sdi}; else rd_shift <= {spi_sdi,rd_shift[7:1]};
- 支持高位优先或低位优先的数据接收
四、关键信号时序分析
-
传输使能时序:
- user_wr_en拉高触发数据锁存
- baud_en控制数据传输速率
-
状态转移逻辑:
case(c_state) IDLE: if(start_req && baud_en) next_state; START: if(baud_en) go to WR_DATA; WR_DATA: if(wr_cnt==15) go to END; END: if(baud_en) go to IDLE; endcase
-
数据有效性验证:
if((latch_data[10] == 1'b1) && (wr_cnt == 15)) rd_shift_valid <= 1'b1;
五、应用场景
- 典型应用场景:
- 传感器数据采集(如加速度计、陀螺仪)
- 存储设备控制(Flash、EEPROM)
- 显示驱动(OLED/LCD控制器)
六、总结
本文通过Verilog代码实现了一个可配置的SPI主机驱动模块,详细解析了SPI四种模式的工作原理,并通过模块化设计实现了灵活的数据传输控制。该设计适用于多种嵌入式系统场景,通过调整配置参数即可适配不同外设需求。
扩展阅读建议:
- 《Verilog数字系统设计教程》
- SPI协议官方规范文档
- 嵌入式系统中的时序优化技术