当前位置: 首页 > news >正文

SPI协议——对外部SPI Flash操作

目录

1. W25Q32JVSSIQ背景知识

1.1 64个可擦除块

1.2 1024个扇区(每个块有16个扇区)

1.3 页


1. W25Q32JVSSIQ背景知识

        

W25Q32JV阵列被组织成16,384个可编程页,每页有256字节。一次最多可以编程256个字节。页面可分为16组(4KB扇区清除)、128组(32KB块删除)、256组(64KB块删除)或整个芯片(芯片清除)。W25Q32JV分别有1,024个可擦除扇区和64个可擦除块。小型的4KB扇区允许在需要数据和参数存储的应用程序中具有更大的灵活性。

1.1 64个可擦除块

8M的空间被切割成128块,每块64kb

  

1.2 1024个扇区(每个块有16个扇区)

每块64kb又每切割成16个扇区,每扇区4kb(16*4=64kb)

1.3 页

一扇区是4KB,划分成16份每份256字节这就是页,而且擦除数据也只能按照扇区或者块来擦除,下图的00FF00H-00FFFFH刚好256字节,000000h-0000ff之间也是256字节

2. Flash操作注意事项

2.1 写入操作

1. 写入操作之前必须先进行写使能;

2. 每个数据只能由1改写为0,不能由0改写为1是因为FLASH芯片自身的限制决定,它没有完全任意修改的能力,所以芯片内部无数据的时候默认为0XFF,表示为空。;

3. 写入数据之前必须先进行擦除,擦除后所有的数据位为1;

4. 进行擦除时必须按照最小擦除单元进行擦除(最小擦除单位为扇区);

5.连续写入多字节数据时,最多写入一页的数据,如果超过一页则会覆盖前面写的内容;

6. 写入操作结束后, 芯片进入忙状态(寄存器中有一个busy位),不影响新的读写操作;

2.2 读操作

进行读操作时,直接调用读取操作时序,无需使能,但是别忘了拉低电平,没有页的限制,读取之后也不会进入到忙状态,但是不能在忙状态时读取数据;

3.代码编写

此次对SPI Flash进行读写操作还是采用SPI1,具体的配置请见上篇文章,在这里不做详细概述。

3.1 spi_flash.c添加代码

