一、简介
SPI是外围串行设备接口,主要应用于EEPROM、FLASH、实时时钟、AD转换器,还有数字信号处理器和数字信号解码器。它是一种高速、全双工、同步的通信总线。它有四根线,MISO:主机输入从机输出 MOSI:主机输出从机输入 SCK:时钟线 CS:片选。
SPI内部结构简明图
从图中可以看出,主机和从机都有一个串行移位寄存器,主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。主机寄存器通过MOSI将字节发送给从机,从机寄存器通过MISO发送给主机,这样两个移位寄存器的内容就被交换,外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节,如果只进行读操作,只需发送一个空字节0xff。
SPI主模块与通信的外设时钟相性应该一致,可通过配置CPHA和CPOL。如果CPHA为1时,在SCK的第二个边沿锁存数据,如果CPHA为0时,在SCK的第一个边沿锁存数据。CPOL决定SCK在空闲状态是高或低电平,CPOL为0时,SCK空闲状态为低电平,CPOL为1时,SCK空闲状态为高电平。
接着我们将用SPI去读写FLASH(W25Q128),容量为128Mbit,即16M字节,根据下图,16MB分为256个块,每块64KB,每个块又分为16个扇区,每个扇区4KB,每个扇区分为16页,每页256字节。
W25Q128最小的擦除单位为扇区,所以要写数据时,应先将该扇区的数据读到缓存,然后更改该数据,把扇区擦除,再将该数据重新写进去。
二、硬件设计
三、软件编程
SPI.c
1)配置相关引脚的复用功能,使能SPIx时钟;
2)初始化SPIx,设置SPIx工作模式;
3)使能SPIx;
4)设置波特率函数;
assertparam(expr)是用来检测参数的有效性,它在stm32f10x_conf.h有定义,参数若为真则执行(void)0,即什么也不做;若为假则执行assert_failed((uint8_t *)__FILE__, __LINE__),会报错。
波特率是由SPI的CR1寄存器的位5:3控制的。
5)读写字节函数;
只有当发送缓冲区空了,才能往发送缓冲区写数据,只有当接收缓冲区非空,才能读数据。
发送库函数的定义,往DR寄存器写值
W25Q128.c
1)初始化W25Q128,PB12是片选引脚。
2)W25Q128的指令函数
(1)读状态寄存器:首先要拉底片选(The instruction is entered by driving /CS low )
其次发送命令(shifting the instruction code "05h" for Status Register-1 into the DI pin on the rising edge of CLK)
读数据(the status register bits are then shifted out on the DO pin at the falling edge of CLK)
最后拉高片选(the instruction is completed by driving/CS high)
(2)可查阅W25Q128的资料,对应时序图来编写指令函数,就不一一分析了。
Dst_Addr*4096是因为它的形参是地址/4096,所以要乘回去,形参在后面write函数里;
(3)无检验写FLASH,必须保证所写的地址范围全部为0xff,否则会失败,因为该函数没有擦除扇区。pageremain代表一页剩余空间。
(4)该函数带擦除,如果要写的地址不是0xff,要擦除使它为0xff,才能往里面写数据;
主函数:按下KEY0,将text_buf的数据写进FLASH,按下KEY1,再将它读出来,显示到OLED上。