W25Q64CV SPI Flash Memory

SPI简介

SPI是一种同步串行通信接口规范,用于短距离通信,主要应用于嵌入式系统。SPI通信由一个主设备和一个或多个从设备组成,其中主设备生成时钟信号并控制通信的开始和结束。

SPI通信的基本组成

四个基本信号

SCK (Serial Clock) - 时钟信号,由主设备产生。
MOSI (Master Out Slave In) - 主设备输出,从设备输入的数据线。
MISO (Master In Slave Out) - 主设备输入,从设备输出的数据线。
CS (Chip Select) - 芯片选择信号,用于激活特定的从设备。

SPI操作模式

SPI有四种操作模式,由主设备产生的时钟信号的相位和极性决定:
模式0:CPOL = 0,CPHA = 0
模式1:CPOL = 0,CPHA = 1
模式2:CPOL = 1,CPHA = 0
模式3:CPOL = 1,CPHA = 1
其中,CPOL代表时钟的极性,CPHA代表时钟的相位。不同的模式会影响数据采样和设置的时间点。
1.Mode 0 (CPOL = 0, CPHA = 0)
时钟极性(CPOL):时钟信号的空闲状态为低电平。
时钟相位(CPHA):数据在时钟的上升沿被采样,并在下降沿改变。
特点:这是最常见的SPI模式。数据在第一个时钟脉冲的上升沿读取,之后每个时钟周期的上升沿都会读取新数据。
2. Mode 1 (CPOL = 0, CPHA = 1)
时钟极性(CPOL):时钟信号的空闲状态为低电平。
时钟相位(CPHA):数据在时钟的下降沿被采样,并在上升沿改变。
特点:与Mode 0相比,数据采样发生在时钟的下降沿。
3. Mode 2 (CPOL = 1, CPHA = 0)
时钟极性(CPOL):时钟信号的空闲状态为高电平。
时钟相位(CPHA):数据在时钟的上升沿被采样,并在下降沿改变。
特点:与Mode 0相比,时钟的空闲状态为高电平。
4. Mode 3 (CPOL = 1, CPHA = 1)
时钟极性(CPOL):时钟信号的空闲状态为高电平。
时钟相位(CPHA):数据在时钟的下降沿被采样,并在上升沿改变。
特点:这种模式下,时钟的空闲状态为高电平,数据采样在时钟的下降沿。

通信过程

初始化:主设备通过拉低CS信号来选择特定的从设备。
数据传输:主设备通过MOSI发送数据,并在同一时钟周期内通过MISO接收从设备的数据。
时钟同步:数据在时钟的上升沿或下降沿被采样,这取决于SPI的工作模式。

W25Q64简介

W25Q64CV是一款高性能SPI闪存芯片,具备64M位(8M字节)的存储容量,用于需要高速数据存储和读取的嵌入式系统。操作电压为2.7V至3.6V,提供工业级(-40°C至+85°C)和汽车级(-40°C至+105°C)的温度规格,具备软件和硬件写保护功能,支持安全启动和数据保护。

引脚

在这里插入图片描述
/CS: 芯片选择输入,用于激活或禁用设备
DO (IO1): 主设备输出,从设备输入的串行数据线
/WP (IO2): 写保护输入,可配置为输入/输出2
GND: 地
VCC: 电源
/HOLD (IO3): 保持输入,可配置为输入/输出3。允许系统在Flash设备正在被选中(即/CS为低电平)时,挂起或暂停当前正在进行的操作。当/HOLD引脚被释放(即拉高回到高电平)时,设备可以从之前挂起的地方恢复操作,无需重新开始整个操作流程
DI (IO0): 主设备输出,从设备输入的串行数据线
CLK: 串行时钟输入,控制数据传输的时序

存储

提供8M字节的存储空间,适用于存储大量数据和程序代码,存储阵列被组织成32,768个可编程页,每页256字节。页可以以16(4KB扇区擦除)、128(32KB块擦除)、256(64KB块擦除)或整个芯片(芯片擦除)的组进行擦除

