华大FLASH之w25Q系列

news2024/11/27 0:21:26

W25Q64JV的标准/双/四SPl指令集由48条基本指令组成,这些指令通过SPI总线完全控制(见指令集表1-2)。
指令从芯片选择(/CS)的下降沿开始。时钟输入DI输入的第一字节数据提供指令代码。DI输入上的数据在时钟的上升沿上采样,
最高有效位(MSB)优先。指令的长度从单个字节到几个字节不等,后面可能是地址字节、数据字节、虚拟字节(无需在意),
在某些情况下还可能是组合。指令以edge/CS的上升沿完成。每条指令的时钟相对时序图如图5至57所示。所有读取指令都可以在
任何时钟位之后完成。但是,所有写、编程或擦除指令都必须在字节边界上完成(/CS驱动高电平,在时钟位满8位之后),
否则该指令将被忽略。此功能进一步保护设备免受无意写入。此外,当存储器被编程或擦除时,或者当状态寄存器被写入时,
除了读取状态寄存器之外的所有指令都将被忽略,直到编程或擦除周期完成。

 读写接口都是先发送cmd,即是表中的byte1,而后发送或者接收信息,SPI访问接口这里暂不延升。

#define LOAD_CMD(a, cmd, addr)  do  {                                       \
                                        (a)[0U] = (cmd);                    \
                                        (a)[1U] = (uint8_t)((addr) >> 16U); \
                                        (a)[2U] = (uint8_t)((addr) >> 8U);  \
                                        (a)[3U] = (uint8_t)(addr);          \
                                    } while (0U)


static void W25QXX_Wt(uint8_t u8Cmd, uint32_t u32Address, const uint8_t *pu8Data, uint32_t u32DataLength)
{
    uint8_t au8Cmd[4U];

    LOAD_CMD(au8Cmd, u8Cmd, u32Address);

    W25Q_CS_ACTIVE();
    (void)BSP_W25Q_SPI_Transmit(au8Cmd, 4U);
    (void)BSP_W25Q_SPI_Transmit(pu8Data, u32DataLength);
    W25Q_CS_INACTIVE();
}

static void W25QXX_Rd(uint8_t u8Cmd, uint32_t u32Address, uint8_t *pu8Data, uint32_t u32DataLength)
{
    uint8_t au8Cmd[4U];

    LOAD_CMD(au8Cmd, u8Cmd, u32Address);

    W25Q_CS_ACTIVE();
    (void)BSP_W25Q_SPI_Transmit(au8Cmd, 4U);
    (void)BSP_W25Q_SPI_Receive(pu8Data, u32DataLength);
    W25Q_CS_INACTIVE();
}


static void W25QXX_WriteCmd(uint8_t u8Cmd, const uint8_t *pu8CmdData, uint32_t u32CmdDataLength)
{
    W25Q_CS_ACTIVE();
    (void)BSP_W25Q_SPI_Transmit(&u8Cmd, 1U);
    (void)BSP_W25Q_SPI_Transmit(pu8CmdData, u32CmdDataLength);
    W25Q_CS_INACTIVE();
}

static void W25QXX_ReadCmd(uint8_t u8Cmd, uint8_t *pu8CmdData, uint32_t u32CmdDataLength,
                         uint8_t *pu8Info, uint8_t u8InfoLength)
{
    W25Q_CS_ACTIVE();
    (void)BSP_W25Q_SPI_Transmit(&u8Cmd, 1U);
    (void)BSP_W25Q_SPI_Transmit(pu8CmdData, u32CmdDataLength);
    (void)BSP_W25Q_SPI_Receive(pu8Info, (uint32_t)u8InfoLength);
    W25Q_CS_INACTIVE();
}

