『7x24小时有问必答』
SPI是嵌入式开发中最常见的高速通信协议,广泛应用于Flash存储、显示屏、传感器等外设。本文系统讲解SPI协议基础、子系统架构、驱动开发实战和调试技巧,帮你快速掌握SPI驱动开发。

一、SPI协议基础

️ SPI四线制

SCLKMOSIMISOCS/SS
时钟信号(主机产生)
主机输出

从机输入
主机输入

从机输出
片选信号

(低电平有效)
全双工 vs I2C:SPI支持全双工通信(同时发送和接收),而I2C是半双工。这是SPI速度更高的原因之一。

SPI四种模式

模式
CPOL
CPHA
说明
Mode 0
0
0
空闲低,第一边沿采样
Mode 1
0
1
空闲低,第二边沿采样
Mode 2
1
0
空闲高,第一边沿采样
Mode 3
1
1
空闲高,第二边沿采样

二、SPI子系统架构

️ 核心架构

spi_master主机控制器
→
SPI核心层

管理调度
→
spi_device

spi_driver

从设备+驱动

核心数据结构

// SPI主机

struct  spi_master {

struct  device dev;

u16  bus_num;                     // 总线编号

u16  num_chipselect;           // 片选数量

u32  max_speed_hz;              // 最大时钟

int  (*transfer_one)(struct  spi_master*,  struct  spi_device*,  struct  spi_transfer*);

};

// SPI设备

struct  spi_device {

struct  spi_master *master;

u32  max_speed_hz;

u8  chip_select;

u16  mode;

};

// SPI传输

struct  spi_transfer {

const void  *tx_buf;      // 发送缓冲

void  *rx_buf;      // 接收缓冲

unsigned  len;

u32  speed_hz;

};

三、设备树配置

&spi0  {

      status =  
"okay";

/* SPI Flash */

spi_flash:flash@0  {

            compatible =  
"jedec,spi-nor";

            reg = <
0>;                              // 片选0

            spi-max-frequency = <50000000>;  // 50MHz

      };

/* OLED显示屏 */

oled@1  {

            compatible =  
"solomon,ssd1306";

            reg = <
1>;

            spi-max-frequency = <
10000000>;

      };

};

四、SPI传输API

常用API速查

API函数
说明
spi_write(spi, buf, len)
单次发送
spi_read(spi, buf, len)
单次接收
spi_sync(spi, message)
同步传输消息
spi_async(spi, message)
异步传输消息

五、SPI驱动开发实战

SPI Flash驱动框架

/* 读取Flash ID */

static int  spi_flash_read_id(struct  spi_device *spi)

{

u8  tx_buf[1] = {  0x9F  };

u8  rx_buf[3];

return  spi_write_then_read(spi, tx_buf,  1, rx_buf,  3);

}

/* probe函数 */

static int  spi_flash_probe(struct  spi_device *spi)

{

      data = devm_kzalloc(&spi->dev,  
sizeof(*data), GFP_KERNEL);

      data->spi = spi;

      spi_set_drvdata(spi, data);

      spi_flash_read_id(data);

return0;

}

/* 驱动注册 */

static struct  spi_driver spi_flash_driver = {

      .probe   = spi_flash_probe,

      .remove = spi_flash_remove,

      .driver = {

            .name =  
"spi_flash",

            .of_match_table = spi_flash_of_match,

      },

};

module_spi_driver(spi_flash_driver);

六、调试技巧

️ 用户空间调试

# 安装工具

apt install spidev-tools

# 查看SPI设备

ls /dev/spidev*

# 传输测试

spidev_test -D /dev/spidev0.0 -v

内核调试

# 查看SPI设备

ls /sys/bus/spi/devices/

# 查看SPI驱动

ls /sys/bus/spi/drivers/

# 查看内核日志

dmesg | grep -i spi

七、SPI vs I2C对比

特性
SPI
I2C
通信方式
全双工
半双工
速度
高(MHz级)
低(KHz级)
线数
4线
2线
多从机
需要多个CS
地址寻址
适用场景
Flash、显示屏
传感器、EEPROM

八、核心要点总结

<b> SPI核心要点:
四线制:SCLK、MOSI、MISO、CS
四种模式:CPOL+CPHA组合决定采样边沿
核心API:spi_write/spi_read/spi_sync/spi_async
设备树:spi-max-frequency设置时钟频率
</b>

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码