SPI通信协议深度解析

描述

SPI通信协议深度解析:信号引脚、CLK行为与测量指南

一、SPI信号引脚详解

SPI(Serial Peripheral Interface)是一种全双工同步串行通信协议,广泛应用于嵌入式系统。其核心信号引脚包括:

SPI

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 测量连接方法

SPI

3.3 测量参数解读

参数 典型值 测量要点
CLK频率 1-50MHz 确认是否达到标称值
建立时间 >10ns 数据在时钟边沿前的稳定时间
保持时间 >5ns 数据在时钟边沿后的稳定时间
上升/下降时间 <10ns 信号边沿质量
占空比 45-55% 时钟对称性

四、常见问题排查

4.1 CLK无波形的情况分析

SPI

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 使用逻辑分析仪解码

SPI

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 多从设备连接方式

SPI

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信号测量技能,是嵌入式开发工程师的核心竞争力之一。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分