STM32
直播中

小麦地

11年用户 1638经验值
私信 关注
[问答]

一文读懂串行外设接口SPI

串行外设接口SPI是什么?其有哪些部分组成呢?
如何对串行外设接口SPI进行初始化呢?





回帖(1)

刘阳

2021-12-16 09:46:31
9 SPI

(1)介绍

串行外设接口SPI,是一种同步串行外设接口,允许MCU与外围设备进行全双工同步串行通信。
SPI总线是三线制,采用主从模式架构,支持一个或多个Slave设备,由于设计简单,性能优良,又不牵扯专利问题,被广泛使用。SPI可以配置为支持SPI协议或者支持IIS音频协议。SPI默认工作在SPI模式,可以软件切换为IIS模式,在小容量和中容量设备上,不支持IIS音频协议。
IIS音频协议也是一种3引脚的同步串行接口通信协议,它支持四种音频标准,包括飞利浦IIS协议,MSB和LSB对齐标准,以及PCM标准。
(2)SPI的组成

SPI只需要四根线:
1.SCk(串行时钟线):作为主设备的输出,从设备的输入
2.MISO(主机/从机输出数据线):该引脚在从模式下发送数据,在主模式下接收数据。
3.MOSI(主机输出/从机输入数据线):该引脚在主模式下发送数据,在从模式下接收数据。
4.NSS(低电平有效的从机选择线):它是一个可选的引脚,用来选择主/从设备。





(3)库函数

SPI_Init
















(4)示例


#include "spi.h"
//以下是 SPI 模块的初始化代码,配置成主机模式,访问 SD Card/W25Q128/NRF24L01
//SPI 口初始化
//这里针是对 SPI2 的初始化
void SPI2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//PORTB 时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE );//①SPI2 时钟使能
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB13/14/15 复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure); //①初始化 GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15); //PB13/14/15 上拉
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置 SPI 全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置 SPI 工作模式:设置为主 SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 8 位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//选择了串行时钟的稳态:时钟悬空高
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //数据捕获于第二个时钟沿
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信号由硬件管理
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //预分频 256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从 MSB 位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC 值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure); //②根据指定的参数初始化外设 SPIx 寄存器
SPI_Cmd(SPI2, ENABLE); //③使能 SPI 外设
SPI2_ReadWriteByte(0xff); //④启动传输
}
//SPI 速度设置函数
//SpeedSet://SPI_BaudRatePrescaler_256 256 分频 (SPI 281.25K@sys 72M)
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));
SPI2->CR1&=0XFFC7;
SPI2->CR1|=SPI_BaudRatePrescaler; //设置 SPI2 速度
SPI_Cmd(SPI2,ENABLE);
}
//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI2_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //等待发送区空
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI2, TxData); //通过外设 SPIx 发送一个数据
retry=0;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //等待接收
//完一个 byte
{ retry++;
if(retry>200)return 0; }
return SPI_I2S_ReceiveData(SPI2); //返回通过 SPIx 最近接收的数据
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分