选用硬件:STM32F103 Nano开发板 板载有W25Q16
SPI:Serial Peripheral interface 串行外围设备接口
上图是SPI主机与从机设备间连线的关系,可以看出,主机主导了主机和从机的时序(SCLK),数据发送的流程是:
主机移位寄存器发送数据→MOSI→从机移位寄存器接收数据
从机移位寄存器发送数据→MISO→主机移位寄存器接收数据
两条线路发送数据是同步的。于是主机和从机的移位寄存器数据被交换。
只进行主机写入数据到从机时,主机忽视从机返回的数据;
只进行主机读取从机数据时,主机可发送空数据。
通常规定主机与从机间的数据格式均为MSB(Most Significant Bit 高位数据先行)
此外SPI设备通常还有SS或NSS接口用于片选。每一个从设备都要接到主机的一个SS引脚上。
SS/NSS:低电平有效
通常不会使用硬件SS接口,而是直接软件控制引脚电平实现片选。
通讯开始时,SS端电平拉低,通讯结束时,SS端电平拉高。
时钟极性(CPOL)和时钟相位(CPHA)对传输协议的影响如下:
CPOL=0:闲置时时钟信号(SCK)低电位
CPOL=1:闲置时时钟信号(SCK)高电位
CPHA=0:在时钟信号的第一个上升沿/下降沿采样
CPHA=1:在时钟信号的第二个上升沿/下降沿采样
不同模式下SPI的采样与时钟电平关系如下表所示
对于W25Q16,只支持SPI模式0和模式3。这也是大多数SPI硬件支持的模式。
数据内容 | 大小 |
---|---|
存储空间 | 2M Byte |
页数 | 8192 |
每页大小 | 256 Byte(0.25KB) |
最小扇区 | 4KB |
电源供电 | 2.7V~3.6V |
W25Q16支持4倍传输模式,在本次学习中暂时不会用到,详情见数据手册。
引脚功能:
CS:片选端输入,发送或接受数据前应先拉低片选端为低电平0,完成后拉高片选端电平为1,读取BUSY位(见下文寄存器)直至BUSY位为0,可继续发送或接受下一条指令。
WP:低电平有效,用于保护状态寄存器。
HOLD:低电平有效,允许芯片暂停工作,保持输出。
开发板的硬件连接:
W25Q16支持软件Reset(有30μs的延迟),软件启动Dual SPI和Quad SPI 。使用QUAD SPI通信时,需要使用WP引脚和HOLD引脚。在此只学习有关标准SPI通信的方法。
W25Q16内部结构与存储地址示意图如下,W25Q16共2M字节的存储空间被分为32个Block,每个Block(64KB)下有16个Sector(4KB),每个Sector(4KB)下有16个Page(256Byte),在图中的每一行的左侧地址到右侧地址表示一个Page。
在此特别说明两个状态寄存器:BUSY和WEL(Write Enable Only)
BUSY寄存器是只读寄存器,在对存储空间操作(包括页写入,块擦除等)时,BUSY寄存器保持在高电平位,此时芯片无法执行新的指令。完成操作后,BUSY寄存器重置为低电平,芯片可继续执行指令。
实际使用中可以用BUSY寄存器来判断指令是否执行完毕。
WEL寄存器同样是只读寄存器。当寄存器至为高电平时,可以执行对存储内容进行更改(包括页写入,块擦除等)的命令。置为低电平时,不能更改存储内容。
其它寄存器用于对数据的保护,通常不需要使用。需要使用时可查看数据手册的说明。
W25Q16数据传输为MSB模式,传入数据在上升沿采样。因此应使用SPI MODE3
The first byte of data clocked into the DI input provides the instruction code. Data on the DI input is sampled on the rising edge of clock with most significant bit (MSB) first.
芯片支持volatile数据写入,很多指令出于保护目的而设计,但在开发板上不需要。具体有待进一步学习。
预设的操作指令如下图所示:
对指令的一些说明:
(1) 芯片一次写入数据最多支持256Byte。超出256Byte的数据将覆盖前面已经写入的数据。
(2) 标准SPI模式下输入可基本参照上表,双路SPI或四路SPI模式下需要参考数据手册的说明。上表中带括号“()”的指令在双路SPI和四路SPI模式下有不同的输入方式,具体参照数据手册。
(3) 上表中【ID15-ID0】或【ID7-ID0】以及【MF7-MF0】对应第一个表中的设备地址,A表示地址,D表示数据,S表示寄存器,L表示Locked Value(具体见数据手册)。
(4) Write Enable/Disable 写使能/禁止
在页写入,扇区擦除,块擦除,全片擦除命令前必须使用的命令。使WEL位置1。
(5) Read/Write Status Register-1/2/3 读取/写入寄存器1/2/3的状态
上文中只介绍了Status Register-1的内容,实际使用中基本也只需要用到其中的BUSY和WEL两个状态寄存器,主要是读取寄存器的状态用于判断指令是否完成,或改变写入权限(通常通过写使能命令)。
对于读取状态寄存器的命令,当CS(片选端)未置高电平时将一直返回寄存器的状态。CS置1后命令结束。
(6) Read Data 读取数据
读取数据命令能够从发送的地址开始不断地读取数据直至CS置高电平1,能够读取至整个芯片。
此外还有作用相近的Fast Read 命令,在3个地址字节后加dummy字节,用于调整时钟速度,再进行数据的发送。具体没有进行实验,暂时只使用Read Data命令。
(7) Page Program 页写入
页写入命令必须在写使能(WEL=1)的条件下才有效。
页写入命令中的地址数据末八位(A7-A0)应当为00h,此时的地址是页的首地址,能够完整地将数据写入页中。
若地址末八位不是00h,则当输入的数据地址自增至页尾时,地址将回到页首继续写入。
写入数据的位置必须是擦出状态(0xFF),否则写入失败。
若写入的数据超出256字节,则超出的字节将覆盖写入数据的首部分字节。
完成数据写入后,应将CS置1才能使命令有效。此后芯片需要等待一段时间t才能完成数据的写入。写入过程中可用Read Status Register 读取BUSY寄存器查看命令是否完成。写入命令完成后,写使能自动被禁止(WEL=0)。
(8)
Sector Erase 扇区擦除(4KB)
32KB Block Erase 半块擦除
64KB Block Erase 整块擦除
Chip Erase 全片擦除
这几个命令与页写入命令相似,同样需要在WEL=1的条件下才可使用。命令执行过程中可通过查看BUSY标志位确认命令是否完成,命令完成后写使能自动被禁止,即WEL=0。
被擦除的数据将被全部置为1,即FFh。
初始化结构体的可控参数如下所示。
typedef struct
{
uint32_t Mode; //模式:主(SPI_MODE_MASTER),从(SPI_MODE_SLAVE)
uint32_t Direction; //方式: 只接收模式,单线双向通信数据模式,全双工
uint32_t DataSize; //8 位还是 16 位帧格式选择项
uint32_t CLKPolarity; //时钟极性
uint32_t CLKPhase;//时钟相位
uint32_t NSS; //SS 信号由硬件(NSS 管脚)还是软件控制
uint32_t BaudRatePrescaler;//设置 SPI 波特率预分频值
uint32_t FirstBit;//起始位是 MSB 还是 LSB
uint32_t TIMode; //帧格式 SPI motorola 模式还是 TI 模式
uint32_t CRCCalculation; //硬件 CRC 是否使能
uint32_t CRCPolynomial; //CRC 多项式
}SPI_InitTypeDef;
各个参数具体的预设值可参考官方数据手册。以下是根据W25Q16数据手册进行的初始化预设
SPI2_Handler.Instance=SPI2; //SPI2
SPI2_Handler.Init.Mode=SPI_MODE_MASTER; //设置为主模式
SPI2_Handler.Init.Direction=SPI_DIRECTION_2LINES; //SPI 设置为双线模式
SPI2_Handler.Init.DataSize=SPI_DATASIZE_8BIT; //SPI 发送接收 8 位帧结构
SPI2_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH; //串行同步时钟的空闲状态为高电平
SPI2_Handler.Init.CLKPhase=SPI_PHASE_2EDGE; //第二个跳变沿数据被采样
SPI2_Handler.Init.NSS=SPI_NSS_SOFT;//NSS 信号由硬件管理
SPI2_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256
;//定义波特率预分频的值:波特率预分频值为 256
SPI2_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB; //数据传输从 MSB 位开始
SPI2_Handler.Init.TIMode=SPI_TIMODE_DISABLE; //关闭 TI 模式
SPI2_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件 CRC
SPI2_Handler.Init.CRCPolynomial=7; //CRC 值计算的多项式
HAL_SPI_Init(&SPI2_Handler);//初始化
注:
SPI模式中还支持TI模式,TI模式又称SSP模式,是由TI公司定义的通讯标准,关闭TI模式下的SPI是由Motorola公司定义的通讯标准。通常使用的是Motorola公司定义的SPI通讯模式。
CRC:CRC校验
用STM32CubeMX配置引脚时,要设置SYS的Debug模式为Serial Wire,以免下载程序一次后无法读取调试器。