软件SPI读写W25Q64硬件SPI读写W25Q64

article/2025/8/22 1:42:49

目录

软件SPI读写W25Q64 

MySPI

W25Q64

主函数

硬件SPI读写W25Q64


软件SPI读写W25Q64 

  • 程序整体框架:

SPI模块包含通信引脚封装,初始化,SPI三个基本时序单元(起始,终止,交换一个字节)

W25Q64通过调用SPI基本时序完成整个时序(写使能,页编程,擦除,读数据)

主函数中调用W25Q64的硬件驱动层函数时序功能

MySPI

#include "stm32f10x.h"                  // Device headervoid MySPI_W_CS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}
void MySPI_W_CLK(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_5,(BitAction)BitValue);
}
void MySPI_W_MOSI(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_7,(BitAction)BitValue);
}
uint8_t MySPI_R_MISO(void)
{return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6);
}void MySPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_Init_Structure;//要求配置为推挽输出,浮空或上拉输入GPIO_Init_Structure.GPIO_Mode=GPIO_Mode_IPU;GPIO_Init_Structure.GPIO_Pin=GPIO_Pin_6;GPIO_Init_Structure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Init_Structure);GPIO_Init_Structure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_Init_Structure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7;GPIO_Init_Structure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Init_Structure);MySPI_W_CS(1);MySPI_W_CLK(0);
}
//三个基本时序:起始,交换数据,终止
void MySPI_Start(void)
{MySPI_W_CS(0);
}
void MySPI_Stop(void)
{MySPI_W_CS(1);
}
//通过掩码,依次挑出每一位操作,优点是保留了原数据的值
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{uint8_t i,ByteReceive = 0x00;for(i = 0;i < 8;i ++){MySPI_W_MOSI(ByteSend &(0x80>>i));MySPI_W_CLK(1);if(MySPI_R_MISO() == 1){ByteReceive |= (0x80 >> i);}MySPI_W_CLK(0);}return ByteReceive;
}//还可以按照移位示意图中的方式交换数据,优点是效率高,但不能保存原数据值
//uint8_t MySPI_SwapByte(uint8_t ByteSend)
//{
//	 uint8_t i;
//   for(i=0;i<8;i ++)
//    {
//    	MySPI_W_MOSI(ByteSend &0x80);
//		ByteSend <<=1;			//最高位移出,最后补0
//    	MySPI_W_CLK(1);
//    	if(MySPI_R_MISO() == 1) {ByteSend |= 0x01;}	 //输入的数据放在最低位
//    	MySPI_W_CLK(0);
//    }
//    return ByteSend;
//}

W25Q64

在注意事项中:写入操作后,芯片进入忙状态。这里通过定义的函数进行事前等待和事后等待。

事前等待:1、写入前先等待,等不忙了再写入   2、效率高。  3、在写入和读取操作之前都要等待。

事后等待:1、写入后立刻等待,不忙了退出。  2、这样最保险,函数结束后,函数之外的地方芯片肯定不忙。  3、只需在写入后等待。

