教程:AT32F435 QSPI 读写W25Q256

您所在的位置:网站首页 stm32扇区擦除最小 教程:AT32F435 QSPI 读写W25Q256

教程:AT32F435 QSPI 读写W25Q256

2023-06-01 14:01| 来源: 网络整理| 查看: 265

本文使用的是雅特力 AT32F435VGT7作为测试QSPI接口的单片机主要参数如下:

封装:LQFP100 Flash:1024KB RAM:384KB 最大主频:288MHz QSPI接口Flash:W25Q256FVEG QSPI接口为2个 这里使用的是QSPI1

使用的接口为QSPI1,引脚对应如下:

单片机引脚引脚定义W25Q256引脚35QSPI_IO05脚DI32QSPI_IO12脚DO33QSPI_IO23脚WP34QSPI_IO37脚HOLD36QSPI_SCK6脚CLK47QSPI_CS1脚CS#

如下图所示: W25Q256引脚图MCU引脚图 AT32F435的QSPI简介: 官方文档参考: 链接: AN0088_AT32_MCU_QSPI_Application_Note_ZH_V2.0.0在这里插入图片描述

W25Q256需要几个重要的命令如下表:

命令类型命令说明W25X_WriteEnable0x06写使能W25X_ReadStatusReg10x05读状态寄存器1W25X_ReadStatusReg20x35读状态寄存器2W25X_ReadStatusReg30x15读状态寄存器3W25X_WriteStatusReg20x31写状态寄存器2W25X_ManufactDeviceID0x90读手册IDW25X_Enable4ByteAddr0xB7使能4字节地址模式W25X_ChipErase0xC7全片擦除W25X_SectorErase0x20扇区擦除W25X_EnterQPIMode0x38使能QSPI模式W25X_SetReadParam0xC0设置读速度W25X_FastReadData0x0B快速读取数据W25X_PageProgram0x02页编程

这里参考正点原子STM32F767开发文档说明:

状态寄存器3S23S22S21S20S19S18S17S16位说明HODL/RSTDRV1DRV0WPSADPADS 状态寄存器2S15S14S13S12S11S10S9S8位说明SUSCMPLB3LB2LB1QESRP1 状态寄存器1S7S6S5S4S3S2S1S0位说明SRP0TBBP3BP2BP1BP0BUSY

上面三个状态寄存器,我们只关心我们需要用到的一些位:ADS、QE 和 BUSY 位。其他位 的说明,请看 W25Q256 的数据手册。

ADS 位,表示 W25Q256 当前的地址模式,是一个只读位,当 ADS=0 的时候,表示当前是 3 字节地址模式,当 ADS=1 的时候,表示当前是 4 字节地址模式,我们需要使用 4 字节地址模 式,所以在读取到该位为 0 的时候,必须通过 W25X_Enable4ByteAddr 指令,设置为 4 字节地 址模式。

QE 位,用于使能 4 线模式(Quad),此位可读可写,并且是可以保存的(掉电后可以继续 保持上一次的值)。在本章,我们需要用到 4 线模式,所以在读到该位为 0 的时候,必须通过 W25X_WriteStatusReg2 指令设置此位为 1,表示使能 4 线模式。

BUSY 位,用于表示擦除/编程操作是否正在进行,当擦除/编程操作正在进行时,此位为 1, 此时 W25Q256 不接受任何指令,当擦除/编程操作完成时,此位为 0。此位为只读位,我们在执 行某些操作的时候,必须等待此位为 0。

W25X_ManufactDeviceID 指令,用于读取 W25Q256 的 ID,可以用于判断 W25Q256 是否正常。对于 W25Q256 来说:MF[7:0]=0XEF,ID[7:0]=0X18。

W25X_EnterQPIMode 指令,用于设置 W25Q256 进入 QPI 模式。上电时,W25Q256 默认是 SPI 模式,我们需要通过该指令设置其进入 QPI 模式。注意:在发送该指令之前,必须先设置状态 寄存器 2 的 QE 位为 1!!

