stm32 SPI-FLASH W25Q64

时间:2022-01-17 00:50:19

The W25Q64BV array is organized into 32,768 programmable pages of 256-bytes each. Up to 256 bytes can be programmed at a time. Pages can be erased in groups of 16 (sector erase), groups of 128 (32KB block erase), groups of 256 (64KB block erase) or the entire chip (chip erase)

BUSY is a read only bit in the status register (S0) that is set to a 1 state when the device is executing a Page Program, Sector Erase, Block Erase, Chip Erase or Write Status Register instruction

W25Q64

stm32 SPI-FLASH W25Q64

stm32 SPI-FLASH W25Q64

stm32 SPI-FLASH W25Q64

SPI配置步骤

1.使能SPI时钟

2.使能GPIO端口时钟

3.初始化GPIO,配置引脚模式

4.初始化SPI

5.使能SPI

6.SPI读写数据

7.查看SPI传输状态

stm32 SPI-FLASH W25Q64

举例

stm32 SPI-FLASH W25Q64

stm32 SPI-FLASH W25Q64

stm32 SPI-FLASH W25Q64

stm32 SPI-FLASH W25Q64

stm32 SPI-FLASH W25Q64

stm32 SPI-FLASH W25Q64

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; //CRC多项式寄存器
}SPI_InitTypeDef; #define EN25X_WriteEnable 0x06
#define EN25X_WriteDisable 0x04
#define EN25X_ReadStatusReg 0x05
#define EN25X_WriteStatusReg 0x01
#define EN25X_ReadData 0x03
#define EN25X_FastReadData 0x0B
#define EN25X_FastReadDual 0x3B
#define EN25X_PageProgram 0x02
#define EN25X_BlockErase 0xD8
#define EN25X_SectorErase 0x20
#define EN25X_ChipErase 0xC7
#define EN25X_PowerDown 0xB9
#define EN25X_Continue_Read 0xFF
#define EN25X_ReleasePowerDown 0xAB
#define EN25X_DeviceID 0xAB
#define EN25X_ManufactDeviceID 0x90
#define EN25X_JedecDeviceID 0x9F void SPI_init()
{
GPIO_InitTypeDef gpio =
{
GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15,
GPIO_Speed_50MHz,
GPIO_Mode_AF_PP
}; SPI_InitTypeDef spi =
{
SPI_Direction_2Lines_FullDuplex,
SPI_Mode_Master, //0x0104
SPI_DataSize_8b,
SPI_CPOL_High,
SPI_CPHA_2Edge,
SPI_NSS_Soft,
SPI_BaudRatePrescaler_256,
SPI_FirstBit_MSB,
7
}; RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); //使能SPI时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIO端口时钟 GPIO_Init(GPIOB, &gpio); //初始化GPIO,配置引脚模式 SPI_Init(SPI2, &spi); //初始化SPI SPI_Cmd(SPI2, ENABLE); //使能SPI
} void SPI2_SetSpeed(u8 rate)
{
SPI2->CR1 &= 0xFFC7;
SPI2->CR1 |= rate;
SPI_Cmd(SPI2, ENABLE);
} void EN25Q64_init()
{
GPIO_InitTypeDef gpiob =
{
GPIO_Pin_12,
GPIO_Speed_50MHz,
GPIO_Mode_Out_PP
}; GPIO_InitTypeDef gpiog13 =
{
GPIO_Pin_13,
GPIO_Speed_50MHz,
GPIO_Mode_Out_PP
}; GPIO_InitTypeDef gpiog14 =
{
GPIO_Pin_13,
GPIO_Speed_50MHz,
GPIO_Mode_Out_PP
}; GPIO_InitTypeDef gpiof =
{
GPIO_Pin_9,
GPIO_Speed_50MHz,
GPIO_Mode_Out_PP
}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOG | RCC_APB2Periph_GPIOF, ENABLE); GPIO_Init(GPIOB, &gpiob);
SPI2_NSS = 1; //以太网模块片选(拉高,防止干扰) GPIO_Init(GPIOG, &gpiog13);
FLASH_CS = 1; //FLASH片选 GPIO_Init(GPIOG, &gpiog14);
SD_CS = 1; //SD卡模块片选 GPIO_Init(GPIOF, &gpiof);
TUB_4 = 1; //NRF24L01模块片选 SPI_init();
} u8 SPI_read_write(u16 d) //SPI读写数据
{
while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) != SET); SPI_I2S_SendData(SPI2, d); while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != SET); return SPI_I2S_ReceiveData(SPI2);
} u16 EN25Q64_read_id()
{
u16 r; FLASH_CS = 0; SPI_read_write(EN25X_ManufactDeviceID);
SPI_read_write(0); //dummy
SPI_read_write(0);
SPI_read_write(0); r = SPI_read_write(EN25X_Continue_Read) << 8;
r = SPI_read_write(EN25X_Continue_Read); FLASH_CS = 1; return r;
} void EN25Q64_read_unique_id(u8 *id)
{
int i = 0; FLASH_CS = 0; SPI_read_write(0x4B);
SPI_read_write(0); //dummy
SPI_read_write(0);
SPI_read_write(0);
SPI_read_write(0); for(i = 0; i < 8; i++)
{
id[i] = SPI_read_write(0xFF);
} FLASH_CS = 1;
} u8 EN25Q64_read_status()
{
u8 r; FLASH_CS = 0; SPI_read_write(EN25X_ReadStatusReg);
r = SPI_read_write(EN25X_Continue_Read); FLASH_CS = 1; return r;
} void EN25Q64_read(u8 *buf, u32 addr, u16 num)
{
u16 i = 0; FLASH_CS = 0; SPI_read_write(EN25X_ReadData);
SPI_read_write((u8)(addr) >> 16); //24bit地址
SPI_read_write((u8)(addr) >> 8);
SPI_read_write((u8)addr); for(i = 0; i < num; i++)
{
buf[i] = SPI_read_write(EN25X_Continue_Read);
} FLASH_CS = 1;
} void EN25Q64_write_enable()
{
FLASH_CS = 0; SPI_read_write(EN25X_WriteEnable); FLASH_CS = 1;
} void EN25Q64_write_disable()
{
FLASH_CS = 0; SPI_read_write(EN25X_WriteEnable); FLASH_CS = 1;
} void EN25Q64_write_status(u8 s)
{
FLASH_CS = 0; SPI_read_write(EN25X_WriteDisable);
SPI_read_write(s); FLASH_CS = 1;
} void EN25Q64_is_busy()
{
while((EN25Q64_read_status() & 0x01) == 0x01); //BUSY
} void EN25Q64_write_page(u8 *buf, u32 addr, u16 num) //页写
{
u16 i = 0; EN25Q64_write_enable(); FLASH_CS = 0; SPI_read_write(EN25X_PageProgram); //Page Program
SPI_read_write(addr >> 16);
SPI_read_write(addr >> 8);
SPI_read_write(addr); for(i = 0; i < num; i++)
{
SPI_read_write(buf[i]);
} FLASH_CS = 1; EN25Q64_is_busy();
} void EN25Q64_write_nocheck(u8 *buf, u32 addr, u16 num)
{
u8 *b = buf;
u32 a = addr;
u16 n = num; n = 256 - (num % 256); //写满一页 while(1)
{
EN25Q64_write_page(b, a, n); if(n == num)
{
break;
} b += n;
a += n;
num -= n; if(num > 256)
{
n = 256;
}
else
{
n = num;
}
}
} void EN25Q64_sector_erase(u32 a)
{
EN25Q64_write_enable();
EN25Q64_is_busy(); FLASH_CS = 0; SPI_read_write(EN25X_SectorErase);
SPI_read_write((u8)a >> 16);
SPI_read_write((u8)a >> 8);
SPI_read_write(a); FLASH_CS = 1; EN25Q64_is_busy();
} u8 EN25QXX_BUF[4096];
void EN25Q64_write(u8 *buf, u32 addr, u16 num)
{
u16 i;
u32 pos;
u16 offset;
u16 n;
u8 *b = buf; pos = addr / 4096; //扇区位置
offset = addr % 4096;
n = 4096 - offset ; //写满扇区 if(num <= n)
{
n = num;
} while(1)
{
EN25Q64_read(EN25QXX_BUF, pos * 4096, 4096); //读出整个扇区 EN25Q64_sector_erase(pos); //擦除整个扇区 for(i = 0; i < n; i++)
{
EN25QXX_BUF[i + offset] = b[i];
} EN25Q64_write_nocheck(EN25QXX_BUF, pos * 4096, 4096); //写入整个扇区 if(n == num)
{
break;
} pos++;
num -= n;
offset = 0;
b += n;
if(num > 4096)
{
n = 4096;
}
else
{
n = num;
}
}
} void EN25Q64_chip_erase()
{
EN25Q64_write_enable();
EN25Q64_is_busy(); FLASH_CS = 0; SPI_read_write(EN25X_ChipErase); FLASH_CS = 1; EN25Q64_is_busy();
} void EN25Q64_power_down()
{
FLASH_CS = 0; SPI_read_write(EN25X_PowerDown); FLASH_CS = 1; delay_us(3);
} void EN25Q64_release_power_down()
{
FLASH_CS = 0; SPI_read_write(EN25X_ReleasePowerDown); FLASH_CS = 1; delay_us(3);
}

