首页 > 其他分享 >stm32用spi开发W25Q128(Flash闪存芯片)

stm32用spi开发W25Q128(Flash闪存芯片)

时间:2024-07-16 20:30:29浏览次数:14  
标签:SPI1 闪存 引脚 Flash SPI W25Q128 InitStructure GPIO

前提提要spi概念

目录

stm32用spi开发W25Q128(Flash闪存芯片)

开发流程

1. 看硬件数据手册,确定通信协议,时序图,引脚
2. 初始化要用引脚

graph LR 开发流程--> A(看硬件数据手册,确定通信协议,时序图,引脚) A-->B(初始化要用引脚,时钟) B-->C(硬件spi)-->硬件spi时钟初始化--> 参考官方例程初始化硬件spi -->E(参考芯片数据手册调用函数即可) B-->D(模拟spi)-->参考时序图写代码封装数据发送函数-->E

W25Q128(Flash闪存芯片)介绍

串行Flash芯片,型号是W25Q128,容量是128Mbit,该存储IC采用SPI接口进行通信。

* 可编程块>扇区>可编程页
* 1个扇区 == 16个可编程页== 4KB
* 1个可编程块 == 16个扇区==64KB
* 该存储IC由65536个可编程页组成,每个可编程页的大小是256字节,所以存储IC的容量是16MB
* 一次最多可以编程256字节

内存分布

1个可编程块是由16个可编程扇区组成
该存储IC一共有256个可编程块,一个可编程块是64KB

image

引脚说明

image

image

指令介绍

(1) 写使能指令 0x06

折叠重要但又不重要的图片

image

(2) 读状态寄存器 0x35

折叠重要但又不重要的图片

image

(3) 写失能指令 0x04

折叠重要但又不重要的图片

image

(4) 擦除扇区指令 0x20

折叠重要但又不重要的图片

image
image

(5) 读取厂商和设备ID 0x90

折叠重要但又不重要的图片

image

代码

点击查看代码

void W25Q128_Config(void)
{
  SPI_InitTypeDef  SPI_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  //打开SPI1的时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  //打开GPIOB端口的时钟
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
  
  //选择IO口的复用功能
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1);		//SCK
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1);		//MISO
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1);     	//MOSI

  GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AF;					//复用模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
  GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  //配置CS片选引脚  输出模式  
  GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_14;
  GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
    
  //片选引脚,空闲状态为高电平
  W25Q128_CS(1);

  //配置SPI1  W25Q128存储IC支持模式0和模式3
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;	//全双工
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;							//主模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;						//8bit数据位
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;							//时钟极性  1
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;							//时钟相位  1    11 --模式3
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;								//软件控制CS片选	
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;	

  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;					//高位先出
  SPI_Init(SPI1, &SPI_InitStructure);

  //使能SPI1
  SPI_Cmd(SPI1, ENABLE);

}

//发送一个字节,并且会得到一个字节
uint8_t W25Q128_SendByte(uint8_t byte)
{
  /*!< Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

  /*!< Send byte through the SPI1 peripheral */
  SPI_I2S_SendData(SPI1, byte);

  /*!< Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /*!< Return the byte read from the SPI bus */
  return SPI_I2S_ReceiveData(SPI1);
}


//读取设备ID   0x17
uint8_t W25Q128_ReadDeviceID(void)
{
	uint8_t device_id = 0;
	
	//1.把片选引脚拉低
	W25Q128_CS(0);
	
	//2.MCU发送指令  0x90
	W25Q128_SendByte(0x90);
	
	//3.MCU发送地址
	W25Q128_SendByte(0x00);
	W25Q128_SendByte(0x00);
	W25Q128_SendByte(0x00);

	//4.MCU提供脉冲,得到厂商ID 
	W25Q128_SendByte(0xFF);
	
	//5.MCU提供脉冲,得到设备ID
	device_id = W25Q128_SendByte(0xFF);
	
	//6.把片选引脚拉高
	W25Q128_CS(1);
	
	return device_id;
}


int main()
{
	uint8_t buf[128] = {0};
	
	//1.硬件的初始化
	USART1_Config(9600);
	W25Q128_Config();
	
	//2.读取W25Q128的设备ID
	sprintf((char *)buf,"Device ID = %#X\r\n",W25Q128_ReadDeviceID());
	USART1_SendString((char *)buf);
	
	while(1)
	{
		
	}
}

重要:模拟spi可以看上篇文章,主要是将端口初始化修改还有传输数据修改即可

** #define W25Q128_CS(n) (n) ? GPIO_SetBits(GPIOB,GPIO_Pin_14) : GPIO_ResetBits(GPIOB,GPIO_Pin_14) **