W25X_Enable4ByteAddr 指令,用于设置 W25Q256 进入 4 字节地址模式。当读取到 ADS 位为 0 的时候,我们必须通过此指令将 W25Q256 设置为 4 字节地址模式,否则将只能访问 16MB 的地 址空间。

W25X_SetReadParam 指令,可以用于设置读参数控制位 P[5:4],具体参考数据手册 我们这里设置 P[5:4]=11,即可工作在 104Mhz的时钟频率下。此时,读取数据时的 dummy 时钟个数为 8 个(参见 W25X_FastReadData 指令)

W25X_WriteEnable 指令,用于设置 W25Q256 写使能。在执行擦除、编程、写状态寄存器等 操作之前,都必须通过该指令,设置 W25Q256 写使能,否则无法写入。

W25X_FastReadData 指令,用于读取 FLASH 数据,在发送完该指令以后,就可以读取 W25Q256 的数据了。该指令发送完成后,我们可以持续读取 FLASH 里面的数据,只要不停的给时钟,就 可以不停的读取数据。

W25X_PageProgram 指令,用于编程 FLASH(写入数据到 FLASH),该指令发送完成后,最 多可以一次写入 256 字节到 W25Q256,超过 256 字节则需要多次发送该指令。

W25X_SectorErase 指令,用于擦除一个扇区(4KB)的数据。因为 FLASH 具有只可以写 0, 不可以写 1 的特性,所以在写入数据的时候,一般需要先擦除(归 1),再写。W25Q256 的最小 擦除单位为一个扇区(4KB)。该指令在写入数据的时候,经常要有用。

W25X_ChipErase 指令,用于全片擦除 W25Q256。

接下来设置W25Q256的初始化步骤: 一 初始化AT32 QSPI接口IO引脚并设置为复用

gpio_init_type gpio_init_struct; crm_periph_clock_enable(CRM_QSPI1_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); gpio_default_para_init(&gpio_init_struct); //io0 gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = GPIO_PINS_0; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE0, GPIO_MUX_10); //io1 gpio_init_struct.gpio_pins = GPIO_PINS_7; gpio_init(GPIOA, &gpio_init_struct); gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_10); //io2 gpio_init_struct.gpio_pins = GPIO_PINS_4; gpio_init(GPIOC, &gpio_init_struct); gpio_pin_mux_config(GPIOC, GPIO_PINS_SOURCE4, GPIO_MUX_10); //io3 gpio_init_struct.gpio_pins = GPIO_PINS_5; gpio_init(GPIOC, &gpio_init_struct); gpio_pin_mux_config(GPIOC, GPIO_PINS_SOURCE5, GPIO_MUX_10); //sck gpio_init_struct.gpio_pins = GPIO_PINS_1; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE1, GPIO_MUX_9); //cs gpio_init_struct.gpio_pins = GPIO_PINS_10; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE10, GPIO_MUX_9);

二 切换 QSPI 控制器到 XIP 模式或命令从模式

qspi_xip_enable(QSPI1, FALSE);

三 设置 HCLK 到 SCLK 的分频 这里时钟288Mhz 设置为4分频就是72MHz

qspi_clk_division_set(QSPI1, QSPI_CLK_DIV_4);

四 设置 SCLK 在 idle 时的电位

qspi_sck_mode_set(QSPI1, QSPI_SCK_MODE_0);

五 设置 FLASH 规格中 Status 的 WIP 位置

qspi_busy_config(QSPI1, QSPI_BUSY_OFFSET_0);

六 使能QSPI模式

W25Qxx_QSPI_Enable();

七 设置为4字节地址模式,否则只能读到16MB

W25Qxx_QSPI_4ByteAdd();

八 设置QSPI模式为最大时钟104MHz

W25Qxx_QSPI_MaxSCK();

杰西莱展示QSPI具体的QSPI.c和QSPI.h和main.c文件 一 QSPI.h文件