SPI

支持SPI模式0和模式3,支持标准SPI、双SPI和四SPI操作,时钟频率高达80MHz,实现快速数据传输

指令

在这里插入图片描述

主要指令分类

制造商和设备识别指令:
用于读取制造商ID和设备ID,帮助用户确认连接的设备。
读指令:
包括普通读取(Read Data)、快速读取(Fast Read)、快速双输出读取(Fast Read Dual Output)等,用于从Flash中读取数据。
写指令:
包括页编程(Page Program)和四页编程(Quad Page Program),用于向Flash写入数据。
擦除指令:
包括扇区擦除(Sector Erase)、32KB块擦除(32KB Block Erase)、64KB块擦除(64KB Block Erase)和芯片擦除(Chip Erase),用于清除Flash中的存储空间。
状态寄存器指令:
包括读取状态寄存器(Read Status Register)和写状态寄存器(Write Status Register),用于监控和配置设备的状态。
安全和保护指令:
包括擦除安全寄存器(Erase Security Registers)和编程安全寄存器(Program Security Registers),用于管理设备的安全性。
特殊功能指令:
如设置突发(Set Burst with Wrap)、连续读取模式位(Continuous Read Mode Bits)、电源下降(Power-down)等。

指令执行流程

选中设备:通过拉低CS(Chip Select)引脚,选中目标Flash设备。
发送指令:通过DI(Data Input)或IO0(Data Input 0)引脚发送指令的操作码。
提供地址(如需要):某些指令,如读取、写入或擦除操作,需要用户提供24位的地址信息。
数据传输:根据指令的功能,进行数据的读取或写入。
等待完成:某些操作如擦除或编程可能需要一定的时间来完成,此时可以通过检查状态寄存器中的BUSY位来确定操作是否完成。
取消选中:操作完成后,通过拉高CS引脚取消选中设备

擦除

在闪存设备,包括W25Q64CV这样的SPI Flash Memory中,写入操作之前需要进行擦除,因为闪存是一种非易失性存储器,它使用浮栅晶体管来存储数据。每个浮栅晶体管可以表示两种状态:擦除状态和编程状态。擦除状态:在擦除状态下,浮栅中几乎没有电荷,晶体管的阈值电压较高,因此在读取操作时,晶体管不导电,表示数据"1"。编程状态:在编程状态下,浮栅捕获了电荷,降低了晶体管的阈值电压,使得在读取操作时晶体管导电,表示数据"0"。由于浮栅晶体管的设计,它们不能从"0"状态直接改为"1"状态,而是需要先擦除回到"1"状态,然后再编程为"0"。

擦除步骤

初始化:确保SPI接口已正确配置,并且W25Q64CV已选中。
写使能:发送06h指令以使能写操作。
执行擦除指令:根据需要执行扇区擦除、块擦除或芯片擦除的指令。
等待完成:擦除操作需要一定的时间来完成。可以通过检查状态寄存器中的BUSY位来确定擦除是否完成。

