STM32工作笔记0067---SPI接口原理与配置

技术交流QQ群【JAVA,C++,Python,.NET,BigData,AI】:170933152

由于工作原因,中间省略了,关于ADC,DAC等的内容,后面补上.

今天咱们讲解前三个

这里,首先SPI是个,高速的,全双工,同步通信总线,这个怎么来说呢?

同步就说,有个独立的发送引脚,有个独立的接收引脚,然后

还有一个时钟引脚,这个是干嘛用的呢,时钟是来控制数据发送的.

因为是同步所以需要时钟,我们知道异步的话,是需要用波特率来约定的.

这样就有三个引脚了,那么这里还有一个引脚,是片选引脚.

这个片选引脚的意思是,通过这个片选引脚可以让,这里的虽然只要一个接受引脚,一个发送引脚,

但是呢,可以用来接多个设备,比如这个设备SPI的片选引脚,连接到另一个设备的片选引脚上面

这样就可以实现,连接多个设备.

这里这个MISO的意思是m是master的意思,然后I是input,然后s是slave,从机的意思

然后o是output输出的意思.

首先因为我全双工的,那么每个终端需要两个引脚的,都是独立的,可以接收也可以发送.

然后,他是可以做主机,也可以做从机.

这里MISO的意思是,这个做主机的时候就是输入,做从机的时候,就是输出

MOSI的意思,作为主机的时候是输出,作为从机的时候是输入.

然后看一下图

可以看到按照左侧的,这里作为主机的时候master,这个时候是MISO,是输入,然后作为从机的时候,是

输出.

然后再看一下这里的移位寄存器.

这个移位寄存器的意思是,他可以把数据位一位一位的,移出去,这样就实现了数据的传输.

每移动一位,那么最高位就变成了次高位,次高位就变成了,原来的最高位,

然后对于环形移位寄存器:

这个环形移位寄存器的意思是这样的,

就是说比如右边的移位寄存器中的值是01010101,

然后左侧移位寄存器中的值是10101010,这个时候

左侧的移位寄存器,作为主机的话,那么就是MISO,从机作为输出

右边的从机会先把1,移到左边的主机MI主机作为输入,然后这样一位一位的移动,就会导致

最终,主机中的数据到了从机,从机中的数据到了主机.

这样,这个就像一个环形一样.

这个就是SPI的内部结构,主要了解这个移位寄存器

然后

然后这里,这里每当,咱们要写数据的时候,比如写入8字节,实际上调用的函数是readWrite也就是,这边写入了8个

字节的数据,那么就会再另一个移位寄存器中输入8个字节数据,这个类似于一个循环.

然后看一下SPI的接口创图,左上角,其实就是咱们说的,他怎么传数据,下面有个波特率发生器,右边就是一些控制

寄存器.

主机要读取数据的话,读取字节,那么从机要发送一个空字节来引发从机的传输.

主机通过向SPI串行寄存器写入一个字节来发起一次传输.

这里写了SPI的所有的特征,这里看看这个

可触发中断的专用发送和接收标志,也就是可以通过配置寄存器,使能位,

可以让这个接收发送,来触发中断.

接下来,挑几个重要的点来说明一下:

这里是NSS脚管理是这样的,NSS就是片选引脚,这个引脚的作用是,

可以让咱们的一个SPI去连接多个设备,也就是通过SPI的引脚,连接到MCU上,然后通过比如MCU的PA2连接一个设备

然后PA3连接一个设备,PA4也连接一个设备,然后,当我使用PA2对应的设备的时候,这个时候就可以把对应的设备对应的

片选拉低,其他的片选拉高,这样就可以实现这个设备的通信了.其他的设备占时不通信,

这样就实现了用一个SPI口,来实现控制多个SPI设备的方法.

这里的CPOL是指的是,没有数据传输时时钟的空闲状态电平,如果CPOL被设置为0,SCK引脚在空闲状态下保持低电平

如果CPOL设置为1,然后CPHA指的是时钟相位,这个指定了什么时候开始采集边沿,同时CPHA如果被设置为1,则在SCK时钟的

第二个边沿开始采集,然后如果CPHA被设置为0,就再SCK时钟的第一个边沿,进行采集.

这里的CPOL和CPHA有两个位,也就是4个组合

这里通过图再理解一下

也就是如果CPOL=1的话,那么就是高电平有效,也就是上面画的一个情况,

这个时候可以看到,第一个边沿是下降沿,第二个边沿是上升沿,如果这个时候CPHA=1的话,

那么就说明要从第二个边沿,也就是上升沿开始去采集.

如果CPOL=0的话,那么就是低电平有效,就是下面的那种情况

这个时候可以看到,第一个边沿是上升沿,第二个边沿是下降沿,如果这个时候CPHA=1的话,

那么就说明要从第二个边沿,也就是下降沿开始去采集.

同样,如果这里CPHA=0 的时候,那么,

CPOL=1是高电平有效,那么第一个边沿就是下降沿,这个时候CPHA=0,从第一个边沿开始采集,

就是从下降沿开始采集.

CPOL=0是低电平有效,那么第一个边沿就是上升沿,这个时候CPHA=0,从第一个边沿开始采集,

就是从上升沿开始采集.

比如我们的主机来连接从机,那么一般对从机的极性都是有严格要求的

这里就要求,我们需要根据从机的相位和极性等来,配置我们的主机的极性和相位

SPI的中断,一共有这几个中断事件,对应的事件标志位,

SPI数据寄存器就是存放数据的.

void SPI_I2S_DeInit(SPI_TypeDef* SPIx);

void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);

//这个用来设置是主机还是从机,数据帧是8位还是16位,

//然后LSB在前还是在后

void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);//还有SPI的使能,要使能哪个SPI

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位.

//下面是4个状态.

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);

打开spi的实验:

这个SPI初始化的函数,第一个参数是哪个SPI这样,

然后第二个是一个结构体,这里看一下这个结构体.

来过一下这个参数

第一个是方向SPI_Direction

去定义看一下

对于方向可以是:

对于

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 即可。

IO口的配置用下面的表格中配置

可以看到有两个数据口:

SPI2_MISO

SPI2_MOSI

一个时钟口:

SPI2_SCK

一个片选口:

F_CS

这里战舰版用到的口是

PB14 这个数据口 MISO

PB15 MOSI这个数据口

PB13这个是SPI2_SCK这个是时钟口

PB12对应的是片选口

战舰版这里用的是SPI2这个口.

然后对于mini版,对应的口是PA2 F_CS这个片选口

他用的SPI1这个口

然后由于:

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

也就说在我们同SPI口写入数据的时候,要注意,在所有的写入数据的时候,操作是这样的,

要先把数据写入到缓存中区,而且缓存是4k,为什么要求4k呢,因为往flash中写入数据的时候

首先要写入一个地址的话,要必须,首先擦除一个扇区,只有先擦除了一个扇区的数据,然后

才能把后面的数据,写入到这个扇区中去,而扇区是flash的最小的单位,这个最小的单位就是4k.

这个文件中记录这个命令.

比如这里读数据的命令等等,那么,这一讲先说到这里,下一讲继续说代码

下一讲会说,比如这类spi的初始化配置

w25qx的命令的用法等等.

猜你喜欢

转载自blog.csdn.net/lidew521/article/details/108384599