#ifndef __QSPIFLASH_H #define __QSPIFLASH_H #include "system.h" //指令表 #define W25X_WriteEnable 0x06 #define W25X_WriteDisable 0x04 #define W25X_ReadStatusReg1 0x05 #define W25X_ReadStatusReg2 0x35 #define W25X_ReadStatusReg3 0x15 #define W25X_WriteStatusReg1 0x01 #define W25X_WriteStatusReg2 0x31 #define W25X_WriteStatusReg3 0x11 #define W25X_ReadData 0x03 #define W25X_FastReadData 0x0B #define W25X_FastReadDual 0x3B #define W25X_PageProgram 0x02 #define W25X_QPIPageProgram 0x32 #define W25X_BlockErase 0xD8 #define W25X_SectorErase 0x20 #define W25X_ChipErase 0xC7 #define W25X_PowerDown 0xB9 #define W25X_ReleasePowerDown 0xAB #define W25X_DeviceID 0xAB #define W25X_ManufactDeviceID 0x90 #define W25X_JedecDeviceID 0x9F #define W25X_Enable4ByteAddr 0xB7 #define W25X_Exit4ByteAddr 0xE9 #define W25X_SetReadParam 0xC0 #define W25X_EnterQPIMode 0x38 #define W25X_ExitQPIMode 0xFF void W25Qxx_QSPI_Init(void); void W25Qxx_QSPI_Enable(void); u16 W25Qxx_QSPI_readID(void); void W25Qxx_QSPI_4ByteAdd(void); void W25Qxx_QSPI_MaxSCK(void); void W25Qxx_QSPI_EraseChip(void); void W25Qxx_QSPI_EraseSector(u32 Addr); void W25Qxx_QSPI_Page(u8* pbuff,u32 Addr,u16 wlen); void W25Qxx_QSPI_Read(u8* pbuff,u32 Addr,u16 rlen); void W25Qxx_QSPI_Write(u8* pBuffer,u32 WriteAddr,u16 wlen); #endif

二 QSPI.c文件

