STM32F4-I²C,SPI

I²C

I²C总线是一种两线式串行总线,用于连接微控制器及其外围设备。它是由数据线 SDA 和时钟 SCL 构成的串行总线,可发送和接收数据。在 CPU 与被控 IC 之间、 IC 与 IC 之间进行双向传送, 高速 IIC 总线一般可达 400kbps 以上。I²C是半双工通信方式。

I²C 总线在传送数据过程中的三种类型信号:

开始信号:

SCL 为高电平时, SDA 由高电平向低电平跳变,开始传送数据。起始信号是种电平跳变时序信号,而不是一个电平信号。

结束信号:

SCL 为高电平时, SDA 由低电平向高电平跳变,结束传送数据。停止信号也是种电平跳变时序信号,而不是一个电平信号。


应答信号:

接收数据端在接收到 8bit 数据后,向发送数据端发出特定的低电平脉冲,表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况判断是否继续传递信号。若未收到应答信号,由判断为受控单元出现故障。

如下图:发送端Transmitter,每发送完一个字节(8bit位),就在时钟脉冲9期间释放数据线,由接收端receiver反馈一个返回的应答信号。

应答信号为低电平时,规定为有效应答位(ACK简称应答位)表示接收端已经成功地接收了该字节。应答信号为高电平时,规定为非应答位(NACK),一般表示接收端接收该字节没有成功。

反馈有效应答位ACK的要求:接收端在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间为稳定的低电平。如果接收端是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送端结束数据发送,并释放SDA线,(由主控端接收被控端发送转成主控端发送被控端接收)。(因为I²C是半双工通信,因此要一方释放SDA线,另一方才能控制SDA线发送。)

I²C空闲状态

I²C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

数据有效性:

I²C总线进行数据传送时,时钟信号SCL为高电平期间,数据线SDA上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的电平状态才允许变化。即:数据在SCL的上升沿到来之前就需准备好。并在在下降沿到来之前必须稳定。(高位先行)

数据的传送:

在I²C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发(时钟边沿变化触发)。

I²C支持总线挂载多设备(一主多从,多主多从)。

设备的SCL,SDA均要配置成开漏输出模式。

多主机的I²C总线系统结构:一般情况下SDA和SCL都会上拉到VCC(拉高),上拉电阻4.7kΩ左右。

主机有对SCL线的完全控制,从机不允许控制SCL时钟线。在空闲状态下,主机可以主动发起对SDA的控制,只有在从机发送数据和发送应答ACK的时候,主机才会转交SDA给从机。

一些常见常用的I²C通信协议的模块:

MPU6050:陀螺仪模块;4针脚OLED模块;AT24C02存储器模块;DS3231实时时钟模块。

STM32自带I²C不稳定,可软件模拟实I²C通信。

EEPROM全称“电可擦除可编程只读存储器”

典型芯片24C02,256个字节2048个位,接口:I²C。

I²C通信引脚:SCL,SDA。

写保护:WP。

电源和地:VCC,GND。

地址线:A0,A1,A2

A2=A1=A0=0。读的时候:Device Address=0xA1,前四位固定,A2,A1,A0三个位设置为0,R/W位置1为读此设备,置0为写此设备。写的时候Device Address=0xA0。

 

24C02字节写时序:指定设备指定地址下写数据

SDA LINE:SDA线上时序,START:起始位

Device Address:要写的设备的地址(总线挂载多个从机设备时,选择要写的从设备),R/W为置0为写。ACK为等待应答位。

WORD ADDRESS:确定设备上面的要写入的地址,等待ACK应答位。

DATA:要写的数据,应答之后,STOP:停止位。

24C02字节读时序:对于指定设备,在指定地址下,读取从机数据。

DUMMY WRITE部分:这部分不是真正向地址写数据,而是表示向设备写要读的数据的地址, 这个地址会被锁存起来,不会触发读写操作,所以才叫做dummy write(哑写)!

哑写操作:

目的是为了更新 I²C 从设备的微控制器内部的字节地址计数器。原理:I²C 从设备的微控制器内部的字节地址计数器会根据每读一个数据或者每写一个数据就累加1,直到累加到计数器记满(写操作) 或者是累加到页尾(读操作)。此时如果直接发送器件地址(也就是进行当前地址读),那么它读出来的是当前计数器所指的地址。(因为只要不断电,the internal address counter就会保持之前的值,比如之前先对计数器0指的地址写了一个数据,此时计数器会累加到1, 然后接着进行当前地址读操作,此时读出的数据将是计数器1所指的地址的数据。)

STM32有自带的硬件I²C,还可以软件模拟实现I²C。大多数情况选择软件模拟实现I²C,节省硬件资源。而且STM32自带的硬件I²C在速率快了之后不稳定。且硬件I²C只能使用设计好的指定引脚。

硬件I²C框图:

 I²C基本结构图:

SPI

SPI相比I²C:

SPI传输更快,I²C开漏输出外加上拉电阻的电路结构,使通信线的高电平驱动能力比较弱,因此由低电平到高电平的时候,上升沿耗时比较长,这就限制了I²C的最大通信速度。I²C通常认为速度是400KHz。SPI通信线多,通信过程中常有资源浪费的现象。