#include "stm32f10x.h"                  // Device header
#include "MySPI.H"
#include "W25Q64_INS.H"void W25Q64_Init(void)
{MySPI_Init();
}
//用指针的方式来获取多个函数的值!!!
void W25Q64_ReadID(uint8_t *MID,uint16_t *DID)
{MySPI_Start();MySPI_SwapByte(W25Q64_JEDEC_ID);*MID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);*DID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);*DID <<= 8;*DID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE);MySPI_Stop();
}
void W25Q64_WiteEnable(void)
{MySPI_Start();MySPI_SwapByte(W25Q64_WRITE_ENABLE);MySPI_Stop();
}
/*** @brief 直到BUSY清零后结束* @param  * @retval */
void W25Q64_WaitBusy(void)
{uint32_t Timeout=100000;  //为了防止卡死MySPI_Start();MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);//直到busy不为1while((MySPI_SwapByte(0xFF) & 0X01) == 0X01){Timeout--;if(Timeout == 0){break;}}MySPI_Stop();
}//页编程写入,注意页编程写入一页的范围
void W25Q64_PageProgram(uint32_t Address,uint8_t *DataArray,uint16_t count)	
{//没有24位,通过数组可以传多个字节。所以用32位,写入数据的数量范围0-256,所以用uint16不用uint8W25Q64_WiteEnable();uint16_t i;MySPI_Start();MySPI_SwapByte(W25Q64_PAGE_PROGRAM);MySPI_SwapByte(Address >> 16);MySPI_SwapByte(Address >> 8);	//高两位会丢弃MySPI_SwapByte(Address);for(i=0;i < count ;i++){MySPI_SwapByte(DataArray[i]);}MySPI_Stop();W25Q64_WaitBusy();
}void W25Q64_SectorErase(uint32_t Address)	
{//写使能仅对之后跟随的一条时序有效,结束之后会失能,所以每个函数加入这个就不用再写失能W25Q64_WiteEnable();MySPI_Start();MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);MySPI_SwapByte(Address >> 16);MySPI_SwapByte(Address >> 8);	MySPI_SwapByte(Address);MySPI_Stop();W25Q64_WaitBusy();
}void W25Q64_ReadData(uint32_t Address,uint8_t *DataArray,uint32_t count)	//改为32位
{	uint32_t i;MySPI_Start();MySPI_SwapByte(W25Q64_READ_DATA);MySPI_SwapByte(Address >> 16);MySPI_SwapByte(Address >> 8);	MySPI_SwapByte(Address);for(i=0;i < count ;i++){//调用交换读取之后,内部指针自动自增DataArray[i]=MySPI_SwapByte(W25Q64_DUMMY_BYTE);}MySPI_Stop();
}

主函数

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.H"
#include "Key.h"
#include "OLED.H"
#include "W25Q64.H"uint8_t MID;
uint16_t DID;uint8_t ArrayWrite[]={0x55,0x66,0x77,0x88};
uint8_t ArrayRead[4];
int main(void)
{OLED_Init();W25Q64_Init();OLED_ShowString(1,1,"MID:   DID:");OLED_ShowString(2,1,"W:");OLED_ShowString(3,1,"R:");W25Q64_ReadID(&MID,&DID);OLED_ShowHexNum(1,5,MID,2);OLED_ShowHexNum(1,12,DID,4);//只擦除不写入,可以验证flash擦除之后变为ff//不擦除直接改写,可以测试不能由0到1,只能1到0//写之前先擦除。xxx000-xxffffW25Q64_SectorErase(0x000000); 	//页地址范围xxxx00-xxxxffW25Q64_PageProgram(0X000000,ArrayWrite,4); W25Q64_ReadData(0X000000,ArrayRead,4);OLED_ShowHexNum(2,3,ArrayWrite[0],2);OLED_ShowHexNum(2,6,ArrayWrite[1],2);OLED_ShowHexNum(2,9,ArrayWrite[2],2);OLED_ShowHexNum(2,12,ArrayWrite[3],2);OLED_ShowHexNum(3,3,ArrayRead[0],2);OLED_ShowHexNum(3,6,ArrayRead[1],2);OLED_ShowHexNum(3,9,ArrayRead[2],2);OLED_ShowHexNum(3,12,ArrayRead[3],2);while(1){}
}
  • 验证不能跨页写入时,

W25Q64_PageProgram(0X0000ff,ArrayWrite,4); 
W25Q64_ReadData(0X000000,ArrayRead,4);

因为读可以跨页,此时读到的结果为 55 FF FF FF

改为这句W25Q64_ReadData(0X000000,ArrayRead,4);结果如下。说明不能跨页存储,超过范围会从页开始存储。

硬件SPI读写W25Q64

只需要修改底层MySPI文件,将软件实现改为硬件实现,之后基于通信层的业务代码不用改变

转移到移位寄存器后会自动生成波形,硬件自动生成不需要像软件那样置高低电平

#include "stm32f10x.h"                  // Device headervoid MySPI_W_CS(uint8_t BitValue)
{GPIO_WriteBit(GPIOA,GPIO_Pin_4,(BitAction)BitValue);
}void MySPI_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);GPIO_InitTypeDef GPIO_Init_Structure;//硬件外设控制的输出MOSI,SCK;用复用推挽输出GPIO_Init_Structure.GPIO_Mode=GPIO_Mode_AF_PP;GPIO_Init_Structure.GPIO_Pin=GPIO_Pin_5 | GPIO_Pin_7;GPIO_Init_Structure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Init_Structure);//软件控制的输出信号ss,通用推挽输出GPIO_Init_Structure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_Init_Structure.GPIO_Pin=GPIO_Pin_4;GPIO_Init_Structure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Init_Structure);//MISOGPIO_Init_Structure.GPIO_Mode=GPIO_Mode_IPU;GPIO_Init_Structure.GPIO_Pin=GPIO_Pin_6;GPIO_Init_Structure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_Init_Structure);SPI_InitTypeDef SPI_InitStrcture;SPI_InitStrcture.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_128;//配置模式SPI_InitStrcture.SPI_CPHA=SPI_CPHA_1Edge;		//第一个边沿采样SPI_InitStrcture.SPI_CPOL=SPI_CPOL_Low; SPI_InitStrcture.SPI_CRCPolynomial=7;SPI_InitStrcture.SPI_DataSize=SPI_DataSize_8b;SPI_InitStrcture.SPI_Direction=SPI_Direction_2Lines_FullDuplex;SPI_InitStrcture.SPI_FirstBit=SPI_FirstBit_MSB;    //高位先行SPI_InitStrcture.SPI_Mode=SPI_Mode_Master;		//主机模式SPI_InitStrcture.SPI_NSS=SPI_NSS_Soft;SPI_Init(SPI1,&SPI_InitStrcture);//不要忘记开使能SPI_Cmd(SPI1,ENABLE);//默认不选择从机MySPI_W_CS(1);}
//三个基本时序:起始,交换数据,终止
void MySPI_Start(void)
{MySPI_W_CS(0);
}
void MySPI_Stop(void)
{MySPI_W_CS(1);
}//四步
uint8_t MySPI_SwapByte(uint8_t ByteSend)
{while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) != SET);SPI_I2S_SendData(SPI1,ByteSend);//发送接收同步,当接收完成标志着发送也完成while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) != SET);return SPI_I2S_ReceiveData(SPI1);}

