陈庙红——STM32——SPI

陈庙红——STM32——SPI

STM32_SPI

SPI_GPIO_Config

GPIO引脚的复用位置设置:
SPI_SCK,SPI_MOSI,SPI_MISO,配置成推挽复用输出 SPI_NSS通用推挽输出,由于PA4使用的软件配置。
如:在宏定义中:

define SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4);

define SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4);

SPI模式的初始化
(1)SPI_Mode:STM32的SPI设备课配置成SPI_Mode_Master或者SPI_Mode_Slave
(2)SPI_DataSize:SPI通信数据帧的大小为8位或者16位
(3)SPI_CPOL和SPI_CPHA:配置SPi的时钟极性(CPOL)和时钟相位(CPHA),这两个配置影响SPI的通信模式,该设置符合通信设备的要求。CPOL分别可以取SPI_CPOL_High(SPI通信空闲时SCK为高电平)和SPi_CPOL_Low(SPI通信时SCK为低电平)。CPHA则可以去SPI_CPHA_1Edgr(在SCK的技术边沿进行采集数据)和SPI_CPHA_2Edge(在SCK的偶数边沿进行数据采集)。
flash支持SPI的模式0和模式3通信。在SPI空闲时,SCK为低电平,奇数边沿采样(模式0);
也可以在SPI空闲时,SCK为高电平,偶数边采样(模式3)。即无论CPOL的状态是什么,FLASh的采样时刻为SCK的上升沿。本次实验我们把它配置为模式3,把CPOL赋值为SPI_CPOL_high;CPHA赋值为SPI_CPHA_2Edge。
(4)SPI_NSS:本成员配置NSS引脚的使用模式,可以选择硬件模式(SPI_NSS_Hard)或者软件模式(SPI_NSS_Soft),本次采用软件模式向成员复制。
(5)SPI_BaudRatePrescaler;设置波特率的分频,分频后时钟即为SPI的SCK信号线的时钟频率,这个成员参数为fpclk的2.4.6.8.16.32.64.128.256分频,本实验赋值为SPI_RaudRatePrescaler_4,即fPCLK的4分频。
(6)SPI_FirstBit:配置高数据位MSB先行还是低数据位LSB先行,此时为SPI_First_MSB。
(7)SPI_CRCPolynomial:这是SPI的CRC校验中的多项式,本实验不支持。
配置完结构体之后调用SPI_Init()函数把这些参数写入寄存器中,一实验SPI的初始化,然后调用SPI_Cmd来是你呢个SPI1.

控制Flash的命令

1)第6 行,调用宏SPI_FLASH_CS_LOW(),这是一个自定义的宏,使Flash 的片选
有效,以使能Flash 设备。
2)第9 行,利用用户函数SPI_FLASH_SendByte() 来向Flash 发送第一个命令字节编
码“W25X_DeviceID”(自定义的宏:0xAB)。
3)根据指令表,发送完这个指令后,后面紧跟着三个字节的“dummy byte”,我们把
Dummy_Byte 宏定义为“0xff”,实际上改成其他宏编码也无影响。
4)第15 行,完整的命令在前面已经发送完毕,根据时序,在第5 个字节Flash 通过
DO 端口输出它的器件ID,我们调用函数SPI_FLASH_SendByte() 接收返回的数据,并赋
值给Temp 变量。SPI_FLASH_ReadDeviceID() 函数的返回值即为读取得的器件ID。
5)把片选信号拉高,结束通信。

SPI收发数据的功能

1)调用库函数SPI_I2S_GetFlagStatus() 等待发送数据寄存器清空。
2)发送数据寄存器准备好后,调用库函数SPI_I2S_SendData() 向从机发送数据。
3)调用库函数SPI_I2S_GetFlagStatus() 等待接收数据寄存器非空。
4)接收寄存器非空时,调用SPI_I2S_ReceiveData() 获取接收寄存器中的数据并作为
函数的返回值,这个数据即由从机发送给主机的数据。
这是最底层的发送数据和接收数据的函数,利用了库函数的标志检测确保通信正常。

读取厂商的ID

这个函数根据命令流程,发送一个字节的命令编码“JEDEC ID (9Fh)”后,从机就
通过DO 线返回厂商ID 及0 ~ 16 位的设备ID。图15- 8 为读厂商ID 的时序图。

擦除FLASH的内容

其中第一个字节为扇区擦除命令编码(20h),紧跟其后的为要进行擦除的24 位起始
地址。根据Flash 的说明,它把整个存储矩阵分为块区和扇区,每块(Block)的大小为64
KB,每个扇区(Sector)的大小为4 KB,对存储矩阵进行擦除时,最小的单位为扇区。由
于篇幅问题,就不显示它的地址分布图了。

写使能

本函数十分简单, 就是根据写使能命令的时序, 发送写使能命令write enable(06h)

读FLASH状态

在擦除函数SPI_FLASH_SectorErase() 中, 还调用用户函数SPI_FLASH_WaitFor
WriteEnd()来确保在Flash 不忙碌的时候,才发送命令或数据。这个函数通过读取Flash 的
状态寄存器来获知它的工作状态 不断循环地检测Flash 状态寄存器的Busy 位,直到Flash 的内部写时序
完成,从而确保下一通信操作正常。主机通过发送读状态寄存器命令Read Status Register
(05h),返回它的8 位状态寄存器的值。

向FLASH写数据

小结

通过以上的函数,我们就可以实现对Flash 的擦除、写入和读取操作了,还有一小部
分函数没有分析到,大家根据需求在使用的时候再分析一下源代码吧。
最后,总结一下在STM32 如何建立与SPI-FLASH 的通信。
1)配置I/O 端口,使能GPIO。
2)根据将要进行通信器件的SPI 模式,配置STM32 的SPI,使能SPI 时钟。
3)配置好SPI 后,根据各种Flash 定义的命令控制对它的读写。
注意在写操作前要先进行存储扇区的擦除操作,擦除操作前也要先发出“写使能”
命令。

你可能感兴趣的:(陈庙红-STM32)