SPI是串行外围设备接口,SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,也为 PCB 的布局上节省空间,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,主要应用在EEPROM,FLASH,实时时钟,AD转换器,数字信号处理器和数字信号解码器之间。STM32F4 也有 SPI 接口。

SPI 接口一般使用 4 条线通信:

MISO:主设备数据输入,从设备数据输出。
MOSI:主设备数据输出,从设备数据输入。
SCLK:时钟信号,由主设备产生。
CS:从设备片选信号,由主设备控制。拉低选中对应从设备。

当从设备的片选信号CS为高电平,也就是从机未被选中时,从机的MISO引脚必须切换为高阻态。高阻态相当于引脚断开,不输出任何电平,这样防止一条线有多个输出导致电平冲突的问题。在CS为低电平时,从机被选中,相应从机的MISO才允许变为推挽输出。

SPI接口内部简图以及工作原理:

起始条件:CS由高电平切换到低电平;

终止条件:CS由低电平切换到高电平。

主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。寄存器通过MOSI信号线将字节传送给从机,从机也将自己的移位寄存器中的内容通过MISO 信号线返回给主机。这样,两移位寄存器中的内容就被交换;

外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输;

在主机的波特率发生器驱动下。在第一个时钟的边沿,数据输出:主机移位寄存器中8位数据整体往左移一位,最高位的数据1移动到MOSI数据线上(实际上是放到了输出数据寄存器),最低空出来;从机移位寄存器的最高位的数据0也移动到MISO数据线上(实际上是放到了输出数据寄存器),最低位空出来。

在下一个边沿数据采样输入:MOSI数据线上的1移位到从机最后一位;MISO数据线上的0移位到主机的最后一位。

输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入。

SPI特征:

可以同时发出和接收串行数据:3线全双工同步传输

可以当作主机或从机工作:主或从操作,支持多主模式

提供频率可编程时钟:8个主模式波特率预分频系数(最大为fpcuk/2),从模式频率(最大为fpcLk/2)

发送结束中断标志; 写冲突保护; 总线竞争保护。

8或16位传输顿格式选择,可编程的数据顺序:MSB在前或LSB在前
主和从模式下均可由软件或硬件进行NSS管理: 主/从操作模式的动态改变可编程的时钟极性和相位
可触发中断的专用发送和接收标志,SPI总线忙状态标志
支持可靠通信的硬件CRC:在发送模式下,CRC值可以被作为最后一个字节发送;在全双工模式中对接收到的最后一个字节自动进行CRC校验

可触发中断的主模式故障、过载以及CRC错误标志

支持DMA功能的1字节发送和接收缓冲器:产生发送和接受请求

从器件选择(NSS)引脚管理(也叫CS引脚,SS引脚):

可以使用SPI_CR1寄存器中的SSM位设置硬件或软件管理从器件选择。

软件管理 NSS (SSM = 1)从器件选择信息在内部由SPI_CR1寄存器中的SSM位的值驱动。外部NSS 引脚空闲,可供其它应用使用。

硬件管理 NSS(SSM = 0)。
根据 NSS 输出配置(SPI_CR1 寄存器中的 SSOE 位),硬件管理 NSS 有两种模式。NSS 输出使能(SSM = 0,SSOE =1)
仅当器件在主模式下工作时才使用此配置。当主器件开始通信时,NSS 信号驱动为低电平,并保持到 SPI 被关闭为止。
NSS 输出禁止(SSM = 0,SSOE = 0)
对于在主模式下工作的器件,此配置允许多主模式功能。对于设置为从模式的器件,NSS 引脚用作传统 NSS 输入: 在 NSS 为低电平时片选该从器件,在 NSS 为高电平时取消对它的片选。

时钟信号的相位和极性(组成SPI四种工作方式):

SPI_CR寄存器的CPOL和CPHA位,能够组合成四种可能的时序关系。CPOL(时钟极性)位控制在没有数据传输时时钟的空闲状态电平,此位对主模式和从模式下的设备都有效。CPHA位控制数据是在第一或者第二边沿被采集 / 锁存。

若CPOL置0,在空闲状态SCK引脚保持低电平;CPOL被置1,在空闲状态SCK引脚保持高电平。

如果CPHA(时钟相位)位被置1,SCK时钟的第二个边沿(CPOL位为0时就是下降沿,CPOL位为1时就是上升沿)进行数据位的采样,数据在第二个时钟边沿被锁存。

如果CPHA位被清0,SCK时钟的第一边沿(CPOL位为0时就是下降沿,CPOL位为’1”时就是上升沿)进行数据位采样,数据在第一个时钟边沿被锁存。
CPOL时钟极性和CPHA时钟相位的组合:选择数据捕捉的时钟边沿。

数据帧格式:

根据SP_CR1寄存器中的LSBFIRST位,输出数据位时可以MSB在先也可以LSB在先。

根据SPI_CR1寄存器的DFF位,每个数据帧可以是8位或是16位。所选择的数据帧格式对发送,接收都有效。

