[10min速通]STM32CubemMX配置W25Q128

[10min速通]🦏STM32CubemMX配置W25Q128

1、下载源码

下载github开源驱动代码。

GitHub - nimaltd/w25qxx: w25qxx SPI FLASH driver for stm32 HAL

此处声明此工程不是本人所作。
这个工程的作者在Readme中提供的视频教程配置非常详细了,会魔法的同学可以直接去看视频进行配置,不用看此文。

如果访问不了github,可以直接下载文末的资料,打包好了。

2、配置Cube

2.1 基础配置

内容包含,时钟树、串口、SW下载接口等基础配置。此处不再赘述。

2.2 SPI配置

SW25Q128支持三种SPI通信模式:标准SPI,Dual SPI,Quad SPI。速度依次增加,每种模式所用到的通信时序也不一样,目前使用的是标准SPI。

SPI工作模式选择模式0或者3。写入时钟最大133M,读取时钟最大50M,这里我们把时钟控制在50M以内。

Untitled

下面是依据硬件电路配置接口。以下是我的接口:

Untitled

Untitled

特别注意的是CS引脚,因为配置SPI的时候,没有选择硬件NSS引荐,因此我们这里单独把PB14设置为CS引脚。

3、配置MDK

3.1 添加源文件

github上下载下来的文件如下:

Untitled

w25qxx就是我们需要加入到MDK里的驱动文件。

我们把w25qxx.c加入到…/Core/Src文件夹下。把w25qxx.h和w25qxxConf.h加入到…/Core/Inc文件夹。

3.2 管理源文件

接下来把文件导入到工程中。

