SPI驱动W25Q64

news/2024/7/10 19:22:05 标签: stm32, 开源, 嵌入式硬件, c语言

文章目录

  • 前言
  • 一、硬件电路
  • 二、W25Q64初始化
  • 三、W25Q64读数据
  • 四、W25Q64写数据


前言

在这里插入图片描述

一、硬件电路

PA15为W25Q64片选线配置为GPIO输出模式
在这里插入图片描述

二、W25Q64初始化

在这里插入图片描述

通过SPI读取设备ID验证是否能正确读写

static int ReadID(void){
	uint8_t cmd = 0x9F;
	uint8_t data[3] = {0};
	W25Q64CSLOW;
	HAL_StatusTypeDef status =  HAL_SPI_Transmit(&hspi1, &cmd, 1, 10);
	if(status != HAL_OK){
		LogDebug("ReadID HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}

	status =  HAL_SPI_Receive(&hspi1, data, 3, 10);
	if(status != HAL_OK){
		LogDebug("ReadID HAL_SPI_Receive ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}
	W25Q64CSGIGH;
	int id = (data[0]<<16) | (data[1]<<8) | (data[2]<<0);
	return id;
}

static int W25Q64Init(void){
	uint32_t id = ReadID();
	if(id != 0xEF4017){
		LogDebug("W25Q64Init  ERROR\r\n");
		return -EIO;
	}
	LogDebug("W25Q64Init id is %X\r\n",id);
}

三、W25Q64读数据

在这里插入图片描述
该指令 允许读出一个字节或一个以上的字节。先把 /CS引脚 拉低为低电平,然后把 03h 通过DI引脚 写入芯片,再送入 24位的地址,这些数据将在 CLK 的上升沿被芯片采集。芯片接收完 24位地址 之后,就会把相应地址的数据在 CLK引脚的下降沿从 DO引脚 发送出去,高位在前。当发送完这个地址的数据之后,地址将自动增加,然后通过 DO引脚把 下一个地址的数据发送出去,从而形成一个 数据流。也就是说,只要时钟在工作,通过 一条读指令,就可以把 整个芯片存储区的数据读出来。

static int W25Q64Read(uint32_t addr,uint8_t *pdata,uint32_t length){

	uint8_t data[4] = {0};
	data[0] = 0x03;
	data[1] = (addr & 0xFF0000)>>16;
	data[2] = (addr & 0x00FF00)>>8;
	data[3] = (addr & 0x0000FF)>>0;
	
	W25Q64CSLOW;
	HAL_StatusTypeDef status =  HAL_SPI_Transmit(&hspi1, data, 4, 10);
	if(status != HAL_OK){
		LogDebug("W25Q64Read HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}

	status =  HAL_SPI_Receive(&hspi1, pdata, length, 100);
	if(status != HAL_OK){
		LogDebug("W25Q64Read HAL_SPI_Receive ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}
	W25Q64CSGIGH;
	
	return ESUCCESS; 
}

四、W25Q64写数据

  1. 写使能指令(06h)
    该指令会使 状态寄存器WEL位置位。在执行每个页编程、扇区擦除、块擦除、芯片擦除和写状态寄存器等指令之前,都要先置位 WEL。/CS引脚 先拉低为低电平后,写使能指令代码 06h 从 DI引脚输入,在 CLK上升沿采集,然后将 /CS引脚 拉高为高电平。
    在这里插入图片描述
//在页写和擦除等指令完成后 写使能位会被自动置0 因此每次要写数据之前必须开启写使能位
static int WriteEnable(void){
	uint8_t cmd = 0x06;
	W25Q64CSLOW;
	HAL_StatusTypeDef status =  HAL_SPI_Transmit(&hspi1, &cmd, 1, 10);
	if(status != HAL_OK){
		LogDebug("WriteEnable HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}
	W25Q64CSGIGH;
	return ESUCCESS;
}

//等待页写或者擦除完成
static int WaitWriteEnd(void){
	uint8_t cmd = 0x05;
	uint8_t registerStatus = 0;
	W25Q64CSLOW;
	HAL_StatusTypeDef status =  HAL_SPI_Transmit(&hspi1, &cmd, 1, 10);
	if(status != HAL_OK){
		LogDebug("WriteEnable HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}

	status =  HAL_SPI_Receive(&hspi1, &registerStatus, 1, 10);
	if(status != HAL_OK){
		LogDebug("WriteEnable HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}

	while(registerStatus & 0x01){
		status = HAL_SPI_Receive(&hspi1, &registerStatus, 1, 10);
		if(status != HAL_OK){
			LogDebug("WriteEnable HAL_SPI_Transmit ERROR\r\n");
			W25Q64CSGIGH;
			return -EIO;
		}
	}
	W25Q64CSGIGH;
	return ESUCCESS;
}
  1. 写禁止指令(04h)
    该指令将会使 WEL位 变为0。/CS引脚 拉低为低电平后,再把 04h 从 DI引脚 输入到芯片,将 /CS引脚 拉高为高电平后,就可完成这个指令。

在执行完 写状态寄存器、页编程、扇区擦除、块擦除、芯片擦除等指令之后,WEL位就会自动变为 0。
在这里插入图片描述

  1. 页写(0x02)
    该指令会从指定地址的页开始写数据,当要写的数据超过当前页最大地址时,从该页的首地址覆盖写。
    在页写之前要对该页进行擦除。因为W25Q64在存储数据时是将内存中的1置为0来实现的,所以在写数据时要先擦除写地址的数据。
    在这里插入图片描述
static int PageWrite(uint32_t addr,uint8_t *pdata,uint32_t length){
	if(length > 256)
		length = 256;

	uint8_t data[4] = {0};
	data[0] = 0x02;
	data[1] = (addr & 0xFF0000)>>16;
	data[2] = (addr & 0x00FF00)>>8;
	data[3] = (addr & 0x0000FF)>>0;
	int ret = WriteEnable();
	if(ret != ESUCCESS){
		LogDebug("PageWrite WriteEnable ERROR\r\n");
		return -EIO;
	}
	
	W25Q64CSLOW;
	HAL_StatusTypeDef status =  HAL_SPI_Transmit(&hspi1, data, 4, 10);
	if(status != HAL_OK){
		LogDebug("PageWrite HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}

	status =  HAL_SPI_Transmit(&hspi1, pdata, length, 100);
	if(status != HAL_OK){
		LogDebug("PageWrite HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}
	W25Q64CSGIGH;

	ret = WaitWriteEnd();
	if(ret != ESUCCESS){
		LogDebug("PageWrite WaitWriteEnd ERROR\r\n");
		return -EIO;
	}
	return ESUCCESS; 
	
}
  1. 扇区擦除
    W25Q64擦除的最小单位为4K的扇区。
    例如输入0-4095之间的地址,会将第一个扇区擦除。输入任意地址,会将该地址所处于的扇区擦除。
    在这里插入图片描述

static int SectorErase(uint32_t addr){
	uint8_t data[4] = {0};
	data[0] = 0x20;
	data[1] = (addr & 0xFF0000)>>16;
	data[2] = (addr & 0x00FF00)>>8;
	data[3] = (addr & 0x0000FF)>>0;
	int ret = WriteEnable();
	if(ret != ESUCCESS){
		LogDebug("SectorErase WriteEnable ERROR\r\n");
		return -EIO;
	}
	
	W25Q64CSLOW;
	HAL_StatusTypeDef status =  HAL_SPI_Transmit(&hspi1, data, 4, 10);
	if(status != HAL_OK){
		LogDebug("SectorErase HAL_SPI_Transmit ERROR\r\n");
		W25Q64CSGIGH;
		return -EIO;
	}
	W25Q64CSGIGH;

	ret = WaitWriteEnd();
	if(ret != ESUCCESS){
		LogDebug("SectorErase WaitWriteEnd ERROR\r\n");
		return -EIO;
	}
	return ESUCCESS; 
}

http://www.niftyadmin.cn/n/5424098.html

相关文章

C++进阶之路---二叉搜索树详解 | 具体实现

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、二叉搜索树简介 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树&am…

Stable Diffusion 模型下载:Comic Babes(漫画宝贝)

本文收录于《AI绘画从入门到精通》专栏&#xff0c;专栏总目录&#xff1a;点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八 下载地址 模型介绍 条目内容类型大模型基础模型SD 1.5来源CIVITAI作者datmuttdoe文件名称comicBabes_v2.safet…

[Linux_IMX6ULL应用开发]-hello程序的交叉编译

目录 【开发板、虚拟机和PC的三者联通】 使用串口连接到开发板 连接Ubuntu虚拟机 互ping测试 【交叉编译hello.c文件】 Ubuntu编译无法在板子运行问题 使用交叉编译链编译hello.c 【开发板、虚拟机和PC的三者联通】 在这里我们使用IMX6ULL-PRO开发板进行学习&#xff0c;…

Doris部署学习(一)

目录 前言 一、Docker容器支持 二、Doris编译步骤 1.拉取镜像 2.构建Docker编译容器 3.下载源码并编译 前言 本文档主要介绍如何通过源码在Docker编译 Doris&#xff0c;以及部署。 一、Docker容器支持 Docker教程&#xff1a;Docker & Docker-Compose 安装教程 - 知…

java-新手笔记(枚举)

枚举&#xff08;Enumeration&#xff09;是一种特殊的类&#xff0c;用于表示固定数量的常量值。 枚举类型使得代码更加清晰&#xff0c;易于维护&#xff0c;同时也增加了类型安全。 这边使用一个枚举封装重要数据 enum Day {SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FR…

PCL点云处理之最小二乘球面点云拟合(直接拟合法,完整实验)(二百三十一)

PCL点云处理之最小二乘球面点云拟合(直接拟合法,完整实验)(二百三十一) 一、算法介绍二、算法实现1.代码2.结果一、算法介绍 现在假设有这样一群点云,它们分布在一个球的表面,可能并不严格,带有些许噪声,此时我们需要计算球心坐标和球的半径。(这里提供完整的实验过…

一条 sql 语句可能导致的表锁和行锁以及死锁检测

锁 MDL 当对一个表做增删改查操作的时候&#xff0c;加 MDL 读锁&#xff1b;当要对表做结构变更操作的时候&#xff0c;加 MDL 写锁 ALTER TABLE tbl_name NOWAIT add column ... ALTER TABLE tbl_name WAIT N add column ... …

Redis基本概念

什么是Redis 官方文档 Redis(Remote Dictionary Server) Redis 是一个开源的使用 ANSIC 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库&#xff0c;并提供多种语言的 API 的非关系型数据库。 传统数据库遵循 ACID 规则。而 Nosql&…