// 假设已经有了SPI通信的基础函数库:spi_begin(), spi_end(), spi_write(), spi_read()
// 以及控制CS引脚的函数:cs_select() 和 cs_deselect()// 擦除操作前的写使能函数
void spi_write_enable(void) {cs_select(); // 选中Flash设备spi_write(0x06); // 发送写使能指令cs_deselect(); // 取消选中设备
}// 扇区擦除函数
void spi_sector_erase(uint32_t address) {spi_write_enable(); // 使能写操作cs_select(); // 选中Flash设备spi_write(0x20); // 发送扇区擦除指令spi_write((address >> 16) & 0xFF); // 发送地址的高8位spi_write((address >> 8) & 0xFF);  // 发送地址的中8位spi_write(address & 0xFF);         // 发送地址的低8位cs_deselect(); // 取消选中设备spi_wait_until_ready(); // 等待擦除完成
}// 32KB块擦除函数
void spi_32kb_block_erase(uint32_t address) {spi_write_enable(); // 使能写操作cs_select(); // 选中Flash设备spi_write(0x52); // 发送32KB块擦除指令spi_write((address >> 16) & 0xFF); // 发送地址的高8位spi_write((address >> 8) & 0xFF);  // 发送地址的中8位spi_write(address & 0xFF);         // 发送地址的低8位cs_deselect(); // 取消选中设备spi_wait_until_ready(); // 等待擦除完成
}// 64KB块擦除函数
void spi_64kb_block_erase(uint32_t address) {spi_write_enable(); // 使能写操作cs_select(); // 选中Flash设备spi_write(0xD8); // 发送64KB块擦除指令spi_write((address >> 16) & 0xFF); // 发送地址的高8位spi_write((address >> 8) & 0xFF);  // 发送地址的中8位spi_write(address & 0xFF);         // 发送地址的低8位cs_deselect(); // 取消选中设备spi_wait_until_ready(); // 等待擦除完成
}// 芯片擦除函数
void spi_chip_erase(void) {spi_write_enable(); // 使能写操作cs_select(); // 选中Flash设备spi_write(0xC7); // 发送芯片擦除指令cs_deselect(); // 取消选中设备spi_wait_until_ready(); // 等待擦除完成
}// 等待设备准备就绪的函数
void spi_wait_until_ready(void) {// 这里应实现等待就绪的逻辑,可能通过检查状态寄存器的BUSY位// 例如:uint8_t status;do {cs_select();spi_write(0x05); // 发送读取状态寄存器1的指令status = spi_read(0xFF); // 读取状态寄存器1cs_deselect();} while ((status & 0x01) != 0); // 等待BUSY位清零
}

读写

写入步骤
写使能

选中设备:通过拉低CS(Chip Select)引脚,选中Flash设备
发送写使能指令:通过DI(Data Input)引脚发送06h指令码,使能写操作

页编程 (Page Program)

发送页编程指令:通过DI引脚发送02h指令码
提供地址:发送24位地址信息,指向要编程的起始位置
发送数据:顺序发送要写入的数据。W25Q64CV支持的数据长度从1字节到256字节
等待完成:等待编程操作完成。这可以通过轮询状态寄存器中的BUSY位来实现

// 检查设备是否忙碌的函数
uint8_t spi_check_busy(void) {uint8_t status;cs_select(); // 选中Flash设备spi_write(0x05); // 发送读取状态寄存器1的指令status = spi_read(0xFF); // 读取状态寄存器1cs_deselect(); // 取消选中设备return status;
}// 等待编程完成的函数
void spi_wait_until_ready(void) {while (spi_check_busy() & 0x01); // 检查BUSY位,如果为1则等待
}// 完整的编程函数,包括等待编程完成
void spi_flash_page_program(uint32_t address, const uint8_t *data, uint16_t dataSize) {cs_select(); // 选中Flash设备spi_write(0x06); // 发送写使能指令cs_deselect(); // 取消选中设备cs_select(); // 重新选中设备spi_write(0x02); // 发送页编程指令spi_write((address >> 16) & 0xFF); // 发送地址的高8位spi_write((address >> 8) & 0xFF);  // 发送地址的中8位spi_write(address & 0xFF);         // 发送地址的低8位for (int i = 0; i < dataSize; ++i) {spi_write(data[i]); // 发送数据}cs_deselect(); // 取消选中设备spi_wait_until_ready(); // 等待编程完成
}
读取步骤

选中设备:拉低CS引脚
发送读取数据指令:通过DI引脚发送03h指令码
提供地址:发送24位地址信息,指向要读取的起始位置
读取数据:数据将通过DO(Data Output)引脚顺序输出