6Q31MO(4%`KLZK0.png

如果找不到.h文件,需要设置下面的文件类型为All file

Untitled

最终的文件结构如下:

Untitled

3.3 完成接口配置

作者已经将所有的顶层配置集中在了w25qxxConf.h中,我们只需要更改其中的接口就可以完成基础的配置。

Untitled

下面用代码注释的方式,讲解下如何配置:

#ifndef _W25QXXCONFIG_H
#define _W25QXXCONFIG_H

#define _W25QXX_SPI                   hspi1         //使用到的是spi几
#define _W25QXX_CS_GPIO               GPIOB         //CS引脚的端口
#define _W25QXX_CS_PIN                GPIO_PIN_14   //CS引脚的引脚号
#define _W25QXX_USE_FREERTOS          0             //是否使用到了FreeRTOS,0为不使用。如果用到了其他RTOS,需要改动他的源码
#define _W25QXX_DEBUG                 0             //是否开启DEBUG模式,开启的话,需要提前配置好printf函数,工程运行时,会打印出运行过程。

#endif

此处我们用到的是spi1,CS引脚是PB14,关闭了RTOS跟DEBUG调试功能。

4、接口介绍

作者写的代码并没有提供多少注释,不过变量的命名已经可以做到见名知意。我通读了W25Qxx.c后,给大家介绍下常用的几个函数功能。

4.1 初始化

bool W25qxx_Init(void);
/*
函数功能:初始化芯片。成功就返回1,失败返回0。
*/

4.2 擦除

void W25qxx_EraseChip(void);
void W25qxx_EraseSector(uint32_t SectorAddr);
void W25qxx_EraseBlock(uint32_t BlockAddr);

上面三种擦除分别是:芯片全部擦除,擦除值定扇区,擦除值定块。SectorAddr是指扇区的编号,BlockAddr是指块的编号,编号不是地址。不太明白这句话可以接着往下看。

W25Q128有256个块(block),每个块由16个扇区(Sector)构成。一个块有64KB存储空间,一个扇区有4KB。下图是W25Q64的示意图,W25Q128内部也是这样的,就是block多一点。

image-20230817171513323

我们想擦除第3个块,只需要:

W25qxx_EraseBlock(2);

如果我们想要擦除第2个块中的第3个扇区。只需要:

W25qxx_EraseSector(15+3);

解释以下,15是因为第一个块中包含了0-15,总共16个扇区,编号16对应着第二个块中的第1个扇区,那么18就对应着第2个块中的第3个扇区。

4.3 写入

void W25qxx_WritePage(uint8_t *pBuffer, uint32_t Page_Address, uint32_t OffsetInByte, uint32_t NumByteToWrite_up_to_PageSize);
void W25qxx_WriteSector(uint8_t *pBuffer, uint32_t Sector_Address, uint32_t OffsetInByte, uint32_t NumByteToWrite_up_to_SectorSize);
void W25qxx_WriteBlock(uint8_t *pBuffer, uint32_t Block_Address, uint32_t OffsetInByte, uint32_t NumByteToWrite_up_to_BlockSize);

下面以W25qxx_WriteSector 为例讲解。

参数含义
pBuffer待写入的数据组指针
Sector_Address想要写入的扇区编号
OffsetInByte写入地址的字节偏置
NumByteToWrite_up_to_SectorSize想要写入的字节数

如果我想要写入第19个扇区的第二个字节位置,写入一个两字节的变量。那么代码是:

uint8_t WriteBuff[]={0x11,0x22};
...
W25qxx_WriteSector(WriteBuff, 18, 1,2);

4.4 读取

void W25qxx_ReadPage(uint8_t *pBuffer, uint32_t Page_Address, uint32_t OffsetInByte, uint32_t NumByteToRead_up_to_PageSize);
void W25qxx_ReadSector(uint8_t *pBuffer, uint32_t Sector_Address, uint32_t OffsetInByte, uint32_t NumByteToRead_up_to_SectorSize);
void W25qxx_ReadBlock(uint8_t *pBuffer, uint32_t Block_Address, uint32_t OffsetInByte, uint32_t NumByteToRead_up_to_BlockSize);

下面以W25qxx_ReadSector为例讲解。

参数含义
pBuffer待读取的数据组指针
Sector_Address想要读取的扇区编号
OffsetInByte读取地址的字节偏置
NumByteToWrite_up_to_SectorSize想要读取的字节数

如果我想要写入第19个扇区的第二个字节位置,写入一个两字节的变量。那么代码是:

uint8_t ReadBuff[2];
...
W25qxx_ReadSector(ReadBuff, 18, 1,2);

5、代码示例

首先要包含头文件

#include "w25qxx.h"

再定义读写变量:

uint8_t WriteBuff[] = {0x11, 0x22};
uint8_t ReadBuff[2];

最后编写服务代码

W25qxx_Init();                           // 初始化Flash芯片
W25qxx_EraseChip();                      // 擦除整个芯片
W25qxx_WriteSector(WriteBuff, 18, 1, 2); // 写入两字节数据
W25qxx_ReadSector(ReadBuff, 18, 1, 2);   // 读取两字节数据
printf("read data is 0x%x, 0x%x\n", ReadBuff[0], ReadBuff[1]);

6、其他

6.1 芯片擦除

由于FLASH存储器的特性决定了它只能把原来为“1”的数据位改写成“0”,而原来为“0”的数据位不能直接改写为“1”。 所以这里涉及到数据“擦除”的概念,在写入前,必须要对目标存储矩阵进行擦除操作,把矩阵中的数据位擦除为“1”, 在数据写入的时候,如果要存储数据“1”,那就不修改存储矩阵,在要存储数据“0”时,才更改该位。

作为测试,我们更改示例代码的内容,,读取一个擦除后,没有被编程的地址:

W25qxx_Init();                           // 初始化Flash芯片
W25qxx_EraseChip();                      // 擦除整个芯片
W25qxx_WriteSector(WriteBuff, 18, 1, 2); // 写入两字节数据
W25qxx_ReadSector(ReadBuff, 18, 0, 2);   // 读取两字节数据
printf("read data is 0x%x, 0x%x\n", ReadBuff[0], ReadBuff[1]);

会发现,打印的结果是

0xff, 0x11

0xff的出现正是擦除后,每一位都变成了1。

6.2 没有掉电功能

这个开源代码包含了常用的功能,但是没有power down等不常用的功能。

6.3 这个开源代码适用其他w25qxx型号

6.4 FatFs

用flash存储少量信息没有问题,如果存储大量信息,可以考虑上文件系统,可以关注我的文章。

配套例程和源码

配套资源,0积分下载

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32F1系列微控制器支持SPI接口,可以使用这种接口来读写W25Q128这种类型的SPI Flash存储器。 要读写W25Q128,你需要首先配置STM32F1的SPI接口,然后通过SPI接口与W25Q128进行通信。W25Q128有许多不同的操作指令,你可以使用这些指令来读取或写入存储器中的数据。 具体的步骤如下: 1. 配置STM32F1的SPI接口。这包括设置SPI时钟、工作模式和其他相关参数。 2. 发送操作指令给W25Q128。比如,你可以使用"读指令"来读取存储器中的数据,或者使用"写指令"来写入数据。 3. 发送地址信息。在读写存储器时,你需要指定具体的地址。 4. 读写数据。根据你所使用的操作指令,你可以从存储器中读取数据或者将数据写入存储器中。 在进行读写操作之前,你还需要了解W25Q128的具体操作规则和格式,并确保你的代码能够正确地执行这些操作。 ### 回答2: STM32F1系列微控制器是一种高性能、低功耗的ARM Cortex-M3内核处理器。W25Q128是一种高性能的串行闪存存储器,具有128Mb的存储容量。下面是关于如何在STM32F1读写W25Q128的简要说明。 首先,我们需要连接STM32F1和W25Q128。可以使用SPI总线连接这两个设备。在STM32F1的SPI外设配置寄存器(SPI_CR1)中,设置好SPI的时钟极性和相位,选择合适的帧格式和数据大小。然后,配置STM32F1的GPIO引脚用于SPI通信的时钟(SCK)和数据(MISO和MOSI)线路。 在STM32F1中,可以使用HAL库提供的相关函数来实现对W25Q128的读写。首先,使用HAL_SPI_Init函数对SPI外设进行初始化。然后,使用HAL_SPI_Transmit函数发送写命令和地址到W25Q128,指示要写入的数据的位置。接下来,使用HAL_SPI_Transmit函数发送要写入的数据。最后,使用HAL_SPI_Receive函数接收来自W25Q128的回复。同样,使用HAL_SPI_TransmitReceive函数可以同时发送和接收数据。 读取W25Q128的数据也是类似的过程。首先,使用HAL_SPI_Init函数对SPI外设进行初始化。然后,使用HAL_SPI_Transmit函数发送读命令和地址到W25Q128,指示要读取的数据的位置。接下来,使用HAL_SPI_Receive函数接收来自W25Q128的数据。 需要注意的是,W25Q128的读写操作需要遵循其数据手册中的时序和命令序列。并且还需要按照W25Q128存储器布局,正确配置读写操作的地址和数据。 总结起来,通过合理配置STM32F1的SPI外设和引脚连接,使用HAL库提供的相关函数,我们就可以在STM32F1上实现对W25Q128的读写操作。 ### 回答3: STM32F1系列微控制器是一种基于ARM Cortex-M3内核的高性能单片机,而W25Q128是一款容量为128Mb的闪存芯片,可提供快速的数据存储和读取。下面是一个关于如何在STM32F1上读写W25Q128的简要说明: 首先,我们需要了解一些基本的硬件连接。W25Q128STM32F1之间需要建立SPI通信接口。在STM32F1上有多个SPI接口,可以选择任意一个可用的SPI接口进行连接。 接下来,我们需要在STM32F1上编写代码来实现与W25Q128之间的数据传输。可以使用STM32CubeMX配置SPI接口和GPIO引脚,并生成基本的初始化代码。然后,我们需要编写适当的C代码来进行读写操作。 首先,我们需要初始化SPI接口的设置,包括时钟速度、数据传输模式和数据位宽等。然后,我们需要在STM32F1上配置GPIO引脚来作为片选引脚和SPI通信引脚。 对于读操作,我们需要发送读命令给W25Q128,并接收返回的数据。首先,我们将片选引脚置低,然后发送读命令和要读取的起始地址。通过SPI接口将数据从W25Q128读取到STM32F1的缓冲区中,并根据需要持续进行读取。 对于写操作,我们需要发送写命令给W25Q128,并传输要写入的数据。首先,我们将片选引脚置低,然后发送写命令和要写入的起始地址。然后,我们通过SPI接口将数据从STM32F1发送到W25Q128,并根据需要持续进行写入。 在读写过程完成后,我们需要将片选引脚置高,表示与W25Q128的通信结束。 以上是关于在STM32F1上读写W25Q128的一个简要说明。要实现更复杂的功能,可能需要对SPI接口和命令进行更详细的了解,并对代码进行适当的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值