在了解完I2C通信后,不免会接触到到SPI通信。而一开始,可能会觉得两者好似没什么区别。为什么要学SPI呢,I2C和SPI有什么区别呢。为此我详细展开说说。
1.什么是 SPI?
SPI,全称 Serial Peripheral Interface,中文翻译为串行外设接口,是一种 主从式、同步、全双工 的串行通信协议。
三个关键词:
主从式:一个主机控制多个从设备(主发起,从响应)
同步式:数据传输由时钟信号(SCK)控制同步
全双工:可以边发送边接收,MOSI/MISO 两条独立数据线
2.SPI 的 4 根基本信号线结构
名称 | 主机作用方向 | 描述 |
---|---|---|
SCK | 主机 → 从机 | 同步时钟线,主机输出时钟,控制数据采样节奏 |
MOSI | 主机 → 从机 | 主机输出、从机输入,主机发数据给从机 |
MISO | 从机 → 主机 | 从机输出、主机输入,从机回传数据给主机 |
CS | 主机 → 从机 | 片选信号(Chip Select),低电平有效,用来告诉从机"你被选中通信了" |
注意:
SCK、MOSI、CS 都是主机控制输出;
MISO 是主机读取输入;
SPI 是一种基于边沿的协议 ------ 数据变化和数据采样都是"在时钟跳变沿发生"。
3.SPI 是怎么工作的?(核心机制)