void readData(uint32_t address, uint8_t *buffer, uint16_t dataSize) {cs_select();spi_write(0x03); // 发送读取数据指令spi_write(address >> 16); // 发送高8位地址spi_write(address >> 8);  // 发送中8位地址spi_write(address);       // 发送低8位地址for (int i = 0; i < dataSize; ++i) {buffer[i] = spi_read(0xFF); // 读取数据}cs_deselect();
}

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

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

相关文章

centos7下安装MySQL,Oracle数据库

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 操作系统版本为CentOS 7 使⽤ MySQ…

python数据分析——datetime数据类型2

参考资料&#xff1a;活用pandas库 # 导入pandas库 import pandas as pd # 加载数据集 teslapd.read_csv(r"...\data\tesla_stock_yahoo.csv") # 查看数据 print(tesla.head()) 1、基于日期取数据子集 # 将Date数据列转换为datetime类型 tesla[Date]pd.to_datetime…

学习笔记——网络参考模型——TCP/IP模型(传输层)

四、TCP/IP模型-传输层 一、TCP 1、TCP定义 TCP(Transmission Control Protocol&#xff0c;传输控制协议)∶为应用程序提供可靠的面向连接的通信服务。目前&#xff0c;许多流行的应用程序都使用TCP。 连接&#xff1a;正式发送数据之前&#xff0c;提前建立好一种虚拟的&…

oracle服务器存储过程中调用http

在Oracle服务器中&#xff0c;存储过程调用HTTP请求可以通过几种不同的方法来实现。以下是一些关键步骤和注意事项&#xff0c;以帮助你清晰地理解和执行此操作&#xff1a; 开启Oracle ACL权限&#xff1a; 使用dbms_network_acl_admin包来创建和管理访问控制列表&#xff0…

ES6-03-模版字符串、对象的简化写法

一、模版字符串 1-1、声明 反引号。 1-2、特性 1、字符串内容可以直接换行 得用号连接 2、变量拼接 现在&#xff1a; 二、对象的简化写法 ES6允许在大括号里面&#xff0c;直接写入变量和函数&#xff0c;作为对象的属性和方法。 let name milk;let chage function(){con…

iOS ActivityViewController使用

UIActivityViewController是iOS中用于展示一个活动列表的视图控制器&#xff0c;允许用户通过各种内置或第三方的应用来分享内容。以下是使用UIActivityViewController分享文本内容的示例代码&#xff1a; import UIKit class ViewController: UIViewController { IBA…

java-对象内存

在Java中&#xff0c;对象内存是指用于存储对象实例的内存区域。当我们在Java程序中创建一个对象时&#xff0c;Java虚拟机&#xff08;JVM&#xff09;会在内存中为该对象分配一块内存区域&#xff0c;用于存储对象的字段&#xff08;成员变量&#xff09;、方法和其他与对象相…

通过电脑查看Wi-Fi密码的方法,提供三种方式

式一&#xff1a; 右击桌面右下角的网络图标&#xff0c;依次选择【网络和Internet设置】、【WLAN】、【网络和共享中心】。点击已连接的无线网络。依次点击【无线属性】、【安全】&#xff0c;勾选下方【显示字符】即可。 方式二&#xff1a; 在开始菜单输入“cmd”进入命令…

脚本实现登陆滑块

脚本实现登陆滑块 仅供学习参考&#xff0c;简单操作 你知道吗&#xff0c;滑动验证码居然是为了验证人类比机器人蠢而设计的。 你以为自己快速、准确地滑动拼图、对齐图案&#xff0c;才被允许通过&#xff0c;系统还说你超越了99%的用户&#xff0c;夸你“比闪电还快”&am…

【Python】collections模块:高效处理数据的利器

Python中的collections模块&#xff1a;高效处理数据的利器 Python的collections模块是一个内置模块&#xff0c;它提供了一些专用的容器数据类型&#xff0c;作为Python通用内置容器&#xff08;如列表list、字典dict、集合set和元组tuple&#xff09;的替代品。本文将深入探…

STM32_SPI

1、SPI简介 1.1 什么是SPI SPI&#xff0c;即Serial Peripheral Interface&#xff0c;串行外设接口。SPI是一种高速的、全双工、同步的串行通信总线&#xff1b;SPI采用主从方式工作&#xff0c;一般有一个主设备和一个或多个从设备&#xff1b;SPI需要至少4根线&#xff0c;…

网络安全法中的网络安全规定和措施

《中华人民共和国网络安全法》是中国首部全面规范网络空间安全管理的基础性法律&#xff0c;旨在加强网络安全&#xff0c;保障国家安全和社会公共利益&#xff0c;保护公民、法人和其他组织的合法权益&#xff0c;促进互联网的健康发展。以下是该法律中关于网络安全的一些核心…

Linux线程--线程创建、等待及退出

1. pthread_create 功能 创建一个新的线程。 原型 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);参数 thread: 指向pthread_t类型变量的指针&#xff0c;用于存储新创建线程的标识符。attr: 线程属性&…

