news 2026/6/20 11:33:38

STM32 SPI读取写入W25Q64JVSSIQ

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32 SPI读取写入W25Q64JVSSIQ

w25q64.h

#ifndef__W25Q64_H#define__W25Q64_H#include"main.h"#include"spi.h"// 引脚定义#defineW25Q64_CS_PINGPIO_PIN_15#defineW25Q64_CS_PORTGPIOA// W25Q64指令集#defineW25Q64_WRITE_ENABLE0x06#defineW25Q64_WRITE_DISABLE0x04#defineW25Q64_READ_STATUS10x05#defineW25Q64_WRITE_STATUS10x01#defineW25Q64_READ_DATA0x03#defineW25Q64_PAGE_PROGRAM0x02#defineW25Q64_SECTOR_ERASE0x20#defineW25Q64_CHIP_ERASE0xC7#defineW25Q64_POWER_DOWN0xB9#defineW25Q64_RELEASE_PD0xAB#defineW25Q64_MANUF_DEVICE_ID0x90#defineW25Q64_JEDEC_ID0x9F// Flash容量参数#defineW25Q64_PAGE_SIZE256#defineW25Q64_SECTOR_SIZE4096#defineW25Q64_TOTAL_SIZE(8*1024*1024)// 8MB// 函数声明voidW25Q64_Init(void);uint8_tW25Q64_ReadByte(uint32_taddr);voidW25Q64_ReadBytes(uint32_taddr,uint8_t*buf,uint32_tlen);voidW25Q64_WriteByte(uint32_taddr,uint8_tdata);voidW25Q64_WriteBytes(uint32_taddr,uint8_t*data,uint32_tlen);voidW25Q64_ModifyByte(uint32_taddr,uint8_tdata);voidW25Q64_EraseSector(uint32_tsector_addr);voidW25Q64_WaitBusy(void);uint32_tW25Q64_ReadID(void);#endif/* __W25Q64_H */

w25q64.c