接下来我来对比 SPI 四种模式(Mode 0~3)的行为差异,包括:
CPOL(时钟空闲电平)
CPHA(数据采样边沿)
MOSI 数据什么时候改变
从机什么时候采样数据
这四种模式是 SPI 协议中最核心也最容易混淆的部分。我现在彻底讲明白它们的逻辑区别、时序差异、电平行为和通信节奏。
CPOL 与 CPHA 是什么含义?
CPOL:决定 SCK 在"空闲状态"的电平(即不传数据时 SCK 是高还是低)
CPOL = 0 → 空闲时 SCK = 低电平
CPOL = 1 → 空闲时 SCK = 高电平
CPHA:决定 在哪一个边沿采样数据
CPHA = 0 → 第一个边沿采样
CPHA = 1 → 第二个边沿采样
注意:这里是边沿,不是具体到上升沿还是下降沿,第一个边沿可能是上升沿也可能是下降沿。
第一个边沿 = 从空闲态开始的第一个跳变(比如 CPOL=0,SCK 从 0→1 是第一个边沿)
模式 | CPOL | CPHA | SCK 空闲状态 | 采样边沿 | 传输边沿(MOSI 改变时刻) |
---|---|---|---|---|---|
Mode 0 | 0 | 0 | 低电平 | 上升沿 | 下降沿 |
Mode 1 | 0 | 1 | 低电平 | 下降沿 | 上升沿 |
Mode 2 | 1 | 0 | 高电平 | 下降沿 | 上升沿 |
Mode 3 | 1 | 1 | 高电平 | 上升沿 | 下降沿 |
我以发送一个字节数据(0xA5 = 10100101)为例,分析 SPI 每一位是如何传输的。
Step by Step 时序过程( SPI Mode 0 )
通信准备阶段:
主机将 CS 拉低,激活目标从机(W25Q64)
数据准备完毕,等待时钟同步
第一位传输(发送 bit 7:1)
主机将 MOSI 设置为 1
主机将 SCK 从低拉高(上升沿)
从机在上升沿采样 MOSI 上的值(记录 bit7=1)
主机将 SCK 拉低,完成本位传输
第二位传输(bit6 = 0)
主机将 MOSI=0
SCK 上升沿
从机采样 0
SCK 下降沿结束
重复 8 次后,完整发送 1 字节
发送完后,主机将 CS 拉高,表示结束通信
若是读取数据,主机会在每一位 SCK 上升沿读 MISO 上的电平
SPI Mode 1(CPOL = 0,CPHA = 1)
空闲时 SCK 为低,采样在下降沿,数据改变在上升沿
通信准备阶段:
主机将 CS 拉低,激活目标从机(W25Q64)
SCK 处于空闲低电平(CPOL = 0)
数据准备完毕,等待时钟同步
第一位传输(发送 bit7 = 1)
主机将 SCK 拉高(上升沿)
主机将 MOSI 设置为 1
主机将 SCK 拉低(下降沿)
从机在 下降沿采样 MOSI 上的值(记录 bit7 = 1)
第二位传输(bit6 = 0)
主机将 SCK 拉高
主机将 MOSI 设置为 0
主机将 SCK 拉低
从机在下降沿采样 0
重复 8 次后,完整发送 1 字节
主机将 CS 拉高,表示通信结束
若是读取数据:
主机会在 每一位的 SCK 下降沿 读取 MISO 上的电平
SPI Mode 2(CPOL = 1,CPHA = 0)
空闲时 SCK 为高,采样在下降沿,数据改变在上升沿
通信准备阶段:
主机将 CS 拉低,激活目标从机
SCK 初始为高电平(CPOL = 1)
数据准备完毕,等待同步
第一位传输(bit7 = 1)
主机将 MOSI 设置为 1
主机将 SCK 从高拉低(下降沿)
从机在 下降沿采样 MOSI = 1
主机将 SCK 拉高(恢复空闲)
第二位传输(bit6 = 0)
主机将 MOSI = 0
主机将 SCK 拉低
从机采样 0
主机将 SCK 拉高
重复 8 次后,完整发送 1 字节
主机将 CS 拉高,结束通信
若是读取数据:
主机会在 每一位 SCK 下降沿 读取 MISO 电平
SPI Mode 3(CPOL = 1,CPHA = 1)
空闲时 SCK 为高,采样在上升沿**,数据改变在下降沿
通信准备阶段:
主机将 CS 拉低,激活从机
SCK 初始为高电平(CPOL = 1)
数据准备完毕,等待同步
第一位传输(bit7 = 1)
主机将 SCK 拉低
主机将 MOSI 设置为 1
主机将 SCK 从低拉高(上升沿)
从机在 上升沿采样 MOSI = 1
第二位传输(bit6 = 0)
主机将 SCK 拉低
主机将 MOSI 设置为 0
主机将 SCK 拉高
从机采样 0
重复 8 次后,完整发送 1 字节
主机将 CS 拉高,结束通信
若是读取数据:
主机会在 每一位 SCK 上升沿 读取 MISO 电平
W25Q64 是什么?
W25Q64 是一款 64M-bit(8MB)SPI NOR Flash 存储芯片,常用于存储配置文件、图片、数据日志等。它支持:
SPI Mode 0/3 接口
支持标准读、页写、扇区擦除等
支持写保护、掉电保护
多种容量(如 Q32、Q64、Q128)
W25Q64 内部结构概览
参数 | 数值 |
---|---|
总容量 | 64Mbit = 8MB |
页大小(Page) | 256 字节 |
扇区大小(Sector) | 4KB(16 页) |
块大小(Block) | 64KB |
地址范围 | 0x000000 ~ 0x7FFFFF |
写数据前必须先擦除所在页或扇区!否则写入无效。写数据前必须先擦除所在页或扇区!否则写入无效。
W25Q64 使用的 SPI 协议模式
默认使用 SPI Mode 0(CPOL = 0,CPHA = 0)
通信速率支持高达 80MHz(我们软件模拟约几十 KHz)
通信格式:主机发送 命令 + 地址 + 数据,从机响应结果或接收写入
4.举一个SPI读写W25Q64(软件)例子
从 STM32F103 使用 GPIO 模拟 SPI 信号,实现:
初始化 GPIO
与 W25Q64 通信(读ID、擦除扇区、写数据、读数据)
OLED 显示验证数据读写是否成功
通信的整体逻辑步骤(功能流程)
初始化 SPI 引脚(MySPI_Init)
启动 SPI 通信(CS 拉低,MySPI_Start)
发送命令(如读 ID,擦除、写数据)
可选:写入地址或数据内容
读取或写入数据
结束通信(CS 拉高,MySPI_Stop)
在 OLED 上显示通信结果
第一阶段:软件 SPI 的本质与引脚配置
SPI 是什么?
SPI 是一种同步串行通信协议,使用 4 根信号线:
CS:片选(低电平有效)
SCK:时钟,由主机控制
MOSI:主出从入,主机发给从机
MISO:主入从出,从机回应主机
在 Mode 0 模式下(CPOL=0,CPHA=0):
SCK 空闲为低电平
在 SCK 上升沿采样输入数据(MISO)
MOSI 数据必须在 SCK 上升沿前准备好
软件模拟 SPI 的基本操作函数
模拟 SPI 片选信号 CS(/SS)
cpp
void MySPI_W_SS(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
}
使用 PA4 模拟 SPI 的 CS(Chip Select)信号线
BitValue = 0 表示选中从机(W25Q64)
BitValue = 1 表示释放从机
W25Q64 是在 CS 低电平有效 时才响应 SPI 命令。这个函数用于 SPI 通信的开始与结束。
模拟时钟线 SCK
cpp
void MySPI_W_SCK(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_5, (BitAction)BitValue);
}
使用 PA5 模拟 SPI 的时钟线 SCK(Serial Clock)
SPI 模式 0 规定:空闲时为低电平,在 上升沿采样
模拟 MOSI 输出
cs
uint8_t MySPI_R_MISO(void)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6);
}
使用 PA7 作为 MOSI(主出从入)
STM32 控制这根线向 W25Q64 发送数据位(高位先发)
引脚初始化:MySPI_Init引脚初始化:
模拟读取 MISO(主入从出)
cpp
void MySPI_W_MOSI(uint8_t BitValue)
{
GPIO_WriteBit(GPIOA, GPIO_Pin_7, (BitAction)BitValue);
}
使用 PA6 作为 MISO,从 W25Q64 读取回来的每一位数据就在这里被读取。
读取的是从机在时钟上升沿送出的位电平。
cpp
// 1. 打开 GPIOA 的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 2. 配置 MOSI(PA7)、SCK(PA5)、CS(PA4)为推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 3. 配置 MISO(PA6)为上拉输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 4. 初始状态:SS = 1 表示未选中,SCK = 0 表示时钟空闲
MySPI_W_SS(1);
MySPI_W_SCK(0);
推挽能拉高/拉低,速度快,适合 SPI
SPI 通信控制函数
cpp
void MySPI_Start(void)
{
MySPI_W_SS(0); // 选中从机(CS 拉低)
}
void MySPI_Stop(void)
{
MySPI_W_SS(1); // 释放从机(CS 拉高)
}