#include "QSPIFlash.h" #include "CH340N.h" u8 W25Qxx_QSPI_readSR(u8 cmd); void W25Qxx_QSPI_SendCMD(u8 cmd); void W25Qxx_QSPI_writeSR(u8 cmd,u8 data); //初始化 void W25Qxx_QSPI_Init(void) { gpio_init_type gpio_init_struct; crm_periph_clock_enable(CRM_QSPI1_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); gpio_default_para_init(&gpio_init_struct); //io0 gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = GPIO_PINS_0; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE0, GPIO_MUX_10); //io1 gpio_init_struct.gpio_pins = GPIO_PINS_7; gpio_init(GPIOA, &gpio_init_struct); gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_10); //io2 gpio_init_struct.gpio_pins = GPIO_PINS_4; gpio_init(GPIOC, &gpio_init_struct); gpio_pin_mux_config(GPIOC, GPIO_PINS_SOURCE4, GPIO_MUX_10); //io3 gpio_init_struct.gpio_pins = GPIO_PINS_5; gpio_init(GPIOC, &gpio_init_struct); gpio_pin_mux_config(GPIOC, GPIO_PINS_SOURCE5, GPIO_MUX_10); //sck gpio_init_struct.gpio_pins = GPIO_PINS_1; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE1, GPIO_MUX_9); //cs gpio_init_struct.gpio_pins = GPIO_PINS_10; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE10, GPIO_MUX_9); qspi_xip_enable(QSPI1, FALSE); qspi_clk_division_set(QSPI1, QSPI_CLK_DIV_4); qspi_sck_mode_set(QSPI1, QSPI_SCK_MODE_0); qspi_busy_config(QSPI1, QSPI_BUSY_OFFSET_0); W25Qxx_QSPI_Enable(); W25Qxx_QSPI_4ByteAdd(); W25Qxx_QSPI_MaxSCK(); } //使能QSPI 4线模式 void W25Qxx_QSPI_Enable(void) { u8 state=0; qspi_cmd_type qspi_cmd_struct; //读状态寄存器2 qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_ReadStatusReg2; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = 0; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_0_BYTE; qspi_cmd_struct.data_counter = 1; qspi_cmd_struct.second_dummy_cycle_num = 0; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_111; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = FALSE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); while(qspi_flag_get(QSPI1, QSPI_RXFIFORDY_FLAG) == RESET); state=qspi_byte_read(QSPI1); while(qspi_flag_get(QSPI1, QSPI_CMDSTS_FLAG) == RESET); qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); if((state&0x02)==0) { //发送写使能 qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_WriteEnable; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = 0; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_0_BYTE; qspi_cmd_struct.data_counter = 0; qspi_cmd_struct.second_dummy_cycle_num = 0; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_111; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = TRUE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); while(qspi_flag_get(QSPI1, QSPI_CMDSTS_FLAG) == RESET); qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); //写状态寄存器 state|=1 qspi_cmd_type qspi_cmd_struct; qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_WriteEnable; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = 0; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_0_BYTE; qspi_cmd_struct.data_counter = 0; qspi_cmd_struct.second_dummy_cycle_num = 0; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_444; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = TRUE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); while(qspi_flag_get(QSPI1, QSPI_CMDSTS_FLAG) == RESET); qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); } //设置4字节地址模式 void W25Qxx_QSPI_4ByteAdd(void) { qspi_cmd_type qspi_cmd_struct; qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_Enable4ByteAddr; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = 0; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_0_BYTE; qspi_cmd_struct.data_counter = 0; qspi_cmd_struct.second_dummy_cycle_num = 0; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_444; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = TRUE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); while(qspi_flag_get(QSPI1, QSPI_CMDSTS_FLAG) == RESET); qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); } //忙检查 void W25Qxx_QSPI_Busy(void) { u8 state=0; qspi_cmd_type qspi_cmd_struct; do { qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_ReadStatusReg1; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = 0; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_0_BYTE; qspi_cmd_struct.data_counter = 1; qspi_cmd_struct.second_dummy_cycle_num = 0; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_444; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = FALSE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); while(qspi_flag_get(QSPI1, QSPI_RXFIFORDY_FLAG) == RESET); state=qspi_byte_read(QSPI1); while(qspi_flag_get(QSPI1, QSPI_CMDSTS_FLAG) == RESET); qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); }while(state&0x01); } //设置读最大时钟104MHz void W25Qxx_QSPI_MaxSCK(void) { u8 data=0; qspi_cmd_type qspi_cmd_struct; W25Qxx_QSPI_writeEN(); W25Qxx_QSPI_Busy(); data=3 qspi_cmd_type qspi_cmd_struct; W25Qxx_QSPI_writeEN(); qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_SectorErase; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = Addr; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_4_BYTE; qspi_cmd_struct.data_counter = 0; qspi_cmd_struct.second_dummy_cycle_num = 0; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_444; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = TRUE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); while(qspi_flag_get(QSPI1, QSPI_CMDSTS_FLAG) == RESET); qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); W25Qxx_QSPI_Busy(); } //读取数据 void W25Qxx_QSPI_Read(u8* pbuff,u32 Addr,u16 rlen) { u16 len=0,i=0; qspi_cmd_type qspi_cmd_struct; qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_FastReadData; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = Addr; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_4_BYTE; qspi_cmd_struct.data_counter = rlen; qspi_cmd_struct.second_dummy_cycle_num = 8; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_444; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = FALSE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); do { if(rlen>=128) //FIFO最大128字节 len=128; else len=rlen; while(qspi_flag_get(QSPI1, QSPI_RXFIFORDY_FLAG) == RESET); for(i = 0; i } qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); } // 页写入 最大256字节 void W25Qxx_QSPI_Page(u8* pbuff,u32 Addr,u16 wlen) { u16 len=0,i=0; qspi_cmd_type qspi_cmd_struct; do { W25Qxx_QSPI_writeEN(); W25Qxx_QSPI_Busy(); qspi_cmd_struct.pe_mode_enable = FALSE; qspi_cmd_struct.pe_mode_operate_code = 0; qspi_cmd_struct.instruction_code = W25X_PageProgram; qspi_cmd_struct.instruction_length = QSPI_CMD_INSLEN_1_BYTE; qspi_cmd_struct.address_code = Addr; qspi_cmd_struct.address_length = QSPI_CMD_ADRLEN_4_BYTE; qspi_cmd_struct.data_counter = wlen; qspi_cmd_struct.second_dummy_cycle_num = 0; qspi_cmd_struct.operation_mode = QSPI_OPERATE_MODE_444; qspi_cmd_struct.read_status_config = QSPI_RSTSC_HW_AUTO; qspi_cmd_struct.read_status_enable = FALSE; qspi_cmd_struct.write_data_enable = TRUE; qspi_cmd_operation_kick(QSPI1,&qspi_cmd_struct); if(wlen>=128) len=128; else len=wlen; for(i = 0; i u16 pageremain; pageremain=256-WriteAddr%256; //单页剩余的字节数 if(wlen pBuffer+=pageremain; WriteAddr+=pageremain; wlen-=pageremain; //减去已经写入了的字节数 if(wlen>256) pageremain=256; //一次可以写入256个字节 else pageremain=wlen; //不够256个字节了 } } } //数据写入函数 u8 W25QXX_BUFFER[4096]; void W25Qxx_QSPI_Write(u8* pBuffer,u32 WriteAddr,u16 wlen) { u32 secpos; u16 secoff; u16 secremain; u16 i; u8 * W25QXX_BUF; W25QXX_BUF=W25QXX_BUFFER; secpos=WriteAddr/4096;//扇区地址 secoff=WriteAddr%4096;//在扇区内的偏移 secremain=4096-secoff;//扇区剩余空间大小 //printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//测试用 if(wlen if(W25QXX_BUF[secoff+i]!=0XFF)break;//需要擦除 } if(i W25QXX_BUF[i+secoff]=pBuffer[i]; } W25Qx_QSPI_wNoCheck(W25QXX_BUF,secpos*4096,4096);//写入整个扇区 } else W25Qx_QSPI_wNoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间. if(wlen==secremain) break;//写入结束了 else//写入未结束 { secpos++;//扇区地址增1 secoff=0;//偏移位置为0 pBuffer+=secremain; //指针偏移 WriteAddr+=secremain; //写地址偏移 wlen-=secremain;//字节数递减 if(wlen>4096) secremain=4096; //下一个扇区还是写不完 else secremain=wlen; //下一个扇区可以写完了 } }; }

三main.c文件

#include "system.h" #include "at32f435_437_clock.h" #include "CH340N.h" #include "Time_APP.h" #include "QSPIFlash.h" u8 buf1[]="10086111"; u8 buf2[20]={0}; int main(void) { u8 state1=0,state2=0,state3=0; system_clock_config(); SYS_clock_Init(); SYS_nvic_config(); User_Time_Init(); CH340N_Init(115200); W25Qxx_QSPI_Init(); CH340_Printf("AT32 MCU init\r\n"); CH340_Printf("Flash ID:%04X\r\n",W25Qxx_QSPI_readID()); CH340_Printf("Erase done\r\n"); W25Qxx_QSPI_EraseSector(0); W25Qxx_QSPI_Page(buf1,0,strlen((char *)buf1)); W25Qxx_QSPI_Read(buf2,0,strlen((char *)buf1)); CH340_Printf("read:%s\r\n",buf2); while(1) { } }

到这里文章已完结,后续测试一下读写的速度。以上内容如有侵权请联系我删除。 个人微信:LLQuser 注明来意。也可技术交流

转载本文章请注明出处



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3