问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

SPI总线通信协议入门:原理、优缺点及STM32实现

创作时间:
作者:
@小白创作中心

SPI总线通信协议入门:原理、优缺点及STM32实现

引用
CSDN
1.
https://m.blog.csdn.net/2301_81431262/article/details/145714060

SPI(Serial Peripheral Interface)是一种全双工、同步、主从式的通信协议,由摩托罗拉公司设计。它的核心特点是速度快、硬件简单,常用于单片机与传感器、存储器、显示屏等外设的通信。

一、SPI是什么?

SPI是一种全双工、同步、主从式的通信协议,由摩托罗拉公司设计。它的核心特点是速度快、硬件简单,常用于单片机与传感器、存储器、显示屏等外设的通信。

关键特点:

  • 全双工:数据可以同时发送和接收(类似打电话,双方能同时说话)。
  • 同步:通信双方依赖时钟信号(SCK)同步数据传输节奏。
  • 主从结构:一个主设备(如单片机)控制通信,多个从设备(如传感器)响应。

二、SPI如何工作?

SPI通信需要4根线(部分情况下可简化到3根),每一根线都有明确的任务:

线名
全称
作用
SCK
Serial Clock
主设备发出的时钟信号,控制传输节奏
MOSI
Master Out Slave In
主设备发送数据,从设备接收数据
MISO
Master In Slave Out
从设备发送数据,主设备接收数据
CS/SS
Chip Select
主设备选择要通信的从设备(低电平有效)

工作原理图解(文字描述版):

假设主设备要和某个从设备通信:

  1. 主设备拉低从设备的CS引脚(相当于点名:“嘿,我要和你说话了!”)。
  2. 主设备生成时钟信号SCK,像节拍器一样控制数据传输速度。
  3. 数据同时通过MOSI和MISI传输:
  • 主设备通过MOSI发送数据到从设备。
  • 从设备通过MISO回复数据给主设备。
  1. 通信结束后,主设备拉高CS引脚(结束对话)。

三、SPI的优缺点

优点:

  1. 速度快:SPI的时钟频率可达数十MHz(比I2C快得多)。
  2. 全双工:同时收发数据,效率高。
  3. 硬件简单:无需复杂的地址或应答机制。

缺点:

  1. 需要更多引脚:每增加一个从设备,需多一根CS线(可通过菊花链优化)。
  2. 无错误检测:SPI协议本身没有校验机制,需软件实现。
  3. 无寻址功能:依赖硬件片选(CS)选择从设备。

四、SPI的应用场景

SPI适合对速度要求高、设备数量少的场景,例如:

  • 连接传感器(如温度传感器、陀螺仪)。
  • 驱动显示屏(如OLED、TFT屏幕)。
  • 读写存储器(如Flash、EEPROM)。

五、软件模拟SPI通信(STM32f103c8t6标准库版)

void SPI_W_SS(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB, GPIO_Pin_12,(BitAction)BitValue);
}
void MySPI_W_MOSI(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB, GPIO_Pin_15,(BitAction)BitValue);
}
void MySPI_W_SCK(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB, GPIO_Pin_13,(BitAction)BitValue);
}
uint8_t MySPI_R_MISO(void)
{
    return GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14);
}
void SPI_Init(void)
{
    //开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    //配置io口(输出引脚为推挽输出,输入引脚为浮空输入或上拉输入)
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//配置MISO
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//配置MOSI
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//配置SCK
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//配置CS
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    //SPI模式0初始化引脚
    SPI_W_SS(1);//默认不选择从机
    SPI_W_SCK(0);// 模式0默认SCK为低电平
}
//SPI起始信号
void SPI_Start(void)
{
    SPI_W_SS(0);
}
//SPI终止信号
void SPI_Stop(void)
{
    SPI_W_SS(1);
}
//模式0软件模拟SPI
//SPI交换一个字节
//方法一
//优点:保留原来的参数
//缺点:效率慢
uint8_t SPI_SwapByte(uint8_t ByteSend)
{
    uint8_t i;
    uint8_t ByteRecevie = 0x00;//用来读取从机交换过来的数据
    //在SS下降沿后移出数据
    for(i = 0;i<8;i++)
    {
        SPI_W_MOSI(ByteSend & (0x80>>i));//SPI高位先行,移出最高位
        SPI_W_SCK(1);//上升沿后移入数据
        if(SPI_R_MISO()==1)
        {
            ByteRecevie |= (0x80>>i);//移入到最高位
        }
        SPI_W_SCK(0);//下降沿后移出数据
    }
    return ByteRecevie;
}
//方法二
//优点:效率快
//缺点:改变了原来的参数
uint8_t SPI_SwapByte_better(uint8_t ByteSend)
{
    uint8_t i;
    //在SS下降沿后移出数据
    for(i = 0;i<8;i++)//移动8次
    {
        SPI_W_MOSI(ByteSend & 0x80);//SPI高位先行,移出最高位
        ByteSend <<= 1;//左移一位,低位补零
        SPI_W_SCK(1);//上升沿后移入数据
        if(SPI_R_MISO()==1)
        {
            ByteSend |= 0x01;//移入的数据放最低位
        }
        SPI_W_SCK(0);//下降沿后移出数据
    }
    return ByteSend;
}

六、常见问题答疑

1. 如何连接多个从设备?

  • 方案1:每个从设备单独用一根CS线。
  • 方案2:使用菊花链(Daisy Chain)结构,但需要从设备支持。

2. SPI的时钟模式(CPOL和CPHA)是什么?

  • CPOL(时钟极性):决定SCK空闲时的电平(0=低电平,1=高电平)。
  • CPHA(时钟相位):决定数据在时钟的哪个边沿采样(0=第一个边沿,1=第二个边沿)。

不同设备可能要求不同的模式,需查阅数据手册!

七、结语

SPI是一个简单、高效的通信协议,掌握它的核心要点只需记住:

  1. 四根线:SCK、MOSI、MISO、CS。
  2. 主从结构,全双工同步通信。
  3. 需要硬件片选。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号