第二阶段:模拟传输一个字节的过程(MySPI_SwapByte)
实现原理
SPI 每传输 1 个字节(8 位):
每一位数据在 MOSI 上输出(主机发)
在 SCK 上升沿让从机采样(主出)
同时主机也在上升沿读取 MISO(主入)
cpp
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{
uint8_t i, ByteReceive = 0x00;
for (i = 0; i < 8; i++)
{
// 第 i 位:先将 MOSI 输出(最高位先)
MySPI_W_MOSI(ByteSend & (0x80 >> i)); // 将第 i 位送到 MOSI
MySPI_W_SCK(1); // SCK 拉高(上升沿)
// 在上升沿采样 MISO 线,主机读取从机的回应位
if (MySPI_R_MISO() == 1) ByteReceive |= (0x80 >> i);
MySPI_W_SCK(0); // SCK 拉低,准备下一位
}
return ByteReceive;
}
初始化变量:i
为循环索引;ByteReceive
用来存储收到的数据。
例如 ByteSend = 0b10100001
第一次发送 bit7:ByteSend & 0x80 = 0x80
输出对应位电平到 MOSI
SPI Mode 0:从机在 SCK 上升沿采样数据
主机此时也应从 MISO 线上采样数据
若当前位为高电平,则置 ByteReceive 的对应位为 1
第三阶段:JEDEC ID 的读取过程(读取芯片型号)
第三阶段:JEDEC ID 的读取过程(读取芯片型号)
cpp
void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
{
MySPI_Start(); // CS = 0,激活 Flash
MySPI_SwapByte(0x9F); // 发送 JEDEC ID 指令
*MID = MySPI_SwapByte(0x00); // 接收厂商 ID(通常为 0xEF)
*DID = MySPI_SwapByte(0x00); // 高位 Device ID(如 0x40)
*DID <<= 8;
*DID |= MySPI_SwapByte(0x00); // 低位 Device ID(如 0x17)
MySPI_Stop(); // CS = 1,结束通信
}
每个字节都通过 MySPI_SwapByte() 传输,从机 MISO 返回对应 ID 信息。
第四阶段:擦除操作(扇区擦除)
写使能
cpp
void W25Q64_WriteEnable(void)
{
MySPI_Start();
MySPI_SwapByte(W25Q64_WRITE_ENABLE); // 0x06
MySPI_Stop();
}
所有写操作前必须执行该命令。否则写入失败。
等待芯片空闲
cpp
void W25Q64_WaitBusy(void)
{
uint32_t Timeout;
MySPI_Start();
MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1); // 0x05,读取状态寄存器
Timeout = 100000;
while ((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01) // bit0=WIP=1表示忙
{
Timeout --;
if (Timeout == 0) break;
}
MySPI_Stop();
}
为什么要擦除?
W25Q64 的 NOR Flash 写入特性:
不能直接改写为 0 → 1
必须先将 1 全部清零(擦除为 0xFF),才能写入
cpp
void W25Q64_SectorErase(uint32_t Address)
{
W25Q64_WriteEnable(); // 必须先写使能(WEL=1)
MySPI_Start(); // CS = 0
MySPI_SwapByte(0x20); // 发送擦除指令:Sector Erase
MySPI_SwapByte(addr >> 16); // 地址高8位
MySPI_SwapByte(addr >> 8); // 地址中8位
MySPI_SwapByte(addr); // 地址低8位
MySPI_Stop(); // CS = 1
W25Q64_WaitBusy(); // 等待擦除完成(最多100ms)
}
地址不需要对齐 0x000;芯片内部按地址所在扇区处理(每 4KB 为一个)
第五阶段:写入数据(页写)
写前必须:
写使能(0x06)
地址不要跨页(每页 256 字节)
cpp
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{
W25Q64_WriteEnable(); // 打开写使能(WEL=1)
MySPI_Start(); // 开始通信
MySPI_SwapByte(0x02); // Page Program 指令
MySPI_SwapByte(addr >> 16); // 地址高8位
MySPI_SwapByte(addr >> 8); // 地址中8位
MySPI_SwapByte(addr); // 地址低8位
for (i = 0; i < Count; i++)
{
MySPI_SwapByte(DataArray[i]); // 发送要写入的数据(MOSI)
}
MySPI_Stop(); // 结束通信
W25Q64_WaitBusy(); // 等待写入完成
}
第六阶段:读取数据(Read Data)
cpp
void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{
MySPI_Start();
MySPI_SwapByte(0x03); // Read Data 指令
MySPI_SwapByte(addr >> 16); // 地址高8位
MySPI_SwapByte(addr >> 8); // 中8位
MySPI_SwapByte(addr); // 低8位
for (i = 0; i < Count; i++)
{
DataArray[i] = MySPI_SwapByte(0x00); // 每读取一个字节,发一个 dummy byte
}
MySPI_Stop();
}
主机在 每个 SCK 上升沿读取 MISO,从机按地址返回数据。
5.指令函数
cpp
#ifndef __W25Q64_INS_H
#define __W25Q64_INS_H
#define W25Q64_WRITE_ENABLE 0x06
#define W25Q64_WRITE_DISABLE 0x04
#define W25Q64_READ_STATUS_REGISTER_1 0x05
#define W25Q64_READ_STATUS_REGISTER_2 0x35
#define W25Q64_WRITE_STATUS_REGISTER 0x01
#define W25Q64_PAGE_PROGRAM 0x02
#define W25Q64_QUAD_PAGE_PROGRAM 0x32
#define W25Q64_BLOCK_ERASE_64KB 0xD8
#define W25Q64_BLOCK_ERASE_32KB 0x52
#define W25Q64_SECTOR_ERASE_4KB 0x20
#define W25Q64_CHIP_ERASE 0xC7
#define W25Q64_ERASE_SUSPEND 0x75
#define W25Q64_ERASE_RESUME 0x7A
#define W25Q64_POWER_DOWN 0xB9
#define W25Q64_HIGH_PERFORMANCE_MODE 0xA3
#define W25Q64_CONTINUOUS_READ_MODE_RESET 0xFF
#define W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID 0xAB
#define W25Q64_MANUFACTURER_DEVICE_ID 0x90
#define W25Q64_READ_UNIQUE_ID 0x4B
#define W25Q64_JEDEC_ID 0x9F
#define W25Q64_READ_DATA 0x03
#define W25Q64_FAST_READ 0x0B
#define W25Q64_FAST_READ_DUAL_OUTPUT 0x3B
#define W25Q64_FAST_READ_DUAL_IO 0xBB
#define W25Q64_FAST_READ_QUAD_OUTPUT 0x6B
#define W25Q64_FAST_READ_QUAD_IO 0xEB
#define W25Q64_OCTAL_WORD_READ_QUAD_IO 0xE3
#define W25Q64_DUMMY_BYTE 0xFF
#endif
类别 | 宏定义 | 指令码 | 用途说明 |
---|---|---|---|
写控制 | W25Q64_WRITE_ENABLE |
0x06 |
使能写操作(写/擦前必须执行) |
W25Q64_WRITE_DISABLE |
0x04 |
禁止写操作,防止误写 | |
状态寄存器 | W25Q64_READ_STATUS_REGISTER_1 |
0x05 |
读取状态寄存器1(BUSY/写使能位) |
W25Q64_READ_STATUS_REGISTER_2 |
0x35 |
读取状态寄存器2(包含QE位) | |
W25Q64_WRITE_STATUS_REGISTER |
0x01 |
同时写SR1 和 SR2(共2字节) | |
写入操作 | W25Q64_PAGE_PROGRAM |
0x02 |
页编程(最多256字节) |
W25Q64_QUAD_PAGE_PROGRAM |
0x32 |
四线页编程(用于Quad SPI) | |
擦除操作 | W25Q64_SECTOR_ERASE_4KB |
0x20 |
擦除一个 4KB 扇区 |
W25Q64_BLOCK_ERASE_32KB |
0x52 |
擦除一个 32KB 块 | |
W25Q64_BLOCK_ERASE_64KB |
0xD8 |
擦除一个 64KB 块 | |
W25Q64_CHIP_ERASE |
0xC7 |
整片擦除(耗时较久) | |
W25Q64_ERASE_SUSPEND |
0x75 |
暂停擦除操作(用于多任务) | |
W25Q64_ERASE_RESUME |
0x7A |
恢复擦除操作 | |
电源管理 | W25Q64_POWER_DOWN |
0xB9 |
进入低功耗待机模式 |
W25Q64_RELEASE_POWER_DOWN_HPM_DEVICE_ID |
0xAB |
唤醒 + 读取设备ID | |
模式控制 | W25Q64_HIGH_PERFORMANCE_MODE |
0xA3 |
启用高性能模式(某些版本支持) |
W25Q64_CONTINUOUS_READ_MODE_RESET |
0xFF |
重置连续读模式 | |
识别ID | W25Q64_MANUFACTURER_DEVICE_ID |
0x90 |
读取制造商 + 设备ID(需发送地址) |
W25Q64_READ_UNIQUE_ID |
0x4B |
读取唯一芯片ID(64-bit) | |
W25Q64_JEDEC_ID |
0x9F |
JEDEC 标准ID(1字节厂商 + 2字节设备) | |
读取数据 | W25Q64_READ_DATA |
0x03 |
标准读取(低速,最兼容) |
W25Q64_FAST_READ |
0x0B |
快速读取(需发送 Dummy Byte) | |
W25Q64_FAST_READ_DUAL_OUTPUT |
0x3B |
双线输出快速读 | |
W25Q64_FAST_READ_DUAL_IO |
0xBB |
双线输入输出快速读 | |
W25Q64_FAST_READ_QUAD_OUTPUT |
0x6B |
四线输出快速读 | |
W25Q64_FAST_READ_QUAD_IO |
0xEB |
四线输入输出快速读 | |
W25Q64_OCTAL_WORD_READ_QUAD_IO |
0xE3 |
八线 32-bit 快速读取(部分芯片支持) | |
占位字节 | W25Q64_DUMMY_BYTE |
0xFF |
常用于读取时"填充"MOSI |
6.main函数
cpp
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "W25Q64.h"
uint8_t MID;
uint16_t DID;
uint8_t ArrayWrite[] = {0x01, 0x02, 0x03, 0x04};
uint8_t ArrayRead[4];
int main(void)
{
OLED_Init();
W25Q64_Init();
OLED_ShowString(1, 1, "MID: DID:");
OLED_ShowString(2, 1, "W:");
OLED_ShowString(3, 1, "R:");
W25Q64_ReadID(&MID, &DID);
OLED_ShowHexNum(1, 5, MID, 2);
OLED_ShowHexNum(1, 12, DID, 4);
W25Q64_SectorErase(0x000000);
W25Q64_PageProgram(0x000000, ArrayWrite, 4);
W25Q64_ReadData(0x000000, ArrayRead, 4);
OLED_ShowHexNum(2, 3, ArrayWrite[0], 2);
OLED_ShowHexNum(2, 6, ArrayWrite[1], 2);
OLED_ShowHexNum(2, 9, ArrayWrite[2], 2);
OLED_ShowHexNum(2, 12, ArrayWrite[3], 2);
OLED_ShowHexNum(3, 3, ArrayRead[0], 2);
OLED_ShowHexNum(3, 6, ArrayRead[1], 2);
OLED_ShowHexNum(3, 9, ArrayRead[2], 2);
OLED_ShowHexNum(3, 12, ArrayRead[3], 2);
while (1)
{
}
}
擦除第一个扇区(地址 0x000000 起始的 4KB)
NOR Flash 写入前必须擦除,否则无法从 0 改写为 1!(擦除后,所有数据位变为1)
7.SPI通信与I2C区别
对比项 | SPI(Serial Peripheral Interface) | I²C(Inter-Integrated Circuit) |
---|---|---|
通信方式 | 全双工,主从同步通信 | 半双工,主从同步通信 |
信号线数量 | 通常需要 4 根线:MISO, MOSI, SCLK, CS(每个从机单独 CS) | 只需 2 根线:SCL(时钟), SDA(数据) |
通信速率 | 较高,可达几十 Mbps | 较低,一般为 100kHz、400kHz,最多几 Mbps |
引脚数量 | 多(每个从机需独立 CS 引脚) | 少(多个从机共用总线) |
总线架构 | 一主多从,但每个从机需要独立片选 | 一主多从,多个从机可共享 2 根线 |
地址机制 | 无地址,主机用 CS 选中具体从机 | 有 7 位或 10 位设备地址 |
传输控制 | 主机控制时钟(SCLK)与片选 | 主机控制时钟(SCL),通过地址访问从机 |
数据方向 | MOSI、MISO 分别用于写入和读取(全双工) | SDA 单线收发数据(半双工) |
硬件成本 | 较高(线多,占用 GPIO 多) | 较低(线少,占用 GPIO 少) |
软件协议复杂度 | 简单,无握手或仲裁 | 较复杂,有起始/停止位、ACK/NACK、仲裁机制等 |
常见应用场景 | Flash、SD 卡、屏幕、W25Q64 等高速外设 | EEPROM、RTC、传感器、OLED、MPU6050 等低速外设 |
具体外设举例
外设 | 使用通信协议 | 原因简述 |
---|---|---|
W25Q64 | SPI | 高速读写需求,SPI 支持页写、块擦除等 |
MPU6050 | I²C | 内置 I²C 接口,低速传感器,节省引脚 |
OLED (SSD1306) | I²C 或 SPI | 小数据量,I²C 节省引脚,SPI 提高速度 |
SD 卡 | SPI | 大容量文件操作,SPI 高速全双工性能优越 |