状态标志:

应用程序通过3个状态标志可以完全监控SPI总线的状态。

发送缓冲器空闲标志(TXE)
此标志为1时表明发送缓冲器为空,可以写下一个待发送的数据进入缓冲器中。当写入SPI_DR时,TXE标志被清除。

接收缓冲器非空(RXNE)
此标志为1时表明在接收缓冲器中包含有效的接收数据。读SPI数据寄存器可以清除此标志。

忙(Busy)标志
BSY标志由硬件设置与清除(写入此位无效果),此标志表明SPI通信层的状态。

SPI中断:

SPI时序:

向CS指定的从机发送指令(SPI通信的从机的芯片手册里都会提供好相应的指令集)。规则:XX指令+XXX数据。

指定地址写:向CS指定的设备,发送写指令,随后在指定的地址下,写入指定的数据。

指定地址读:向CS指定的设备,发送读指令,随后在指定的地址下,读取出从机的数据。

软件SPI:是通过程序设置定时翻转电平来实现时序。

硬件SPI:

STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担。可配置8或16位数据帧,可配置高位或者低位先行。时钟频率:一个SCK时钟交换一个bit,时钟频率体现的是传输速度,单位是:Hz或者bit/s。这里时钟频率可配置为f_{PCLK}/(2,4,6,8,16,32,64,128,256)。

SPI接口框图:

接收缓冲区:读取数据由移位寄存器转到RDR,再读出RDR寄存器。

发送缓冲区:发数据写入TDR寄存器。再转入移位寄存器发送。

简化框图:

硬件SPI引脚配置(STM32F4):

哪些引脚可以复用为SPIx的相应功能引脚,需要查数据手册。

 

SPI常用寄存器:

SPI控制寄存器1(SPI_CR1)

SPI控制寄存器2 (SPI_CR2)

SPI状态寄存器 (SPI_SR)

SPI数据寄存器(SPI_DR)

SPI相关库函数:

void SPI_I2S_DeInit(SPI_TypeDef* SPIx);
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);//初始化函数
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);//使能函数
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);
//中断配置函数
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);
//DMA开启使能函数
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);//发送数据函数
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);//接收数据函数
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);//设置数据格式8/16位

//相关状态获取函数
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
typedef struct
{
  uint16_t SPI_Direction;              //方向(2线全双工,2线接收,1线接收,1线发送)
  uint16_t SPI_Mode;                   //确定主机还是从机           
  uint16_t SPI_DataSize;               //确定数据8或16位
  uint16_t SPI_CPOL;                   //极性和相位:与CPHA联合使用        
  uint16_t SPI_CPHA;                   //极性和相位与:与CPOL联合使用 
  uint16_t SPI_NSS;                    //确定是硬件片选还是软件片选   
  uint16_t SPI_BaudRatePrescaler;      //波特率分频系数  
  uint16_t SPI_FirstBit;               //设置低位在前还是高位在前  
  uint16_t SPI_CRCPolynomial;          //CRC校验  
}SPI_InitTypeDef;

SPI程序配置过程:

使能SPIx和IO口时钟
RCC_AHBxPeriphClockCmd();RCC_APBxPeriphClockCmd();

初始化IO口为复用功能

void GPIO_Init(GPIO_TypeDef* GPIOx GPIO_InitTypeDef* GPIO_InitStruct);

设置引脚复用映射
GPIO_PinAFConfig();

初始化SPIx,设置SPIx工作模式
void SP_Init(SPI_TypeDef* SPIx,SPI_InitTypeDef* SPI_InitStruct);

使能SPIx
void SPI_Cmd(SPI_TypeDef* SPlx,FunctionalState NewState);

SPI传输数据
void SPI_12S_SendData(SPI_TypeDef* SPlx, uint16_t Data);

uint16_t SPI_12S_ReceiveData(SPI_TypeDef* SPlx);

查看SPI传输状态
SP1_12S_GetFlagStatus(SPI2,SPI_12S_FLAG_RXNE)

常用的一些SPI通信的模块:

W25QXX系列(FLASH存储器);7针OLED;2.4G无线通信模块(芯片NRF24L01);Micro AD卡。

开发板板载资源硬件连接:

板上的 W25Q128 是直接连在 STM32F4 的 SPI1上的。

W25Q128:

W25Q128 将 16M 的容量分为 256 个块(Block),每个块大小为 64K 字节,每个块又分16 个扇区(Sector),每个扇区 4K 个字节。W25Q128 的最小擦除单位为一个扇区,也就是每次必须擦除 4K 个字节。这样我们需要给 W25Q128 开辟一个至少 4K 的缓存区,这样对 SRAM要求比较高,要求芯片必须有 4K 以上 SRAM 才能很好的操作。

W250128 的擦写周期10W次,有 20 年的数据保存期限,支持电压为 2.7~3.6V。W25Q128 支持标准的SPI,还支持双输出 / 四输出的 SPI,最大 SPI时钟可以到 80Mhz(双输时相当于 160Mhz,四输出时相当于 320M)。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值