define W25Q_WRITE_ENABLE                   ((uint8_t)0x06U)
#define W25Q_VOLATILE_SR_WRITE_ENABLE       ((uint8_t)0x50U)
#define W25Q_WRITE_DISABLE                  ((uint8_t)0x04U)
#define W25Q_READ_STATUS_REG_1              ((uint8_t)0x05U)
#define W25Q_READ_STATUS_REG_2              ((uint8_t)0x35U)
#define W25Q_WRITE_STATUS_REG               ((uint8_t)0x01U)
#define W25Q_PAGE_PROGRAM                   ((uint8_t)0x02U)
#define W25Q_SECTOR_ERASE                   ((uint8_t)0x20U)
#define W25Q_BLOCK_ERASE_32K                ((uint8_t)0x52U)
#define W25Q_BLOCK_ERASE_64K                ((uint8_t)0xD8U)
#define W25Q_CHIP_ERASE                     ((uint8_t)0xC7U)
#define W25Q_ERASE_PROGRAM_SUSPEND          ((uint8_t)0x75U)
#define W25Q_ERASE_PROGRAM_RESUME           ((uint8_t)0x7AU)
#define W25Q_POWER_DOWN                     ((uint8_t)0xB9U)
#define W25Q_READ_DATA                      ((uint8_t)0x03U)
#define W25Q_FAST_READ                      ((uint8_t)0x0BU)
#define W25Q_DEVICE_ID                      ((uint8_t)0xABU)
#define W25Q_RELEASE_POWER_DOWN             (W25Q_DEVICE_ID)
#define W25Q_MANUFACTURER_DEVICE_ID         ((uint8_t)0x90U)
#define W25Q_JEDEC_ID                       ((uint8_t)0x9FU)
#define W25Q_READ_UNIQUE_ID                 ((uint8_t)0x4BU)
#define W25Q_READ_SFDP_REG                  ((uint8_t)0x5AU)
#define W25Q_REASE_SECURITY_REG             ((uint8_t)0x44U)
#define W25Q_PROGRAM_SECURITY_REG           ((uint8_t)0x42U)
#define W25Q_READ_SECURITY_REG              ((uint8_t)0x48U)
#define W25Q_ENABLE_QPI                     ((uint8_t)0x38U)
#define W25Q_ENABLE_RESET                   ((uint8_t)0x66U)
#define W25Q_RESET                          ((uint8_t)0x99U) 

#define W25Q_ST_BUSY                ((uint16_t)W25Q_BIT_0)
#define W25Q_ST_WEL                 ((uint16_t)W25Q_BIT_1) 

1,使能去使能flash 

static void W25QXX_WriteEnable(void)
{
    W25QXX_WriteCmd(W25Q_WRITE_ENABLE, NULL, 0U);
}

static void W25QXX_WriteDisable(void)
{
    W25QXX_WriteCmd(W25Q_WRITE_DISABLE, NULL, 0U);
}

2,检测flash busy忙状态:

uint16_t W25QXX_ReadStatus(void)
{
    uint8_t  u8TempStatus;
    uint16_t u16RetStatus;

    W25QXX_ReadCmd(W25Q_READ_STATUS_REG_2, NULL, 0U, &u8TempStatus, 1U);

    u16RetStatus = u8TempStatus;

    W25QXX_ReadCmd(W25Q_READ_STATUS_REG_1, NULL, 0U, &u8TempStatus, 1U);

    u16RetStatus <<= 8U;
    u16RetStatus |= u8TempStatus;

    return u16RetStatus;
}

static void W25QXX_WaitBusy(void)
{
    while ((W25QXX_ReadStatus() & W25Q_ST_BUSY) == W25Q_ST_BUSY)
    {
        ;
    }
}

 3,flash的读写

static void W25QXX_WritePage(uint32_t u32Address, const uint8_t *pu8Data, uint32_t u32DataLength)
{
    W25QXX_WriteEnable();
    W25QXX_Wt(W25Q_PAGE_PROGRAM, u32Address, pu8Data, u32DataLength);
    W25QXX_WaitBusy();
}