参考李明轩老师笔记

标签:SPI1,闪存,引脚,Flash,SPI,W25Q128,InitStructure,GPIO
From: https://www.cnblogs.com/shishusheng/p/18306040

相关文章

  • 开发板测试手册——SPI FLASH 读写、USB WIFI 模块(2)
    前言本文适用开发环境:Windows开发环境:Windows764bit、Windows1064bitLinux开发环境:Ubuntu14.04.364bit虚拟机:VMware15.1.0U-Boot:U-Boot-2017.01Kernel:Linux-4.9.0、Linux-RT-4.9.0进行本文档操作前,请先按照调试工具安装、Linux开发环境搭建相关文档,安装......
  • FlashAttention/ PagedAttention原理,大模型加速
    1.1GPU硬件特点由于FlashAttention计算self-attention的主要关键是有效的硬件使用,所以了解GPU内存和各种操作的性能特征是很有必要的。以A100(40GBHBM)为例,下面显示其内存层次结构的粗略图。SRAM内存分布在108个流式多处理器(SMs)上,每个处理器192KB。片上SRAM比......
  • NAND Flash基础介绍 一
    ChipCI颗粒厂商提供的是整个一块晶圆,晶圆上已经把芯片划分好了,如下图模组厂商或者颗粒厂商会把晶圆拿去分割,拆分出一个个芯片,每个拆分下来的芯片型号、工艺、空间大小等由颗粒厂家提前定制好了,具体说明可参考https://www.cnblogs.com/studywithallofyou/p/18291633。该文档介......
  • 单片机-Flash动态自保存
         说明:该方法为固定大小的数据包方式进行记录,写满一页后再擦除设定页从新记录,增加Flash使用寿命。    环境需求:Flash需要可程序读写。    以STM32,中容量为例(HAL库方式)。        注意事项:避开程序空间,注意页的大小有的为1K,有的为2K按需......
  • 三星 NAND FLASH命名规范 Samsung NAND Flash Code Information
    一共有三页,介绍了前面主要的编号和横杠后面的编号,当前文档只关注前面的编号。从前面的命名规范中可以得知当前芯片的容量、技术等概要信息,对芯片有一个整体了解。详细解释SmallClassification表示存储单元的类型和应用,比如SLC1ChipXDCard表示是SLC的,包含1个Chip的XD......
  • 痞子衡嵌入式:浅聊恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源(上篇)
    大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦i.MXRT官方SDK里关于串行Flash相关的驱动与例程资源。经常有同事以及i.MXRT客户咨询痞子衡,咱们恩智浦官方SDK里有哪些串行Flash相关的示例,每一次痞子衡都是按照询问需求将SDK里相应资源路径......
  • LVGL一键打包图片工具,全部图片打包成一个bin文件,支持nor flash XIP模式下直接访问数据
    最近做工程项目,需要用到LVGL,但是搜了很长时间没有看到合适的图片打包工具,大多都是生成数组或者单个的bin文件,这样烧录到norflash很麻烦后来看到一篇博客,博主的想法与我类似,不过他后面部分就做的麻烦了,所以,我直接从头写了一个工具,他的博客地址:https://www.wpgdadatong.com.cn/blo......
  • Oracle闪回(Flashback)功能简介
        在Oracle数据库中,ASOFTIMESTAMP语法用于使用时间戳技术访问特定时间之前的数据,或者说把数据库回滚到某个时间点以前的状态。它基于Oracle的时间戳功能,允许用户查询某个表在特定时间点的快照。其语法如下:SELECT<COLUMNS>FROM<TABLE>ASOFTIMESTAMP<TIMESTAMP>......
  • 存储读写之FLASH篇2-本篇内容来自野火文档
    STM32的内部FLASH简介在STM32芯片内部,存在一个重要的FLASH存储器,其主要用途是存储应用程序代码。编写完应用程序后,通常需要使用下载工具将已编译的代码文件写入内部FLASH。不可忽视的是,内部FLASH具有非易失性存储的特性,这意味着在断电后存储的数据不会丢失。每次芯片重新上......
  • 7月1日 STM32F407VET6对Flash的入门学习(记录)
    1、Flash的使用之前必须对Flash进行擦除,不能直接写入进行覆盖。其原因是Flash的工作原理存储二进制的0和1,且只能实现从1到0的变化。这就意味着但Flash中已经烧入由0和1组成的文件后,无法直接再次烧入其他二进制文件。必须使用特定的函数将Flash中已存在的0和1全部转换成1,这个就......