datasheet

SPI专题(二)——STM32驱动FLASH(W25Q64)

2019-01-09来源: eefocus 关键字:SPI  STM32  驱动FLASH  W25Q64

1.硬件连接

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



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


1.1 硬件连接

STM32 的引脚连接如下:这里是使用SPI1配置。



STM32引脚 对应SPI功能

PA2 片选CS

PA5 时钟SCK

PA6 MISO

PA7 MOSI

STM32 的 SPI 功能很强大, SPI 时钟最多可以到 18Mhz,支持 DMA,可以配置为 SPI 协议或者 I2S 协议(仅大容量型号支持)。


1.2 SPI通讯的通讯时序

SPI协议定义了通讯的起始和停止信号、数据有效性、时钟同步等环节。



这是一个主机的通讯时序。NSS、SCK、MOSI 信号都由主机控制产生,而 MISO 的信号由从机产生,主机通过该信号线读取从机的数据。MOSI 与 MISO 的信号只在 NSS 为低电平的时候才有效,在 SCK的每个时钟周期 MOSI和 MISO传输一位数据。


1.通讯的起始和停止信号


在图中的标号1处,NSS 信号线由高变低,是 SPI 通讯的起始信号。NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知道自己被主机选中了,开始准备与主机通讯。在图中的标号6处,NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通讯结束,从机的选中状态被取消。


2.数据有效性


SPI使用 MOSI及 MISO信号线来传输数据,使用 SCK信号线进行数据同步。MOSI及MISO 数据线在 SCK 的每个时钟周期传输一位数据,且数据输入输出是同时进行的。数据传输时,MSB 先行或 LSB 先行并没有作硬性规定,但要保证两个 SPI通讯设备之间使用同样的协定,一般都会采用图中的 MSB先行模式。


观察图中的2345标号处,MOSI及 MISO的数据在 SCK的上升沿期间变化输出,在SCK 的下降沿时被采样。即在 SCK 的下降沿时刻,MOSI 及 MISO 的数据有效,高电平时表示数据“1”,为低电平时表示数据“0”。在其它时刻,数据无效,MOSI及MISO为下一次表示数据做准备。SPI每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制。


1.3 STM32 SPI外设

STM32 的 SPI 外设可用作通讯的主机及从机,支持最高的 SCK 时钟频率为 f pclk /2(STM32F103型号的芯片默认 f pclk1 为 72MHz,f pclk2 为 36MHz),完全支持 SPI协议的 4种模式,数据帧长度可设置为 8 位或 16 位,可设置数据 MSB 先行或 LSB 先行。它还支持双线全双工(前面小节说明的都是这种模式)、双线单向以及单线模式。


SPI架构:



通讯引脚 :


SPI的所有硬件架构都从图中左侧 MOSI、MISO、SCK及 NSS线展开的。STM32芯片有多个SPI外设,它们的SPI通讯信号引出到不同的GPIO引脚上,使用时必须配置到这些指定的引脚。


2.软件配置

这里使用 STM32 的 SPI1 的主模式,SPI 相关的库函数和定义分布在文件 stm32f10x_spi.c 以及头文件 stm32f10x_spi.h 中。


2.1配置相关引脚的复用功能,使能 SPI1 时钟

第一步就要使能 SPI1 的时钟, SPI1 的时钟通过 APB2ENR 的第 12 位来设置。其次要设置 SPI1 的相关引脚为复用输出,这样才会连接到 SPI1 上否则这些 IO 口还是默认的状态,也就是标准输入输出口。这里我们使用的是 PA5、 6、 7 这 3 个(SCK、 MISO、 MOSI, 

CS 使用软件管理方式),所以设置这三个为复用 IO。



    GPIO_InitTypeDef GPIO_InitStructure;


    RCC_APB2PeriphClockCmd( RCC_APB2P%riphGPHOA"RCC_APB2Periph_SPI1%r52C%521ENABLE ); 


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);


    GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);


2.2初始化 SPI1,设置 SPI1 工作模式

接下来初始化 SPI1,设置 SPI1 为主机模式,设置数据格式为 8 位,然设置 SCK 时钟极性及采样方式。并设置 SPI1 的时钟频率(最大 18Mhz),以及数据的格式(MSB 在前还是LSB 在前)。这在库函数中是通过 SPI_Init 函数来实现。 

函数原型:


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


第一个参数是 SPI 标号,第二个参数结构体类型 SPI_InitTypeDef 为相关属性设置。


SPI_InitTypeDef 的定义如下:


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_Mode 设置 SPI 的主从模式,主机模式 (SPI_Mode_Master),从机模式 (PI_Mode_Slave)。

SPI_DataSiz 数据为 8 位还是 16 位帧格式选择项。SPI_DataSize_8b(8 位),SPI_DataSize_16b (16位)

SPI_CPOL 设置时钟极性

SPI_CPHA 设置时钟相位,也就是选择在串行同步时钟的第几个跳变沿(上升或下降)数据被采样,可以为第一个或者第二个条边沿采集

SPI_NSS 设置 NSS 信号由硬件(NSS 管脚)还是软件控制

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

初始化的范例格式为:


    SPI_InitTypeDef  SPI_InitStructure;


SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工

    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       //设置SPI工作模式:设置为主SPI

    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;       //设置SPI的数据大小:SPI发送接收8位帧结构

    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;     //选择了串行时钟的稳态:时钟悬空高

    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //数据捕获(采样)于第二个时钟沿

    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;       //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制

    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //定义波特率预分频的值:波特率预分频值为256

    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;  //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始

    SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值计算的多项式

    SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器


2.3使能 SPI1

初始化完成之后使能 SPI1 通信,在使能 SPI1 之后,就可以开始 SPI 通讯了。使能 SPI1 的方法为:


SPI_Cmd(SPI1, ENABLE); //使能 SPI 外设


2.4 SPI 传输数据

通信接口需要有发送数据和接受数据的函数,固件库提供的发送数据函数原型为:


void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);


往 SPIx 数据寄存器写入数据 Data,从而实现发送。


固件库提供的接受数据函数原型为:


uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) ;


这从 SPIx 数据寄存器读出接收到的数据。


2.5查看 SPI 传输状态

在 SPI 传输过程中,要判断数据是否传输完成,发送区是否为空等等状态, 

通过函数 SPI_I2S_GetFlagStatus 实现的,判断发送是否完成的方法是:


SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE);


3.软件设计

3.1 SPI实现

SPI_InitTypeDef  SPI_InitStructure;


void SPI1_Init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;


    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE ); 


    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(GPIOA, &GPIO_InitStructure);


    GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);


    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工

    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;       //设置SPI工作模式:设置为主SPI

    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;       //设置SPI的数据大小:SPI发送接收8位帧结构

    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;     //选择了串行时钟的稳态:时钟悬空高

    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //数据捕获(采样)于第二个时钟沿

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软

[1] [2] [3] [4]

关键字:SPI  STM32  驱动FLASH  W25Q64

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/2019/ic-news010942855.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32学习笔记一一输入捕获
下一篇:最后一页

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

两片STM32使用HAL完成SPI全双工主从通信

SPI是一种非常简单易用的全双工主从式通信协议。本文使用两片STM32F429,一个作为主机,一个作为从机完成SPI的全双工通信测试。在STM32的HAL库中简化了SPI主机端的发送接收,但是HAL库没有提供一个简单的SPI从机代码接口,这样就需要自己拼接接口来完成全双工的通信。以下都以实现全双工通信为目的进行配置和编写:一 主机端:禁止使用SPI的硬件片选信号,因为这个信号是SPI使能了之后就一直为低,直到禁止了SPI之后才为高。可以使用某一个普通IO来充当片选信号。这里选用一个较低的速率来通信,在HAL库的spi头文件中有说明各个模式下SPI的最大速度。二 从机端:主从的速率要一样,从机打开SPI中断三 硬件连接:主机
发表于 2019-01-07
两片STM32使用HAL完成SPI全双工主从通信

stm32 SPI-FLASH W25Q64

W25Q64SPI配置步骤1.使能SPI时钟2.使能GPIO端口时钟3.初始化GPIO,配置引脚模式4.初始化SPI5.使能SPI6.SPI读写数据7.查看SPI传输状态举例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
发表于 2019-01-04
stm32 SPI-FLASH W25Q64

STM32双机SPI中断通信机制

研究STM32F4的SPI有一阵子了,进步很缓慢,前几天终于鼓起勇气,用手抄了一遍官方的代码,然后自己一个字字的敲进去,然后再调试。历时大约一个星期,终于把SPI的中断发送和中断接收给整清楚了。在没有正确运行出结果之前,一切都是辣么痛苦。此文鼓励我继续往前进步。先说主机端,首先当然是写SPI驱动文件,也就是SPI的配置,具体文件如下:SPI.c#include <stm32f4xx.h>#include "usart.h"#include "spi.h"    u8 Master_Temp =0;  extern
发表于 2018-12-28

STM32 SPI方式读写SD卡

前段时间在51上模拟SPI实现了对SD卡的读取,效果还算不错,最近将其移植到STM32上,不过使用硬件SPI和使用软件SPI还是有差别的。 代码如下: void User_SPIInit(void){ GPIO_InitTypeDef GPIO_InitStructure;  SPI_InitTypeDef SPI_InitStructure;  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1,ENABLE);  //使能时钟  
发表于 2018-12-26

KST-STM学习之I2C+SPI

高电平,避免毛刺信号。4、实际上 I 2 C 的配置过程比较复杂,比如要充分考虑冲突和仲裁等处理方式,但是那些处理方式在绝大多数场合用不到。STM32F103 系列自带的 I 2 C 协议模块设计的过于复杂,对于实际应用来讲实用性不强,因此实际应用 I 2 C 时,还是用 IO 口直接模拟协议。5、即在 SCK 的第一个时钟边沿还要早半个时钟周期时,SPI 主机就已经开始输出数据了,但是 SPI 从机却是在片选 SSEL 置低后开始输出数据,总之 SPI 设备输出数据要早于 SCK,这也是为什么 SPI 通信时要先使能片选。6、SPI 和 I2C的对比7、SPI接口8、引脚连接 9、SPI外设 SP3需要注意的地方
发表于 2018-12-14
KST-STM学习之I2C+SPI

STM32 SPI NSS 引脚为不能拉高问题

使用过 STM32 的SPI 的朋友可能都会发现一个问题,那就是其NSS引脚 在硬件模式下无法自动拉高,可能也因为这个原因致使  。大部分朋友在使用SPI时候都是优先选用软件 控制NSS引脚的工作模式。最近想用 SPI 直接 DMA 对一传感器进行数据通信,想直接用SPI的硬件NSS控制模式来操作SPI(之前一直是软件模式,这次对 CPU时间比要求较高,不想再用软件去切换引脚 ):引脚配置 及 SPI DMA 配置如下:/* 引脚配置 */  GPIO_InitStructure.GPIO_Pin =  SPI_MASTER_PIN_NSS | SPI
发表于 2018-12-12
STM32 SPI NSS 引脚为不能拉高问题

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2018 EEWORLD.com.cn, Inc. All rights reserved
pt type="text/javascript" src="//v3.jiathis.com/code/jia.js?uid=2113614" charset="utf-8">