void W25QXX_ReadData(uint32_t u32Address, uint8_t *pu8ReadBuf, uint32_t u32NumByteToRead)
{
    W25QXX_Rd(W25Q_READ_DATA, u32Address, pu8ReadBuf, u32NumByteToRead);
}

void W25QXX_WriteData(uint32_t u32Address, const uint8_t *pu8WriteBuf, uint32_t u32NumByteToWrite)
{
    uint32_t secpos;
    uint16_t secoff;
    uint16_t secremain;
    uint16_t i;
    uint8_t  *pW25QXX_BUF;
    pW25QXX_BUF = W25QXX_BUFFER;
    uint32_t u32WriteBufAddr = (uint32_t)&pu8WriteBuf;

    secpos     = u32Address / 4096U;
    secoff     = (uint16_t)(u32Address % 4096U);
    secremain  = 4096U - secoff;

    if (u32NumByteToWrite <= secremain)
    {
        secremain = (uint16_t)u32NumByteToWrite;
    }

    for(;;)
    {
        W25QXX_ReadData(secpos * 4096U, pW25QXX_BUF, 4096U); // read one sector content
        for (i = 0U; i < secremain; i++) // check if blank sector
        {
            if (pW25QXX_BUF[secoff + i] != (uint8_t)0xFFU)
            {
                break;
            }
        }

        if (i < secremain)
        {
            W25QXX_EraseSector(secpos);          // not blank, need erase
            for (i = 0U; i < secremain; i++)     // backup first
            {
                pW25QXX_BUF[i + secoff] = pu8WriteBuf[i];
            }
            W25QXX_Write_NoCheck(pW25QXX_BUF, secpos * 4096U, 4096U); // write back after erase

        }
        else
        {
            W25QXX_Write_NoCheck((const uint8_t *)u32WriteBufAddr, u32Address,secremain);
        }

        if (u32NumByteToWrite == secremain)
        {
            break;
        }
        else
        {
            secpos++;          // next sector
            secoff          = 0U;

            u32WriteBufAddr    += secremain;
            u32Address         += secremain;
            u32NumByteToWrite  -= secremain;
            if (u32NumByteToWrite > 4096U)
            {
                secremain = 4096U;
            }
            else
            {
                secremain = (uint16_t)u32NumByteToWrite;
            }
        }
    }
}

4,earse擦除flash

void W25QXX_EraseChip(void)
{
    W25QXX_WriteEnable();
    W25QXX_WaitBusy();
    W25QXX_WriteCmd(W25Q_CHIP_ERASE, NULL, 0U);
    W25QXX_WaitBusy();
}


void W25QXX_EraseSector(uint32_t u32SectorAddress)
{
    u32SectorAddress *= W25Q_SIZE_SECTOR;

    W25QXX_WriteEnable();
    W25QXX_WaitBusy();

    W25QXX_Wt(W25Q_SECTOR_ERASE, u32SectorAddress, NULL, 0U);

    W25QXX_WaitBusy();
    W25QXX_WriteDisable();
}


