SPI通信协议深度解析:信号引脚、CLK行为与测量指南
一、SPI信号引脚详解
SPI(Serial Peripheral Interface)是一种全双工同步串行通信协议,广泛应用于嵌入式系统。其核心信号引脚包括:
1.1 核心信号线
| 信号名称 | 方向 | 全称 | 功能 |
|---|---|---|---|
| SCLK | 主→从 | Serial Clock | 时钟信号,由主设备产生 |
| MOSI | 主→从 | Master Out Slave In | 主设备输出数据 |
| MISO | 从→主 | Master In Slave Out | 从设备输出数据 |
| CS/SS | 主→从 | Chip Select/Slave Select | 片选信号,使能从设备 |
1.2 可选信号
| 信号名称 | 用途 | 说明 |
|---|---|---|
| INT | 从→主 | 中断请求 |
| RESET | 主→从 | 复位信号 |
二、CLK信号行为特性分析
2.1 CLK的产生机制
在SPI通信中,SCLK信号完全由主设备控制。根据Linux内核SPI子系统的实现(如drivers/spi/spi.c):
// 内核SPI传输核心函数
static int spi_transfer_one_message(struct spi_controller *ctlr,
struct spi_message *msg)
{
// 1. 激活片选
cs_assert(ctlr, msg->spi);
// 2. 生成时钟信号
ctlr->prepare_transfer_hardware(ctlr);
// 3. 执行数据传输
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
// 产生CLK脉冲
ctlr->transfer_one(ctlr, msg->spi, xfer);
}
// 4. 停止时钟
ctlr->unprepare_transfer_hardware(ctlr);
// 5. 释放片选
cs_deassert(ctlr, msg->spi);
}
2.2 CLK波形特征
CLK信号的行为受以下因素影响:
- 时钟极性(CPOL):
- CPOL=0:空闲时低电平
- CPOL=1:空闲时高电平
- 时钟相位(CPHA):
- CPHA=0:数据在第一个时钟边沿采样
- CPHA=1:数据在第二个时钟边沿采样
graph LR
A[CPOL/CPHA组合] --> B[模式0:CPOL=0, CPHA=0]
A --> C[模式1:CPOL=0, CPHA=1]
A --> D[模式2:CPOL=1, CPHA=0]
A --> E[模式3:CPOL=1, CPHA=1]
2.3 CLK激活时机
根据用户提供的代码分析(SES_PORT_SPIDEV_interface.c):
// SPI传输触发点
if (ioctl(spiLinkDescription_g[intfHandle].spiDev,
SPI_IOC_MESSAGE(1),
&message) >= 0)
{
// 传输成功
}
关键结论:
- CLK只在
ioctl()执行期间产生 - 数据传输完成后,CLK立即停止
- 即使是从设备数据读取,也需要主设备发起传输并提供CLK
三、SPI信号测量指南
3.1 测量设备要求
| 设备 | 推荐型号 | 关键参数 |
|---|---|---|
| 示波器 | Rigol DS1054Z | 4通道,50MHz+ |
| 探头 | PP215 | 10:1衰减比 |
| 逻辑分析仪 | Saleae Logic Pro 16 | 16通道,100MS/s |
3.2 测量连接方法
3.3 测量参数解读
| 参数 | 典型值 | 测量要点 |
|---|---|---|
| CLK频率 | 1-50MHz | 确认是否达到标称值 |
| 建立时间 | >10ns | 数据在时钟边沿前的稳定时间 |
| 保持时间 | >5ns | 数据在时钟边沿后的稳定时间 |
| 上升/下降时间 | <10ns | 信号边沿质量 |
| 占空比 | 45-55% | 时钟对称性 |
四、常见问题排查
4.1 CLK无波形的情况分析
4.2 典型故障解决方案
- CLK持续输出:
- 检查SPI控制器是否处于连续传输模式
- 验证片选信号是否保持激活状态
- CLK频率不稳定:
# 在Linux中检查时钟源
cat /sys/kernel/debug/clk/clk_summary | grep spi
- 数据与CLK不同步:
- 调整CPOL/CPHA设置
- 增加建立/保持时间裕量
五、SPI驱动开发实践
5.1 内核SPI框架结构
// SPI设备注册
struct spi_board_info my_spi_dev = {
.modalias = "my_device",
.max_speed_hz = 10000000,
.bus_num = 0,
.chip_select = 1,
.mode = SPI_MODE_0,
};
spi_register_board_info(&my_spi_dev, 1);
// 驱动实现
static struct spi_driver my_spi_driver = {
.driver = {
.name = "my_device",
},
.probe = my_probe,
.remove = my_remove,
};
module_spi_driver(my_spi_driver);
5.2 用户空间spidev使用
// 配置SPI模式
ioctl(fd, SPI_IOC_WR_MODE, &mode);
// 设置位顺序
ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb);
// 执行传输
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,
};
ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
六、高级测量技巧
6.1 使用逻辑分析仪解码
6.2 信号完整性优化
- 阻抗匹配:
- 串联匹配电阻:22-100Ω
- 终端匹配:在接收端并联100Ω电阻
- PCB布线规则:
- SCLK与MOSI/MISO等长布线
- 避免平行走线超过信号波长1/20
- 参考地平面完整
- 噪声抑制:
// 软件滤波
for (int i = 0; i < 3; i++) {
value = read_adc();
if (abs(value - last) < threshold) break;
}
七、SPI协议变体
7.1 多从设备连接方式
7.2 半双工模式
// 配置为3线模式
ioctl(fd, SPI_IOC_WR_MODE, SPI_3WIRE);
// 方向切换
gpio_set_value(direction_pin, TX_MODE);
spi_write(...);
gpio_set_value(direction_pin, RX_MODE);
spi_read(...);
八、总结与最佳实践
8.1 SPI使用黄金法则
- CLK由主控产生:从设备永远不能主动产生时钟
- 通信必须成对:每次传输都需要主设备发起
- 空闲状态保持:传输结束后CLK保持CPOL定义的电平
- 片选管理严格:CS信号必须在传输前有效,传输后无效
8.2 调试检查清单
- CLK信号是否在预期时间出现
- CPOL/CPHA设置是否匹配从设备要求
- 片选信号是否在传输间隙正确释放
- 信号电压是否符合器件要求
- 建立/保持时间是否满足时序要求
完整测量案例:GitHub-SPI-Signal-Analysis
包含示波器截图、逻辑分析仪配置和参考驱动代码
最后建议:当SPI通信出现问题时,首先测量CLK信号行为。通过确认CLK是否在预期时间出现、频率是否正确、占空比是否合规,可以快速定位80%以上的通信故障。掌握SPI信号测量技能,是嵌入式开发工程师的核心竞争力之一。
1万+

被折叠的 条评论
为什么被折叠?