#include"w25q64.h"// 私有函数声明staticvoidW25Q64_CS_Low(void);staticvoidW25Q64_CS_High(void);staticvoidW25Q64_WriteEnable(void);staticuint8_tW25Q64_ReadStatus(void);// 初始化函数voidW25Q64_Init(void){W25Q64_CS_High();HAL_Delay(10);// 读取ID验证连接uint32_tid=W25Q64_ReadID();if(id==0xEF4017)// W25Q64JV的JEDEC ID{// 初始化成功}}// 读取单个字节uint8_tW25Q64_ReadByte(uint32_taddr){uint8_tcmd[4]={W25Q64_READ_DATA,(addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF};uint8_tdata=0;W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,cmd,4,100);HAL_SPI_Receive(&hspi6,&data,1,100);W25Q64_CS_High();returndata;}// 读取多个字节voidW25Q64_ReadBytes(uint32_taddr,uint8_t*buf,uint32_tlen){uint8_tcmd[4]={W25Q64_READ_DATA,(addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF};W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,cmd,4,100);HAL_SPI_Receive(&hspi6,buf,len,1000);W25Q64_CS_High();}// 写入单个字节voidW25Q64_WriteByte(uint32_taddr,uint8_tdata){uint8_tcmd[5]={W25Q64_PAGE_PROGRAM,(addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF,data};W25Q64_WriteEnable();W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,cmd,5,100);W25Q64_CS_High();W25Q64_WaitBusy();}// 写入多个字节(注意:不能跨页写入)voidW25Q64_WriteBytes(uint32_taddr,uint8_t*data,uint32_tlen){// 确保不跨页写入uint32_tpage_remain=W25Q64_PAGE_SIZE-(addr%W25Q64_PAGE_SIZE);uint32_twrite_len=(len>page_remain)?page_remain:len;uint8_t*cmd=(uint8_t*)malloc(write_len+4);if(cmd==NULL)return;cmd[0]=W25Q64_PAGE_PROGRAM;cmd[1]=(addr>>16)&0xFF;cmd[2]=(addr>>8)&0xFF;cmd[3]=addr&0xFF;memcpy(&cmd[4],data,write_len);W25Q64_WriteEnable();W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,cmd,write_len+4,1000);W25Q64_CS_High();W25Q64_WaitBusy();free(cmd);// 如果还有数据需要写入,递归调用if(len>write_len){W25Q64_WriteBytes(addr+write_len,data+write_len,len-write_len);}}// 修改指定地址的字节(先擦除后写入)voidW25Q64_ModifyByte(uint32_taddr,uint8_tdata){// 计算所在扇区uint32_tsector_addr=addr-(addr%W25Q64_SECTOR_SIZE);uint8_tsector_buffer[W25Q64_SECTOR_SIZE];// 1. 读取整个扇区W25Q64_ReadBytes(sector_addr,sector_buffer,W25Q64_SECTOR_SIZE);// 2. 修改指定字节sector_buffer[addr-sector_addr]=data;// 3. 擦除扇区W25Q64_EraseSector(sector_addr);// 4. 重新写入整个扇区// 分页写入,每次写入一页(256字节)for(uint32_ti=0;i<W25Q64_SECTOR_SIZE;i+=W25Q64_PAGE_SIZE){W25Q64_WriteBytes(sector_addr+i,&sector_buffer[i],W25Q64_PAGE_SIZE);}}// 擦除扇区(4KB)voidW25Q64_EraseSector(uint32_tsector_addr){uint8_tcmd[4]={W25Q64_SECTOR_ERASE,(sector_addr>>16)&0xFF,(sector_addr>>8)&0xFF,sector_addr&0xFF};W25Q64_WriteEnable();W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,cmd,4,100);W25Q64_CS_High();W25Q64_WaitBusy();}// 等待Flash操作完成voidW25Q64_WaitBusy(void){while(W25Q64_ReadStatus()&0x01){HAL_Delay(1);}}// 读取JEDEC IDuint32_tW25Q64_ReadID(void){uint8_tcmd=W25Q64_JEDEC_ID;uint8_tid_data[3];W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,&cmd,1,100);HAL_SPI_Receive(&hspi6,id_data,3,100);W25Q64_CS_High();return(id_data[0]<<16)|(id_data[1]<<8)|id_data[2];}// 私有函数实现staticvoidW25Q64_CS_Low(void){HAL_GPIO_WritePin(W25Q64_CS_PORT,W25Q64_CS_PIN,GPIO_PIN_RESET);}staticvoidW25Q64_CS_High(void){HAL_GPIO_WritePin(W25Q64_CS_PORT,W25Q64_CS_PIN,GPIO_PIN_SET);}staticvoidW25Q64_WriteEnable(void){uint8_tcmd=W25Q64_WRITE_ENABLE;W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,&cmd,1,100);W25Q64_CS_High();}staticuint8_tW25Q64_ReadStatus(void){uint8_tcmd=W25Q64_READ_STATUS1;uint8_tstatus;W25Q64_CS_Low();HAL_SPI_Transmit(&hspi6,&cmd,1,100);HAL_SPI_Receive(&hspi6,&status,1,100);W25Q64_CS_High();returnstatus;}

使用例程

#include"w25q64.h"// 测试函数voidmain(void){uint8_tread_data;uint8_twrite_data=0xAA;uint32_ttest_addr=0x000000;// 测试地址// 1. 初始化W25Q64_Init();// 2. 写入单个字节W25Q64_WriteByte(test_addr,write_data);HAL_Delay(10);// 3. 读取单个字节read_data=W25Q64_ReadByte(test_addr);if(read_data==write_data){// 写入成功}// 4. 批量写入测试uint8_twrite_buffer[256];uint8_tread_buffer[256];for(inti=0;i<256;i++){write_buffer[i]=i;}W25Q64_WriteBytes(0x1000,write_buffer,256);HAL_Delay(10);// 5. 批量读取测试W25Q64_ReadBytes(0x1000,read_buffer,256);// 6. 修改指定地址的数据W25Q64_ModifyByte(0x2000,0x55);// 7. 擦除扇区测试W25Q64_EraseSector(0x3000);}