TXE RXNE标志位不用手动清除,中断标志位进中断后必须手动清除 

 


http://chatgpt.dhexx.cn/article/MOiXxIV6.shtml

相关文章

W25Q64Flash芯片STM32操作

1、W25Q64Flash芯片介绍 通讯方式&#xff1a;SPI通讯 大小&#xff1a;8M&#xff08;Byte&#xff09; &#xff08;128块&#xff08;Block&#xff09;&#xff0c;每块64K字节&#xff0c;每块16个扇区&#xff08;Sector&#xff09;&#xff0c;每个扇区4K字节&…

STM32学习笔记(十一)丨SPI通信(W25Q64芯片简介,使用SPI读写W25Q64存储器芯片)

本篇文章包含的内容 一、SPI的通信协议及其原理1.1 SPI简介1.2 SPI通信的硬件连接1.3 SPI的时序基本单元1.3.1 起始条件和终止条件1.3.2 交换字节&#xff08;模式0&#xff0c;先移入&#xff0c;再移出&#xff09;1.3.3 交换字节&#xff08;模式1&#xff0c;先移出&#x…

看单片机原理图-外部FLASHW25Q64

系列文章目录 看单片机原理图-最小系统 看单片机原理图-最小系统电源电路 看单片机原理图-输入输出电路LED指示、按键输入 看单片机原理图-红外遥控、EEPROM 看单片机原理图-FLASH 文章目录 系列文章目录前言一、FLASH 前言 硬件&#xff1a;百问网100ASK_STM32F103_MINI开发…

W25Q64 Flash芯片原理与应用方案(含W25Q64中文数据手册)

W25Q64是华邦公司推出的大容量SPI FLASH产品&#xff0c;其容量为64Mb&#xff08;8MB&#xff09;&#xff0c;应用较为广泛。 W25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件。W25Q64将8M字节的容量分为128个块&#xff0c;每个块大小为64K字节&#xff0c;每个…

cortex_m3_stm32嵌入式学习笔记(二十一):SPI实验(通信总线)

SPI 是英语 Serial Peripheral interface 的缩写&#xff0c;顾名思义就是串行外围设备接口。是 Motorola首先在其 MC68HCXX 系列处理器上定义的。 SPI 接口主要应用在 EEPROM&#xff0c; FLASH&#xff0c;实时时钟&#xff0c; AD 转换器&#xff0c;还有数字信号处理器和数…

STM-32:SPI通信协议/W25Q64简介—软件SPI读写W25Q64

目录 一、SPI简介1.1电路模式1.2通信原理1.3SPI时序基本单元1.3.1起始和终止1.3.2交换字节 二、W25Q642.1W25Q64简介2.2W25Q64硬件电路2.3W25Q64框图2.4Flash操作注意事项 三、软件SPI读写W25Q643.1接线图3.2程序代码 一、SPI简介 SPI是串行外设接口&#xff08;Serial Periph…

STM32CubeMx之硬件SPI驱动W25Q64

STM32CubeMx之硬件SPI驱动W25Q64 1.SPI简介 SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚&a…

SPI读写串行FLASH(W25Q64)

文章目录 1、SPI协议1、硬件连接2、通讯时序3、不同的通信模式 2、W25Q64介绍3、SPI读写驱动编写4、源码 1、SPI协议 SPI 协议是由摩托罗拉公司提出的通讯协议(Serial Peripheral Interface)&#xff0c;即串行外围设备接口&#xff0c;是一种高速全双工的通信总线。它被广泛地…

STM32入门开发: 介绍SPI总线、读写W25Q64(FLASH)(硬件+模拟时序)