采用bat结合zabbix监控sqlserver数据库表的信息

采用bat结合zabbix监控sqlserver数据库表的信息&#xff0c;当表插入某个特定的值的时候就发出告警。 监控需求&#xff1a;数据库存在某个表&#xff0c;该表不是一个固定的表名字&#xff0c;而且根据当前的日期生成表&#xff0c;比如tab20240501,tab20240502,需要查询当天…

安卓init进程详解

目录 一、概述1.1 Init进程如何被启动&#xff1f;1.2 Init进程启动后&#xff0c;做了哪些事&#xff1f; 二、kernel启动init进程2.1 kernel_init2.2 do_basic_setup 三、Init 进程启动源码分析3.1 Init 进程入口3.2 ueventd_main3.3 init 进程启动第一阶段3.4 加载SELinux规…

FLINK-窗口算子

参考资料 官方文档- WindowFlink中的时间和窗口之窗口 窗口 在流处理中&#xff0c;我们往往需要面对的是连续不断、无休无止的无界流&#xff0c;不可能等到所有所有数据都到齐了才开始处理。所以聚合计算其实只能针对当前已有的数据——之后再有数据到来&#xff0c;就需要继…

chat4-Server端保存聊天消息到mysql

本文档描述了Server端接收到Client的消息并转发给所有客户端或私发给某个客户端 同时将聊天消息保存到mysql 服务端为当前客户端创建一个线程&#xff0c;此线程接收当前客户端的消息并转发给所有客户端或私发给某个客户端同时将聊天消息保存到mysql 本文档主要总结了将聊天…

多项目的.net core解决方案(项目间引用)如何使用Docker部署

解决方案内部项目之间引用很正常&#xff0c;但我docker不是很熟&#xff0c;对一些基础命令含义还理解不深入&#xff0c;部署引用其他项目的项目总不成功。搜到了一篇非常适合初学者&#xff0c;从dockerfile命令讲解&#xff0c;到解决引用其他项目时如何docker部署的文章。…

JavaWeb_SpringBootWeb基础

先通过一个小练习简单了解以下SpringBootWeb。 小练习&#xff1a; 需求&#xff1a;使用SpringBoot开发一个Web应用&#xff0c;浏览器发起请求/hello后&#xff0c;给浏览器返回字符串"Hello World~"。 步骤&#xff1a; 1.创建SpringBoot项目&#xff0c;勾选We…

3-EMMC命令使用

在调试emmc的过程&#xff0c;我们需要用到命令读写emmc&#xff0c;烧录&#xff0c;查看emmc寄存器&#xff0c;设置寄存器等功能&#xff0c;所以uboot和linux下都有各自的命令可以使用。 1、 uboot下mmc命令 1.1、mmc信息 查看mmc信息&#xff1a;mmc info 描述了emmc的速…