CubeMX配置要点

  1. SPI6配置:
    · Mode: Full-Duplex Master
    · Hardware NSS Signal: Disable
    · Prescaler: 根据HCLK频率调整(建议≤50MHz)
  2. GPIO配置:
    · PA15: GPIO_Output(CS引脚)
    · PB3: SPI6_SCK
    · PB4: SPI6_MISO
    · PB5: SPI6_MOSI
  3. 时钟配置:
    · 确保SPI时钟不超过W25Q64的最大频率(104MHz)

注意事项

  1. 写操作前必须擦除:Flash只能从1变为0,所以写前需要擦除(变为0xFF)
  2. 擦除最小单位:4KB扇区
  3. 写操作跨页处理:页大小为256字节,跨页时需要分页写入
  4. 修改函数效率:W25Q64_ModifyByte会擦除整个扇区,频繁修改时应考虑缓存机制

这个驱动提供了基本的读写和修改功能,可以根据需要扩展更多功能(如整片擦除、快速读取等)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 20:23:49

基于RK3568的YOLOv11模型端侧部署与性能调优完整指南

文章目录 【深度实战】RK3568平台YOLO11模型从零到部署完整指南 前言 技术架构概览 一、开发环境搭建 1.1 Anaconda环境配置 1.2 RKNN工具链安装 下载核心组件 安装依赖和工具包 1.3 PyTorch环境配置 二、数据集准备与标注 2.1 数据集结构设计 2.2 图像标注工具配置 标注操作流…

作者头像 李华
网站建设 2026/6/13 7:22:55

广州沙太路属于天河区吗?具体位置解析

广州沙太路是广州市内一条重要的交通干道&#xff0c;它位于天河区北部&#xff0c;连接着天河与白云两区。这条路对于经常往来于广州大道北、广州东站附近以及白云山周边区域的市民来说十分熟悉。了解沙太路的具体区划归属&#xff0c;有助于更好地规划出行和认识广州城市格局…

作者头像 李华
网站建设 2026/6/20 4:06:11

VS2026关闭代码托管的影响与替代方案,VS2026托管功能移除

最近微软在Visual Studio 2026中移除了内置的托管功能&#xff0c;这一变化让许多开发团队需要重新评估他们的开发和部署流程。托管功能的关闭意味着以往直接通过IDE进行代码托管、构建和发布的一体化体验发生了根本改变。作为长期依赖VS进行项目管理的开发者&#xff0c;我认为…

作者头像 李华
网站建设 2026/6/20 8:47:09

在物理实验中,电子双缝衍射是一个经典的实验,它展示了电子的波动性。今天,我们就用MATLAB的GUI界面来模拟这个实验,通过输入不同的参数,观察衍射图样的变化

基于matlabgui界面下的电子双缝衍射实验的现象模拟&#xff0c;设置的可输入参数有&#xff1a;缝宽a&#xff0c;双缝间距b&#xff0c;加速电压U&#xff0c;缝屏距离D和电子数目n- 首先&#xff0c;我们需要在MATLAB中创建一个GUI界面&#xff0c;这可以通过guide命令来实现…

作者头像 李华
网站建设 2026/6/15 19:44:18

什么是真正的高清?more exceptional c 高清与HDR解析

说到高清视频内容&#xff0c;很多人第一反应是看分辨率&#xff0c;但其实“more exceptional C 高清”这个概念&#xff0c;远不止是像素数量。它本质上追求的是从拍摄源头到最终播放&#xff0c;每一个技术环节都力求卓越&#xff0c;最终在观众眼前呈现出色彩更真实、细节更…

作者头像 李华
网站建设 2026/6/18 19:04:25

如何构建AI原生企业以实现业务转型与增长?

当人工智能从辅助工具逐渐跃升为核心引擎&#xff0c;我们口中的“AI原生企业”&#xff0c;已不再只是一枚时髦标签&#xff0c;它更像一种脱胎换骨的组织形态——不是修修补补在旧体系上加入AI功能&#xff0c;而是从战略、架构到文化与流程&#xff0c;彻底以AI为底层逻辑重…

作者头像 李华