stm32 SPI-FLASH W25Q64的更多相关文章

  1. Jlink使用技巧之烧写SPI Flash存储芯片

    前言 大多数玩单片机的人都知道Jlink可以烧写Hex文件,作为ARM仿真调试器,但是知道能烧写SPI Flash的人应该不多,本篇文章将介绍如何使用JLink来烧写或者读取SPI Flash存储器, ...

  2. Nand Flash,Nor Flash,CFI Flash,SPI Flash 之间的关系

    前言:    在嵌入式开发中,如uboot的移植,kernel的移植都需要对Flash 有基本的了解.下面细说一下标题中的中Flash中的关系 一,Flash的内存存储结构    flash按照内部存 ...

  3. 关于STM32的FLASH操作【转载】

    说到STM32的FLSAH,我们的第一反应是用来装程序的,实际上,STM32的片内FLASH不仅用来装程序,还用来装芯片配置.芯片ID.自举程序等等.当然, FLASH还可以用来装数据. FLASH分 ...

  4. 【iCore、iCore2 双核心板】EPCS 实验(SPI Flash)(基于Verilog语言)

    _____________________________________ 深入交流QQ群: A: 204255896(1000人超级群,可加入) B: 165201798(500人超级群,满员) C ...

  5. nand flash&comma;nor flash&comma;spi flash&comma;片上RAM,片外RAM

    Flash有掉电数据保存的特点,RAM掉电则数据丢失,但是RAM的速度更高,擦写次数理论上没有限制,而Flash则不行. Nand Flash相比其余的几种flash优势在于可擦写次数多,擦写速度快, ...

  6. 27&period;some company&&num;39&semi;s Spi Flash chip replace altera epcsxxx

    由于altera公司的epcsxxx芯片比较贵,所以一般用其它公司的spi flash芯片代替也可以.据AlteraFAE描述:“EPCS器件也是选用某家公司的SPIFlash,只是中间经过Alter ...

  7. OpenRisc-32-ORPSoC烧写外部spi flash

    引言 经过前面的分析和介绍,我们对ORPSoC的启动过程(http://blog.csdn.net/rill_zhen/article/details/8855743)和 ORpSoC的debug子系 ...

  8. SPI FLASH与NOR FLASH的区别?

    1.SPI Flash (即SPI Nor Flash)是Nor Flash的一种: 2.NOR Flash根据数据传输的位数可以分为并行(Parallel)NOR Flash和串行(SPI)NOR ...

  9. SPI Flash&lpar;W25Q16DV&rpar; 驱动

    大体上可分为以下几个部分: 1.注册设备驱动 spi_register_driver 2.分配 mtd_info 结构体 3.配置 mtd_info 结构体 4.注册 mtd_info 结构体 构建 ...

  10. SPI Flash&lpar;W25Q16DV&rpar; 基本操作

    读取厂家\设备 ID 发送 90H 指令,再发送 00h 的地址,然后接收即可. 代码如下: void SPIFlashReadID(int *pMID, int *pDID) { SPIFlash_ ...

随机推荐

  1. 使用Python和Perl绘制北京跑步地图

    当你在一个城市,穿越大街小巷,跑步跑了几千公里之后,一个显而易见的想法是,如果能把在这个城市的所有路线全部画出来,会是怎样的景象呢? 文章代码比较多,为了不吊人胃口,先看看最终效果,上到北七家,下到南 ...

  2. 关于adb驱动

    Android设备(如手机)连接PC时所需要的驱动程序,一般Android设备连接WinXP是无需安装驱动的. adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb ...

  3. HDU 5164Matching on Array&lpar;AC自动机&rpar;

    这是BC上的一道题,当时比赛没有做,回头看看题解,说是AC自动机,想着没有写过AC自动机,于是便试着抄抄白书的模板,硬是搞了我数个小时2000ms时限1800过了= = ! 这里就直接贴上BC的结题报 ...

  4. Mac OSX操作系统安装和配置Zend Server 6教程(3)

    Zend Server安装好以后,在php.ini文件中,没有默认时区.就是导致很多警告信息出现的根本. 接下来,我们看看如果修改这个文件. 首先,进入php.ini文件.此文件在目录zend/etc ...

  5. 关于error C2872&colon; &&num;39&semi;LONG&lowbar;PTR&&num;39&semi; &colon; ambiguous symbol

    今天用VS2010创建了一个add-in工程,使用常量INVALID_HANDLE_VALUE时,编译器就提示如下错误: error C2872: 'LONG_PTR' : ambiguous sym ...

  6. C&num;设计模式之二工厂方法模式(Factory Method Pattern)【创建型】

    一.引言 在上一篇文章中我们讲解了过渡的一种模式叫做[简单工厂],也有叫[静态工厂]的,通过对简单工厂模式得了解,我们也发现了它的缺点,就是随着需求的变化我们要不停地修改工厂里面的方法的代码,需求变化 ...

  7. jQuery第七章插件的编写和使用

    1.本章目标 编写jquery插件 2.插件 也称为扩展,是一种按照一定的规范的应用程序接口编写出来的程序 插件的目标是给已有的一系列函数做一个封装,以便在其他的地方复用,方便维护和开发效率 3.jq ...

  8. Git使用教程:最详细、最傻瓜、最浅显、真正手把手教!

    Git使用教程:最详细.最傻瓜.最浅显.真正手把手教! 蘇小小 Web项目聚集地 9月16日 作者 | 蘇小小 编辑 | 王久一 来源 | 慕课网 导读:因为教程详细,所以行文有些长,新手边看边操作效 ...

  9. Python 函数 &lpar;关键字参数&rpar;

    关键字参数 可变参数允许你传入0个或者任意个参数,这些可变参数在函数调用时会自动组装成一个tuple,而关键字参数允许你传入0个或者任意个含参数名的参数,这些参数在函数内部自动组装成为一个dict d ...

  10. Java多线程-----Thread常用方法

    1.public Thread(Runnable target,String name) 创建一个有名称的线程对象 package com.thread.mothed; public class Th ...