1. SPI协议基础:从起源到全双工通信

各位同学,咱们今天正式开始聊SPI。说实话,SPI这个协议在嵌入式领域太常见了,几乎每个工程师都会用到。但真正把它吃透的人,我觉得并不多。

先说说SPI的起源。上世纪80年代,Motorola公司推出了一款叫MC68HC11的微控制器。当时他们需要一种简单、高速的串行通信方式,用来连接外设芯片。于是SPI(Serial Peripheral Interface)就诞生了。我最早接触SPI是在做一款工业传感器采集板的时候,那时候刚入行,看着四根线一头雾水——怎么四根线就能实现全双工通信?后来才明白,这设计其实非常巧妙。

1.1 四线制功能详解

SPI总线一共就四根信号线,咱们一个一个说清楚。

信号线 全称 方向 功能
SCLK Serial Clock 主机→从机 时钟信号,由主机产生,决定通信速率
MOSI Master Out Slave In 主机→从机 主机发送数据给从机
MISO Master In Slave Out 从机→主机 从机发送数据给主机
CS Chip Select 主机→从机 片选信号,低电平有效,选中对应从机

这里有个关键点:SCLK永远由主机控制。从机只能被动接收时钟,不能主动产生。我在项目中遇到过有人把从机也接了晶振,以为能自己产生时钟——结果通信完全乱套。记住,SPI是主从架构,时钟主权在主机手里。

核心要点:MOSI和MISO是两条独立的数据线,这是SPI能实现全双工通信的物理基础。不像I2C只有一根数据线,半双工来回切换。

1.2 全双工通信原理

全双工,说白了就是同时收发。SPI怎么做到的?

你看,MOSI和MISO是两条独立的物理线路。主机通过MOSI发数据给从机的同时,从机也能通过MISO发数据给主机。这两件事在同一个时钟周期内完成,互不干扰。

具体工作机制是这样的:

  1. 主机拉低CS,选中从机
  2. 主机产生SCLK时钟,每个时钟周期传输1位数据
  3. 在时钟的某个边沿,主机通过MOSI发送1位,从机通过MISO发送1位
  4. 在另一个边沿,双方采样对方发送的数据
  5. 8个时钟周期后,完成1字节的交换

我刚开始做SPI驱动时,总以为主机发一个字节,从机才会回一个字节。后来调试一个AD转换器才发现——SPI的收发是同时发生的。你发0x55的同时,从机也在发数据给你。如果你只关心发送,那接收到的数据就丢了。

实战技巧:很多SPI从机要求主机先发送一个命令字节,然后从机才会返回数据。这时候你发送命令字节时,接收到的数据是无效的;发送完命令后,再发送一个"哑字节"(通常是0x00或0xFF),才能读到真正的数据。这个哑字节就是用来产生时钟的。

1.3 SPI通信的时序基础

SPI的时序其实不复杂,但有两个参数特别重要:时钟极性(CPOL)和时钟相位(CPHA)。咱们先简单提一下,后面会有专门章节详细讲。

  • CPOL:决定SCLK空闲时的电平。CPOL=0时空闲为低,CPOL=1时空闲为高。
  • CPHA:决定数据在哪个时钟边沿采样。CPHA=0时在第一个边沿采样,CPHA=1时在第二个边沿采样。

这两个参数组合起来,就是SPI的四种模式。我见过不少工程师在这上面栽跟头——从机手册上写的是Mode 0,主机配置成了Mode 3,结果数据全是错的。

避坑指南:我曾经调试一款MEMS加速度计,死活读不到正确的ID寄存器。折腾了两天,最后发现是CPHA配反了。从机要求CPHA=1,我默认配成了CPHA=0。所以拿到一个新器件,第一件事就是看数据手册里的时序图,确认CPOL和CPHA。

1.4 SPI知识体系总览

下面这张图把SPI协议的核心知识点串起来了。你想想看,从物理层到应用层,SPI其实就这几个关键点。

SPI协议知识体系 SPI总线协议 物理层:四线制 数据链路:全双工 时序层:CPOL/CPHA 应用层:多设备级联 SCLK 时钟线 MOSI 主机输出 MISO 从机输出 CS 片选信号 同时收发不冲突 移位寄存器交换 MSB/LSB 优先 CPOL=0/1 空闲电平 CPHA=0/1 采样边沿 4种模式组合 独立CS多设备 菊花链级联 速率匹配 SPI协议从物理层到应用层,层层递进,每一层都有坑

嗯,这张图把SPI的知识结构理清楚了。咱们这门课会按照这个脉络,一层一层往下挖。物理层搞明白四根线怎么接,数据链路层搞明白全双工怎么玩,时序层搞明白CPOL/CPHA怎么配,应用层搞明白多设备怎么级联。

我个人觉得,SPI最迷人的地方就是它简单但灵活。四根线,没有复杂的协议栈,没有地址仲裁,想怎么用就怎么用。但也正因为灵活,才容易出问题。后面的章节,咱们会一个一个坑踩过去。