void W25QXX_EraseBlock(uint32_t u32BlockAddress)
{
    W25QXX_Wt(W25Q_BLOCK_ERASE_64K, u32BlockAddress, NULL, 0U);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2063032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

KCP源码解析系列(五)拥塞控制

流量控制和拥塞控制的区别 如果你约了你的朋友见面聊一件事&#xff0c;有两种沟通方式&#xff1a; 第一种是一次只说一句话&#xff0c;然后等待你的朋友回应“收到”&#xff0c;确认他在听之后&#xff0c;再说下一句话&#xff0c;如此反复&#xff0c;直到事情说完。第…

身份证二要素验证接口如何用PHP进行调用

一、什么是身份证二要素验证接口&#xff1f; 身份证二要素验证接口又叫身份证实名认证、身份实名验证、身份证核验接口、实名核验接口等&#xff0c;该接口叫法非常多&#xff0c;但是他的入参都是一样的&#xff0c;核验姓名和身份证号码是否一致&#xff0c;并返回性别、籍…

2024年了,我依然建议去创建属于自己的Google App

大环境的确不好&#xff0c;Android&#xff0c;iOS程序员都白菜价了&#xff0c;每天充斥着我们耳边的都是裁员、降薪等不好的消息&#xff0c;是不是我们移动端开发人员的日子真的到头了呢&#xff1f;大约在一年前&#xff0c;其实我也意识到这个问题&#xff0c;想学习的话…

BlazeFace: Sub-millisecond Neural Face Detection on Mobile GPUs

Abstract 我们提出了BlazeFace&#xff0c;这是一种轻量级且性能优异的面部检测器&#xff0c;专为移动GPU推理而设计。它在旗舰设备上运行速度可达200到1000 FPS。这种超实时性能使其能够应用于任何增强现实管道中&#xff0c;作为任务特定模型的输入来准确识别面部感兴趣区域…

CST软件仿真案例:圆极化平板天线仿真02

本期继续完成一款圆极化Patch天线的仿真实例。读者可以完整的了解到怎么用CST微波工作室&#xff0c;完成对一款天线建模、设置到仿真分析的完整过程。 本期中&#xff0c;我们要设计的圆极化天线尺寸如下图所示&#xff1a; 本期内容是接着上期部分开始。首先先完成仿真实例0…

k8s部署redis一主两从三哨兵(集群内访问)

一、配置清单 1.基于K8s搭建部署1主2从3哨兵的Redis集群哨兵模式(集群内访问) 2.持久化数据选择用storageclass&#xff0c;动态创建pv存储&#xff0c;动态存储使用longhorn 创建redis配置文件 #注意内容中注释 apiVersion: v1 kind: Namespace metadata:name: prod--- ap…

C#学习第二节课 ,伤害计算

伤害计算 我一直好奇游戏的伤害计算是怎么计算并输出的,这第二节课利用学过的初级语法,Console.WriteLine,Console.ReadLine(),以及基础变量,int,string 和if 判断 组合,来实现打印一下伤害计算吧! 老规矩 先上结果图 代码区域 namespace hello01 {internal class Program …

秒杀商品超出限量购买修复方法

问题:秒杀商品购买会超出限量,多买 修复: 主要修改了以下文件,如果需要了文件全部在附件中,修改的基础版本是v2.3.2如果没有二开过,可以直接覆盖替换;如果二开了,请对比处理, ⚠️注意: 这样修改完以后,可能导致之前的秒杀都库存不足无法购买 ,需要重新添加 修改的记录,以供参…

开源低代码开发工具Lowcoder

Lowcoder_CN 是一个基于Web的低代码开发平台&#xff0c;旨在通过可视化界面和丰富的API&#xff0c;支持快速应用开发、企业内部工具构建以及教育用途。 以下是对Lowcoder_CN的详细介绍&#xff1a; 一、平台特点 开源与免费&#xff1a;Lowcoder_CN是开源的&#xff0c;允许…

【ACM出版 | IEEEACM院士、CCF杰出会员担任组委| 往届会后3个半月检索 】第三届人工智能与智能信息处理国际学术会议(AIIIP 2024)

第三届人工智能与智能信息处理国际学术会议&#xff08;AIIIP 2024&#xff09;将于2024年10月25日-27日在中国-天津举行。新一代人工智能理论的快速发展为信息处理技术的提供了新方法&#xff0c;促进了智能信息处理的发展与应用。智能信息处理是信号与信息领域一个前沿、热点…

颖通控股突击巨额分红6.31亿远超净利润,滞销产品三年累计1750万

《港湾商业观察》黄懿 7月18日&#xff0c;被外界称为香水巨头的颖通控股有限公司&#xff08;下称“颖通控股”&#xff09;向港交所主板提交上市申请&#xff0c;BNP Paribas、中信证券为其联席保荐人。颖通&#xff08;上海&#xff09;贸易有限公司为其国内运营主体。 据…

[星瞳科技]OpenMV如何进行wifi通信?

OpenMV官方扩展板采用ATWINC1500模组&#xff0c;可以传输图像。 详细资料&#xff1a;http://singtown.cc/product/openmv-wifi扩展板/ 如果想使用ESP8266&#xff0c;使用串口通信就可以。 wifi扫描 无线传输图像 无线传输小球坐标 import sensor import time import netw…

基于PHP+MySQL组合开发的DIY分销商城小程序源码系统 附带源代码包以及搭建部署教程

系统概述 随着消费者对购物便捷性、个性化需求的不断增长&#xff0c;传统的电商模式已难以满足市场多样化需求。分销商城小程序以其低门槛、易传播、高粘性等特点&#xff0c;成为众多商家转型升级的首选。本源码系统正是基于这一市场需求&#xff0c;利用PHP这一成熟稳定的后…

【C++】深度解析:用 C++ 模拟实现 priority_queue类,探索其底层实现细节(仿函数、容器适配器)

目录 ⭐前言 ✨堆 ✨容器适配器 ✨仿函数 ⭐priority_queue介绍 ⭐priority_queue参数介绍 ⭐priority_queue使用 ⭐priority_queue实现 ✨仿函数实现 ✨堆的向上调整和向下调整 ✨完整代码 ⭐前言 ✨堆 堆是一种特殊的树形数据结构&#xff0c;通常以二叉树的…

AVI视频损坏了怎么修复?轻松几步解决你的困扰

在数字化时代&#xff0c;视频已成为我们记录生活、分享经验和传递信息的重要方式。AVI作为一种常见的视频格式&#xff0c;因其无损质量的特点而受到广泛欢迎。然而&#xff0c;有时候我们可能会遇到AVI视频文件损坏的情况&#xff0c;导致无法正常播放。别担心&#xff0c;本…

探索paho-mqtt:Python世界的物联网通信桥梁

文章目录 **探索paho-mqtt&#xff1a;Python世界的物联网通信桥梁**第一部分&#xff1a;背景介绍第二部分&#xff1a;paho-mqtt概览第三部分&#xff1a;安装指南第四部分&#xff1a;基础函数使用第五部分&#xff1a;实际应用场景第六部分&#xff1a;常见问题与解决方案第…

VMware vSphere Replication 虚拟机备份及迁移实践

vSphere Replication 介绍 vSphere Replication 是适用于 vSphere 的基于 Hypervisor 管理程序的异步复制解决方案&#xff0c;是 VMware vCenter Server 的扩展&#xff0c;包含在vCenter Server Standard中&#xff0c;可为环境中的所有虚拟机提供灾难恢复和数据保护。 vSph…

上午 2019

信息系统规划方法_信息系统规划有哪些方法-CSDN博客 1. 关键成功因素法&#xff08;CSF&#xff09; 在现行系统中&#xff0c;总存在着多个变量影响系统目标的实现&#xff0c;其中若干个因素是关键的和主要的&#xff08;即关键成功因素&#xff09;。通过对关键成功因素的识…

SpingBoot 两种方式配置多数据源

第一种&#xff1a;使用与MyBaits-Plus师出同门的“dynamic-datasource-spring-boot-starter” 官网地址&#xff1a; 基础必读&#xff08;免费&#xff09; dynamic-datasource 看云 1&#xff1a;引入依赖 <!-- 苞米豆多数据源 --> <dependency><group…

DID测试套件

DID测试套件 介绍 名称 DID Test Suite 网址 https://github.com/w3c/did-test-suite 功能 用于验证DID实现是否符合W3C DID Core规范的一系列测试反映各DID方法&#xff08;如did:orb、did:key、did:web等&#xff09;的实现对DID Core规范的遵从程度确保不同DID方法、…