/* Flash 写使能 */
static void SPI1_FLASH_WriteEnable(void)
{cs_low();SPI_FLASH_SendByte( 0x06 ); //需要查芯片的datasheet来看具体的cs_high();
}/* Flash 等待写结束 */
static void SPI1_FLASH_WaitEnd(void)
{uint8_t	state = 0;cs_low();SPI_FLASH_SendByte(0x05); //需要查芯片的datasheet来看具体的do{state = SPI1_FLASH_ReadByte();}while( (state & 0x01) == SET );cs_high();
}// 扇区擦除验证函数
int SPI_FLASH_VerifyErase(uint32_t addr, uint32_t length)
{uint8_t buffer[16];uint32_t bytesRead;for (bytesRead = 0; bytesRead < length; bytesRead += sizeof(buffer)){uint32_t toRead = sizeof(buffer);if (bytesRead + toRead > length) {toRead = length - bytesRead;}// 读取地址开始的若干字节数据SPI_FLASH_BufferRead(addr + bytesRead, buffer, toRead);// 检查读取的数据是否为0xFFfor (uint32_t i = 0; i < toRead; i++){if (buffer[i] != 0xFF){return -1; // 如果不是0xFF,返回false,表示擦除失败}}}return 0; // 如果所有数据都是0xFF,返回true,表示擦除成功
}/*清空扇区*/
int SPI_FLASH_SectorErase(uint32_t addr)
{cs_low();/* 开始的时候要先发送写使能信号 */SPI1_FLASH_WriteEnable();/* 发送扇区擦除命令 */SPI_FLASH_SendByte(0x20);/* 发送扇区地址,高位先行 */SPI_FLASH_SendByte( (addr & 0xff0000) >> 16 );SPI_FLASH_SendByte( (addr & 0xff00) >> 8 );SPI_FLASH_SendByte( addr & 0xff );cs_high();/* 最后等待Flash 处理完这次信号之后退出 */SPI1_FLASH_WaitEnd();if (!SPI_FLASH_VerifyErase(addr, 4096)) // 通常扇区大小为4KB{printf("Sector erase failed at address 0x%06X\n", addr);}else{printf("Sector erase successful at address 0x%06X\n", addr);}return 0;}/* 按页写数据,在写数据之前要先擦除 */void SPI_FLASH_PageWrite(uint32_t addr, uint8_t *pBuffer, uint8_t size)
{/* 发送使能信号 */SPI1_FLASH_WriteEnable();cs_low();/* 发送页写入命令 */SPI_FLASH_SendByte(0x02);/* 发送要写入的地址,高位先行 */SPI_FLASH_SendByte( (addr & 0xff0000) >> 16 );SPI_FLASH_SendByte( ( addr & 0xff00) >> 8 );SPI_FLASH_SendByte(addr & 0xff );printf("Writing to address 0x%06X: ", addr);for (uint8_t i = 0; i < size; i++){SPI_FLASH_SendByte(pBuffer[i]); // 发送数据printf("%02X ", pBuffer[i]);}printf("\n");cs_high();SPI1_FLASH_WaitEnd();
}/* 读取数据,读取指定地址制定长度的数据 */
void SPI_FLASH_BufferRead(uint32_t addr, uint8_t *pBuffer, uint16_t size)
{cs_low();/* 发送读取命令 */SPI_FLASH_SendByte(0x03);/* 发送要读取的地址,高位先行*/SPI_FLASH_SendByte( (addr & 0xff0000) >> 16 );SPI_FLASH_SendByte( (addr & 0xff00 ) >> 8 );SPI_FLASH_SendByte(addr & 0xff );printf("Reading to address 0x%06X: ", addr);/* 逐位读取数据到指针上 */for (uint8_t i = 0; i < size; i++){pBuffer[i] = SPI_FLASH_SendByte(Dummy_Byte); // 发送数据}cs_high();}

3.2 详细分析

1. 地址分解

假设 addr 是一个24位的地址(0xFFFFFF范围内)。发送前需要将addr分解成三个8位字节,因为SPI通常以字节为单位发送数据。

SPI_SendData((addr & 0xff0000) >> 16);
  • addr & 0xff0000:使用位与操作(&)保留 addr 的高8位,其余位清零。
  • >> 16:将结果右移16位,使得高8位移到最低8位的位置。
  • SPI_SendData():将移位后的结果发送出去,这发送的是 addr 的高8位。
  • 例如:如果 addr = 0x123456,那么 (addr & 0xff0000) = 0x120000,右移16位得到 0x12,即发送的第一个字节是 0x12。

 其他同理

2. SPI1_FLASH_WaitEnd(void)函数

读取寄存器最低位BUSY的状态,如果为1表示忙,0表示空闲;

3.3 main.c函数

uint8_t Rx[100];
uint8_t Tx[] = "Hello!", n;
SPI_FLASH_SectorErase(0x00000);
n=sizeof(Tx) -1 ;
SPI_FLASH_PageWrite(0x00000 ,Tx ,n);
SPI_FLASH_BufferRead(0x00000 ,Rx ,n);
printf("the data is %s\n", Rx);

3.4 运行结果

 

相关文章:

SPI协议——对外部SPI Flash操作

目录 1. W25Q32JVSSIQ背景知识 1.1 64个可擦除块 1.2 1024个扇区&#xff08;每个块有16个扇区&#xff09; 1.3 页 1. W25Q32JVSSIQ背景知识 W25Q32JV阵列被组织成16,384个可编程页&#xff0c;每页有256字节。一次最多可以编程256个字节。页面可分为16组(4KB扇区清除&…...

kotlin类型检测与类型转换

一、is与!is操作符 1、使用 is 操作符或其否定形式 !is 在运行时检测对象是否符合给定类型。 fun main() {var a "1"if(a is String) {println("a是字符串类型:${a.length}")}// 或val b a is Stringprintln(b) } 二、"不安全的"转换操作符…...

【JDBC】Oracle数据库连接问题记录

Failed to load driver class oracle.jdbc.driver.OracleDriver in either of HikariConfig class oracle驱动包未正确加载&#xff0c;可以先尝试使用下面方式加载检查类是否存在&#xff0c;如果不存在需要手动下载odbc包 try {Class.forName("oracle.jdbc.driver.Ora…...

leetcode45 跳跃游戏II

题目 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说&#xff0c;如果你在 nums[i] 处&#xff0c;你可以跳转到任意 nums[i j] 处: 0 < j < nums[i] i j < n 返回到达 nums[n - 1]…...

【数学】什么是方法矩估计?和最大似然估计是什么关系?

背景 方法矩估计&#xff08;Method of Moments Estimation&#xff09;和最大似然估计&#xff08;Maximum Likelihood Estimation, MLE&#xff09;是两种常用的参数估计方法。方法矩估计基于样本矩与总体矩的关系&#xff0c;通过样本数据计算样本矩来估计总体参数。最大似…...

C++初学者指南第一步---10.内存(基础)

C初学者指南第一步—10.内存&#xff08;基础&#xff09; 文章目录 C初学者指南第一步---10.内存&#xff08;基础&#xff09;1.内存模型1.1 纸上谈兵&#xff1a;C的抽象内存模型1.2 实践&#xff1a;内存的实际处理 2. 自动存储3.动态存储&#xff1a;std::vector3.1 动态内…...

扩散模型详细推导过程——编码与解码

符号表 符号含义 x ( i ) z 0 ( i ) \boldsymbol{x}^{(i)}\boldsymbol{z}_0^{(i)} x(i)z0(i)​第 i i i个训练数据&#xff0c;其为长度为 d d d的向量 z t ( i ) \boldsymbol{z}_t^{(i)} zt(i)​第 i i i个训练数据在第 t t t时刻的加噪版本 ϵ t ( i ) \boldsymbol{\epsilo…...

js如何实现开屏弹窗

开屏弹窗是什么&#xff0c;其实就是第一次登录后进入页面给你的一种公告提示&#xff0c;此后再回到当前这个页面时弹窗是不会再出现的。也就是说这个弹窗只会出现一次。 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>…...

C#——文件读取Directory类详情

文件读取Directory类 Durectory提供了目录以及子目录进行创建移动和列举操作方法 Directory和Directorylnfo类(主要操作文件目录属性列如文件是否隐藏的 或者只读等这些属性) Directory对目录进行复制、移动、重命名、创建和删除等操作DirectoryInfo用于对目录属性执行操作 …...

Ruby on Rails Post项目设置网站初始界面

在构建了Ruby的Web服务器后&#xff0c;第三步就可以去掉框架的官方页面&#xff0c;设置自己的网页初始页了。 Linux系统安装Ruby语言-CSDN博客 、在Ubuntu中创建Ruby on Rails项目并搭建数据库-CSDN博客、 Ruby语言建立Web服务器-CSDN博客 了解Ruby onRails项目中的主要文件…...

03-QTWebEngine中使用qtvirtualkeyboard

qt提供了 virtualKeyboard 虚拟键盘模块&#xff0c;只需要在在main函数中最开始加入这样一句就可以了 qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); 但是在使用的时候遇到了一些问题&#xff1a; 1、中文输入的时候没有输入提示 Qvirt…...

leetcode3无重复字符的最长字串(重点讲滑动窗口)

本文主要讲解无重复字符的最长字串的要点与细节&#xff0c;根据步骤一步步走更方便理解 c与java代码如下&#xff0c;末尾 具体要点&#xff1a; 1. 区分一下子串和子序列 子串&#xff1a;要求元素在母串中是连续地出现 子序列&#xff1a;不要求连续 2. 题目中有两个核心…...

Gobject tutorial 八

The GObject base class Object memory management Gobject的内存管理相关的API很复杂&#xff0c;但其目标是提供一个基于引用计数的灵活的内存管理模式。 下面我们来介绍一下&#xff0c;与管理引用计数相关的函数。 Reference Count 函数g_object_ref和g_object_unref的…...

DDMA信号处理以及数据处理的流程---cfar检测

Hello,大家好,我是Xiaojie,好久不见,欢迎大家能够和Xiaojie一起学习毫米波雷达知识,Xiaojie准备连载一个系列的文章—DDMA信号处理以及数据处理的流程,本系列文章将从目标生成、信号仿真、测距、测速、cfar检测、测角、目标聚类、目标跟踪这几个模块逐步介绍,这个系列的…...

【机器学习】从理论到实践:决策树算法在机器学习中的应用与实现

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 &#x1f4d5;引言 ⛓决策树的基本原理 1. 决策树的结构 2. 信息增益 熵的计算公式 信息增益的计算公式 3. 基尼指数 4. 决策树的构建 &#x1f916;决策树的代码实现 1. 数据准备 2. 决策树模型训练 3.…...

Zookeeper 集群节点故障剔除、切换、恢复原理

Zookeeper 集群节点故障剔除、切换、恢复原理 zookeeper 集群节点故障时,如何剔除节点,如果为领导节点如何处理,如何进行故障恢 复的,实现原理? 在 Zookeeper 集群中,当节点故障时,集群需要自动剔除故障节点并进行故障恢复,确保集群的高 可用性和一致性。具体来说,…...

解决帝国cms栏目管理拼音乱码的问题

帝国CMS7.5版本utf-8版网站后台增加栏目生成乱码的问题怎么解决 1、需要改一个函数&#xff0c;并且增加一个处理文件&#xff0c;方法如下&#xff1a; 修改e/class/connect.php文件&#xff0c;找到ReturnPinyinFun函数&#xff0c;如未修改文件在4533-4547行&#xff0c;将…...

Git快速入门

一 快速使用 1.1 初始化 什么是版本库呢&#xff1f;版本库又名仓库&#xff0c;可以简单理解成一个目录&#xff0c;这个目录里面的所有文件都可以被Git管理起来&#xff0c;每个文件的修改、删除&#xff0c;Git都能跟踪&#xff0c;以便任何时刻都可以追踪历史&#xff0…...

【18.0】JavaScript---事件案例

【18.0】JavaScript—事件案例 【一】开关灯事件 【介绍】设置一个按钮&#xff0c;按下按钮触发事件&#xff0c;来回切换圆形图片的颜色 【分析】 图片设置&#xff1a;设置成圆形的图片背景颜色&#xff1a;设置红绿两个颜色&#xff0c;来回切换按钮设置&#xff1a;点击…...

推荐系统三十六式学习笔记:原理篇.矩阵分解12|如果关注排序效果,那么这个模型可以帮到你

目录 矩阵分解的不足贝叶斯个性化排序AUC构造样本目标函数训练方法 总结 矩阵分解在推荐系统中的地位非常崇高。它既有协同过滤的血统&#xff0c;又有机器学习的基因&#xff0c;可以说是非常优秀了&#xff1b;但即便如此&#xff0c;传统的矩阵分解无论是在处理显式反馈&…...

QLVideo终极指南:让macOS Finder完美预览所有视频格式

QLVideo终极指南&#xff1a;让macOS Finder完美预览所有视频格式 【免费下载链接】QuickLookVideo This package allows macOS Finder to display thumbnails, static QuickLook previews, cover art and metadata for most types of video files. 项目地址: https://gitcod…...

三层架构破解小红书数据采集难题:Appium+MitmProxy双引擎实战

三层架构破解小红书数据采集难题&#xff1a;AppiumMitmProxy双引擎实战 【免费下载链接】XiaohongshuSpider 小红书爬取 项目地址: https://gitcode.com/gh_mirrors/xia/XiaohongshuSpider 在小红书内容生态快速发展的今天&#xff0c;数据工程师和产品分析师面临着内容…...

从国科大NLP课程笔记出发:手把手教你用Python复现CYK句法分析算法

从理论到实践&#xff1a;用Python实现CYK句法分析算法的完整指南 在自然语言处理领域&#xff0c;句法分析是理解句子结构的关键步骤。CYK算法作为一种经典的句法分析技术&#xff0c;因其简洁高效的特点&#xff0c;成为许多NLP工程师工具箱中的必备武器。本文将带你从零开始…...

嵌入式开发实战:用状态机+事件驱动框架搞定串口通信(附完整代码)

嵌入式开发实战&#xff1a;状态机与事件驱动框架在串口通信中的高效应用 串口通信作为嵌入式系统中最基础也最常用的外设接口之一&#xff0c;其稳定性和效率直接影响着整个系统的性能表现。传统的轮询式串口处理方式不仅占用大量CPU资源&#xff0c;还难以应对复杂通信协议和…...

[特殊字符] Meixiong Niannian画图引擎应用场景:独立音乐人专辑封面AI生成流程

Meixiong Niannian画图引擎应用场景&#xff1a;独立音乐人专辑封面AI生成流程 1. 项目简介 Meixiong Niannian画图引擎是一款专为个人GPU设计的轻量化文本生成图像系统&#xff0c;基于Z-Image-Turbo底座和meixiong Niannian Turbo LoRA技术构建。这个引擎针对通用画图场景进…...

Offline-First数据同步策略:解决网络中断的智能方案

Offline-First数据同步策略&#xff1a;解决网络中断的智能方案 【免费下载链接】offline-first :electric_plug: Everything you need to know to create offline-first web apps. 项目地址: https://gitcode.com/gh_mirrors/of/offline-first 在当今移动优先的时代&am…...

本地Cookie导出终极指南:Get cookies.txt LOCALLY 安全使用教程

本地Cookie导出终极指南&#xff1a;Get cookies.txt LOCALLY 安全使用教程 【免费下载链接】Get-cookies.txt-LOCALLY Get cookies.txt, NEVER send information outside. 项目地址: https://gitcode.com/gh_mirrors/ge/Get-cookies.txt-LOCALLY 你是否曾担心浏览器Coo…...

技术萨满祭典:给数据中心献祭机械硬盘

一、仪式的缘起&#xff1a;当测试工程师遇见数据之灵在数字文明的殿堂中&#xff0c;数据中心是承载万物之灵的圣地。而软件测试从业者&#xff0c;正是穿梭于代码与硬件之间的现代萨满。当机械硬盘&#xff08;HDD&#xff09;在SSD洪流中逐渐退居幕后&#xff0c;这场为老旧…...

G5080 G6080 G7080 G1810 G2810 ,MG3680,ts3380最新清零软件5B00,5B01,5B02,1700,1701,1702,1704,P07,E08废墨收集器已满

下载地址&#xff1a;链接:https://pan.baidu.com/s/1j7Nwv715wX1JL3qidnGyXA?pwd0000 提取码:0000 常见 佳能打印机 型号&#xff1a; G5080 G6080 G7080 G1810 G2810 G3810 G4810 G1800 G2800 G3800 G4800 G5010 G6010 G7010 G1010 G2010 G3010 G4010 G1000 G2000 G3000 G40…...

VOOHU沃虎xJLSemi景略:智造时代通信基石-以太网接口PHY芯片

随着智能制造和工业物联网的高速发展&#xff0c;工业通信正朝着高速化、智能化的方向迈进。工业自动化设备需要实时、高效地传输大量数据&#xff0c;以实现精准控制和协同作业。 工业以太网现场总线凭借其高速率、高可靠性、兼容性强等优势成为工业通信的主流选择&#xff0…...