Raspberry Pi SPI 通信读出 255?别急,MISO 浮空是元凶!
你有没有遇到过这样的情况:树莓派通过 SPI 读取传感器数据,代码写得严丝合缝,编译运行也毫无报错,但每次 read 出来的值都是 255(0xFF) ?无论你怎么重试、换线、重启,结果始终如一——仿佛芯片在跟你开玩笑。
这并不是玄学问题,而是嵌入式开发中一个极为典型且高频出现的硬件级'沉默故障'。本文将带你从 信号物理层到 Linux 驱动机制 ,层层剥开这个现象背后的真相,并提供一套可立即上手的排查流程和解决方案。我们以 C++ 环境下使用 spidev 访问 /dev/spidev0.0 为例,深入剖析为何会'读出 255',以及如何系统性地解决它。
为什么总是读出 255?一句话说透本质
当你从 SPI 总线上读出一串 0xFF 时,真正的含义是:MISO 线没有被任何设备驱动——它处于高阻态,被上拉电阻拉到了高电平。
在数字电路中:
- 每一位为 1 → 高电平(3.3V)
- 8 位全为 1 →
11111111=0xFF= 十进制 255
所以,'读出 255'不是程序错了,也不是内核 bug,而是 你的树莓派'听不到'从设备的声音 。
接下来我们要问的是:为什么会听不到?
先看协议:SPI 是怎么工作的?
SPI 虽然是四线制接口,看似简单,实则对硬件连接和配置要求非常严格。它的四根关键信号线分别是:
| 信号 | 方向 | 说明 |
|---|---|---|
| SCLK | 主 → 从 | 同步时钟,由主设备生成 |
| MOSI | 主 → 从 | 主发从收数据 |
| MISO | 从 → 主 | 从发主收数据(重点!) |
| CS | 主 → 从 | 片选信号,低电平有效 |
通信流程如下:
- 主机拉低 CS,选中目标从设备;
- 在 SCLK 的每个边沿,主机发送一位(MOSI),同时采样从机返回的一位(MISO);
- 完成 N 个时钟周期后,主机拉高 CS,结束传输。
注意: SPI 本身不带地址或 ACK 机制 ,谁响应完全取决于 CS 是否有效 + 从设备是否准备好输出数据。
一旦中间任何一个环节断掉——比如片选没拉低、从设备未供电、模式不匹配——MISO 就会变成'无人说话的麦克风',默认被上拉为高电平,于是你读到的就是一连串的 0xFF 。
spidev 是什么?我们是如何读 SPI 的?
在 Linux 系统中,Raspberry Pi 的 SPI 接口通过 spidev 驱动暴露给用户空间。你可以像操作文件一样打开 /dev/spidevX.Y 节点进行读写。
例如:
/dev/spidev0.0 → SPI 控制器 0,片选 0
/dev/spidev0.1 → SPI 控制器 0,片选 1
虽然可以用 read() / write() 做基本操作,但真正可靠的方式是使用 一次性提交完整的传输请求。

