STM32的SPI和IIC


提示:以下是本篇文章正文内容,下面案例可供参考

一、SPI介绍

1.SPI简介

SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议。STM32 也有 SPI 接口。下面我们看看 SPI 的内部简明图
在这里插入图片描述

SPI 接口一般使用 4 条线通信:
MISO 主设备数据输入,从设备数据输出。
MOSI 主设备数据输出,从设备数据输入。
SCLK时钟信号,由主设备产生。
CS 从设备片选信号,由主设备控制。

从图中可以看出,主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器写入一个字节来发起一次传输。寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的移位寄存器中的内容通过 MISO 信号线返回给主机。这样,两个移位寄存器中的内容就被交换。外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。

SPI 总线四种工作方式 SPI 模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置,时钟极性(CPOL)对传输协议没有重大的影响。如果CPOL=0,串行同步时钟的空闲状态为低电平;如果 CPOL=1,串行同步时钟的空闲状态为高电
平。时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果CPHA=0,在串行同步时钟的第一个跳变沿(上升或下降)数据被采样;如果 CPHA=1,在串行同步时钟的第二个跳变沿(上升或下降)数据被采样。SPI 主模块和与之通信的外设备时钟相位和极性应该一致。不同时钟相位下的总线数据传输时序如下图所示:
在这里插入图片描述

2.SPI主要特点

● 3线全双工同步传输
● 带或不带第三根双向数据线的双线单工同步传输
● 8或16位传输帧格式选择
● 主或从操作
● 支持多主模式
● 8个主模式波特率预分频系数(最大为fPCLK/2)
● 从模式频率 (最大为fPCLK/2)
● 主模式和从模式的快速通信
● 主模式和从模式下均可以由软件或硬件进行NSS管理:主/从操作模式的动态改变
● 可编程的时钟极性和相位
● 可编程的数据顺序,MSB在前或LSB在前
● 可触发中断的专用发送和接收标志
● SPI总线忙状态标志
● 支持可靠通信的硬件CRC
─ 在发送模式下,CRC值可以被作为最后一个字节发送
─ 在全双工模式中对接收到的最后一个字节自动进行CRC校验
● 可触发中断的主模式故障、过载以及CRC错误标志
● 支持DMA功能的1字节发送和接收缓冲器:产生发送和接受请求

3.SPI中断

在这里插入图片描述

4.STM32中SPI配置方法

配置相关引脚的复用功能,使能 SPI2 时钟

我们要用 SPI2,第一步就要使能 SPI2 的时钟。其次要设置 SPI2 的相关引脚为复用输出,这样才会连接到 SPI2 上否则这些 IO 口还是默认的状态,也就是标准输入输出口。这里我们使
用的是 PB13、14、15 这 3 个(SCK.、MISO、MOSI,CS 使用软件管理方式),所以设置这三个为复用 IO。

GPIO_InitTypeDef GPIO_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

类似的时钟使能和 IO 初始化这里不做详细介绍。

初始化 SPI2,设置 SPI2 工作模式

接下来我们要初始化 SPI2,设置 SPI2 为主机模式,设置数据格式为 8 位,然设置 SCK 时钟极性及采样方式。并设置 SPI2 的时钟频率(最大 18Mhz),以及数据的格式(MSB 在前还是LSB 在前)。这在库函数中是通过 SPI_Init 函数来实现的。

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)

跟其他外设初始化一样,第一个参数是 SPI 标号,这里我们是使用的 SPI2。下面我们来看看第二个参数结构体类型 SPI_InitTypeDef 的定义:

typedef struct
{
   
   
 uint16_t SPI_Direction;
 uint16_t SPI_Mode; 
 uint16_t SPI_DataSize; 
 uint16_t SPI_CPOL; 
 uint16_t SPI_CPHA; 
 uint16_t SPI_NSS; 
 uint16_t SPI_BaudRatePrescaler; 
 uint16_t SPI_FirstBit; 
 uint16_t SPI_CRCPolynomial; 
}SPI_InitTypeDef;

结构体成员变量比较多,这里我们挑取几个重要的成员变量讲解一下:
第一个参数 SPI_Direction 是用来设置 SPI 的通信方式,可以选择为半双工,全双工,以及串行发和串行收方式,这里我们选择全双工SPI_Direction_2Lines_FullDuplex
第二个参数 SPI_Mode 用来设置 SPI 的主从模式,这里我们设置为主机模式 SPI_Mode_Master,当然有需要你也可以选择为从机模式 SPI_Mode_Slave
第三个参数 SPI_DataSiz 为 8 位还是 16 位帧格式选择项,这里我们是 8 位传输,选择SPI_DataSize_8b
第四个参数 SPI_CPOL 用来设置时钟极性,我们设置串行同步时钟的空闲状态为高电平所以我们选择 SPI_CPOL_High
第五个参数 SPI_CPHA 用来设置时钟相位,也就是选择在串行同步时钟的第几个跳变沿(上升或下降)数据被采样,可以为第一个或者第二个条边沿采集,这里我们选择第二个跳变沿,所以选择 SPI_CPHA_2Edge
第六个参数 SPI_NSS 设置 NSS 信号由硬件(NSS 管脚)还是软件控制,这里我们通过软件控制 NSS 关键,而不是硬件自动控制,所以选择 SPI_NSS_Soft
第七个参数 SPI_BaudRatePrescaler 很关键,就是设置 SPI 波特率预分频值也就是决定 SPI 的时钟的参数,从不分频道 256 分频 8 个可选值,初始化的时候我们选择 256 分频值SPI_BaudRatePrescaler_256, 传输速度为36M/256=140.625KHz。
第八个参数 SPI_FirstBit 设置数据传输顺序是 MSB 位在前还是 LSB 位在前,,这里我们选择SPI_FirstBit_MSB 高位在前。
第九个参数 SPI_CRCPolynomial 是用来设置 CRC 校验多项式,提高通信可靠性,大于 1 即可。
设置好上面 9 个参数,我们就可以初始化 SPI 外设了。初始化的范例格式为:

SPI_InitTypeDef SPI_InitStructure;
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主 SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // SPI 发送接收 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 寄存器

使能 SPI2

初始化完成之后接下来是要使能 SPI2 通信了,在使能 SPI2 之后,我们就可以开始 SPI 通讯了。使能 SPI2 的方法是:

SPI_Cmd(SPI2, ENABLE); //使能 SPI 外设

SPI 传输数据

通信接口当然需要有发送数据和接受数据的函数,固件库提供的发送数据函数原型为:

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)

这个函数很好理解,往 SPIx 数据寄存器写入数据 Data,从而实现发送。
固件库提供的接受数据函数原型为:

uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)

这个函数也不难理解,从 SPIx 数据寄存器读出接受到的数据。

查看 SPI 传输状态

在 SPI 传输过程中,我们经常要判断数据是否传输完成,发送区是否为空等等状态,这是通过函数 SPI_I2S_GetFlagStatus 实现的,这个函数很简单就不详细讲解,判断发送是否完成的方法是:

SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE)

二、IIC介绍

1.IIC简介

IIC(Inter-Integrated Circuit)其实是IICBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。I²C的正确读法为“I平方C”(“I-squared-C”),而“I二C”(“I-two-C”)则是另一种错误但被广泛使用的读法。自2006年10月1日起,使用I²C协议已经不需要支付专利费,但制造商仍然需要付费以获取I²C从属设备地址。

I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。

开始信号:SCL 为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的 IC在接收到 8bit 数据后,向发送数据的 IC 发出特定的低电平脉冲,表示已收到数据。

CPU 向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。

这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。IIC 总线时序图如下图所示:
在这里插入图片描述

2.IIC主要特点

● 并行总线/I2C总线协议转换器
● 多主机功能:该模块既可做主设备也可做从设备
● I2C主设备功能
─ 产生时钟
─ 产生起始和停止信号
● I2C从设备功能
─ 可编程的I2C地址检测
─ 可响应2个从地址的双地址能力
─ 停止位检测
● 产生和检测7位/10位地址和广播呼叫
● 支持不同的通讯速度
─ 标准速度(高达100 kHz)
─ 快速(高达400 kHz)
● 状态标志:
─ 发送器/接收器模式标志
─ 字节发送结束标志
─ I2C总线忙标志
● 错误标志
─ 主模式时的仲裁丢失
─ 地址/数据传输后的应答(ACK)错误
─ 检测到错位的起始或停止条件
─ 禁止拉长时钟功能时的上溢或下溢
● 2个中断向量
─ 1个中断用于地址/数据通讯成功
─ 1个中断用于错误
● 可选的拉长时钟功能
● 具单字节缓冲器的DMA
● 可配置的PEC(信息包错误检测)的产生或校验:
─ 发送模式中PEC值可以作为最后一个字节传输
─ 用于最后一个接收字节的PEC错误校验
● 兼容SMBus 2.0
─ 25 ms时钟低超时延时
─ 10 ms主设备累积时钟低扩展时间
─ 25 ms从设备累积时钟低扩展时间
─ 带ACK控制的硬件PEC产生/校验
─ 支持地址分辨协议(ARP)
● 兼容SMBus

3.IIC中断

下表列出了所有的I2C中断请求:
在这里插入图片描述

4.STM32中IIC配置方法

起始信号

void IIC_Start(void)
{
   
   
	SDA_OUT();
	SDA_H;   							//串行数据线高电平(空闲信号)
	CLK_H;   							//串行时钟线高电平(空闲信号)
	Delay_us(5);
	SDA_L;   							//串行数据线拉出下降沿
	Delay_us(5);
	CLK_L;   							//串行时钟线拉出下降沿
}

终止信号

void IIC_Stop(void)
{
   
   
	SDA_OUT();					//输出模式
	CLK_L;							//串行时钟线低电平
	SDA_L;							//串行数据线低电平
	CLK_H;							//串行时钟线高电平
	Delay_us(5);
	SDA_H;							//串行数据线高电平  上升沿
	Delay_us(5);
}

三、SPI驱动OLED

主函数

int main(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值