news 2026/5/6 23:26:43

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/5/4 16:00:55

Java程序员必备并发知识如何高效学习?

有出去面试的朋友肯定深有感受&#xff0c;像我们刚入行那会面试的加分项现在卷得已经成为了面试的基础题&#xff08;手动狗头&#xff09;。其中最典型的就属这个Java并发编程了。之前一般只有大厂才会有高并发编程相关的面试内容&#xff0c;但现在只要你入了Java行业就会涉…

作者头像 李华
网站建设 2026/4/28 12:29:55

系统可视化与配置化控制的实现经验与教训

系统可视化与配置化控制的实现经验与教训 关键词:系统可视化监控、配置化控制、业务大盘设计、线上事故应急方案、高可控系统架构 刚入大厂那几年,我一直有个错觉: 只要代码写得足够严谨,逻辑足够完善,系统就不会出大问题。 直到后来亲手接过一个线上资金系统,再经历过几…

作者头像 李华
网站建设 2026/4/28 12:30:50

Java毕设项目推荐-基于springboot的装修公司客户家装项目进度系统基于springboot的装修公司家装项目管理系统【附源码+文档,调试定制服务】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/5/5 12:34:06

Redis启用AOF持久化的利弊分析:安全与性能如何权衡

对于Redis的使用者来说&#xff0c;是否开启“appendonly yes”是一个关键的配置决策。它决定了数据持久化的方式&#xff0c;直接关系到数据安全性和系统性能的平衡。我将基于运维实践经验&#xff0c;分享这一配置的核心考量与实际影响。 appendonly yes如何保证数据安全 开启…

作者头像 李华
网站建设 2026/5/3 15:26:21

unix shell编程 pdf 教程推荐与学习指南

对于Unix/Linux系统管理员和开发者来说&#xff0c;掌握shell编程是必备技能之一。PDF格式的学习资料因其便于保存、打印和离线阅读的特点&#xff0c;成为许多人系统学习shell编程的首选。通过精心整理的PDF资源&#xff0c;我们可以从基础语法到高级技巧&#xff0c;逐步构建…

作者头像 李华