一、环境介绍 编程软件: keil5 操作系统: win10 MCU型号: STM32F103ZET6 STM32编程方式: 寄存器开发 (方便程序移植到其他单片机) SPI总线: STM32本身支持SPI硬件时序&#xff0c;本文示例代码里同时采用模拟时序和硬件时序两种方式读写W25Q64。 模拟时序更加方便移植到…

树莓派系统介绍

树莓派是一个微型计算机&#xff0c;和普通的电脑没有什么区别&#xff0c;只是体积更小&#xff0c;只有卡片大小&#xff0c;存储能力和计算能力会差一点&#xff0c;主要用于学习&#xff0c;实验所用。 是电脑就要安装操作系统&#xff0c;树莓派官方推荐了两种系统&#…

树莓派 zero linux,树莓派 zero基本调试

回家之前就从网上购买了一堆设备&#xff0c;回去也不能闲着&#xff0c;可以利用家里相对齐全的准备安装调试。结果人还没回来&#xff0c;东西先到了。 购买的核心装备是树莓派zero w&#xff0c;虽然已经知道它比家族大哥树莓派小不少&#xff0c;但拿到手里还是惊奇它的小巧…

树莓派c语言访问mariadb,树莓派之MariaDB

8种机械键盘轴体对比 本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f; 安装MariaDB MariaDB是MySQL的一个分支 直接命令行敲入&#xff1a;1sudo apt-get install mariadb-server 即可完成安装。 一开始安装完成后不知道是需要初始化…

python树莓派_树莓派python

广告关闭 腾讯云11.11云上盛惠 &#xff0c;精选热门产品助力上云&#xff0c;云服务器首年88元起&#xff0c;买的越多返的越多&#xff0c;最高返5000元&#xff01; 最初拿到树莓派的时候测试过,没成功,后来发现一张华丽丽的说明图,顿时醒悟了.. 记录下来,主要学习自 :htt…

树莓派硬件介绍及配件选择

目录 树莓派Datasheet下载地址&#xff1a; Raspberry 4B 外观图&#xff1a; 技术规格书&#xff1a; 性能介绍&#xff1a; 树莓派配件选用 电源的选用&#xff1a; 树莓派外壳选用&#xff1a; 内存卡/U盘选用 树莓派Datasheet下载地址&#xff1a; Raspberry Pi …

树莓派Pico开发版

Pico开发版有16个PWM通道非常适合用于舵机及电机的控制[1]。 单板机(4B)、微控制器(Pico)&#xff0c;树莓派支持Micro Python和C编程[3]。Thony是Python的开发环境。 [1]【评测】树莓派Pico开发板详细评测&#xff0c;到底值不值&#xff1f; [2] Pico树莓派中文站。 [3]一…

1-树莓派及配件购买推荐

树莓派4b主板及配件购买推荐。 作者&#xff1a;白宸羽 套餐 购买链接&#xff1a;https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-22269478747.11.277c1a24rkExbq&id597680312428 TF卡建议选择16g&#xff0c;套餐建议选择“摄像头套餐” HDMI用于连接显示屏&a…

python树莓派编程_python树莓派编程

广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! 例如,你可以用树莓派搭建你自己的家用云存储服务器。? 树莓派用python来进行编程。 树莓派项目的一个核心思想是python编程语言的使用。 python允许树莓派的拥…

树莓派如何第一次启动-树莓派从购买到启动一步一步完全版!

背景 闲来无事&#xff0c;在咸鱼上买了一个树莓派3B。买来配件都十分齐全&#xff0c;于是就想着启动来测试一下。下面是树莓派第一次启动的全过程&#xff0c;包含安装系统。 1 准备工作 1.1所需硬件 笔记本电脑、树莓派3B、16GTF卡、读卡器、电源和电源线共四种。 无需准…

树莓派价格暴涨买不起?他们自己做了一块价格还不到1/4的开发板平替树莓派,还火到海外去了

众所周知&#xff0c;树莓派诞生之初时的设计有四大要点 一个可编程的硬件&#xff08;功能很强&#xff09;√足够有趣&#xff0c;能吸引年轻人&#xff08;可玩性确实高&#xff09;√能反复扔进书包&#xff0c;不怕挤坏&#xff08;质量杠杠滴&#xff09;√ 还有最后一…

当你拿到树莓派后要干什么

最近刚买了一个树莓派&#xff08;pi4 8g&#xff09;&#xff0c;先在分享一些搭建细节&#xff0c;帮助他人更快上手 1.烧录sd卡 官网下载文件 Operating system images – Raspberry Pihttps://www.raspberrypi.com/software/operating-systems/ 下载烧录工具&#xff1a…