本文主要是介绍W25Q32驱动 基于HAL库的SPI,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
环境
芯片:STM32F103ZET6
库:来自HAL的STM32F1XX.H
原理图
cubeMX配置
W25Q32.h
//
// Created by seven on 2024/9/2.
//#ifndef SPI_W25Q32_H
#define SPI_W25Q32_H
#include "spi.h"/*** 初始化W25Q32闪存芯片*/
void W25Q32_Init(void);/*** 停止W25Q32闪存芯片的操作*/
void w25q32_Stop(void);/*** 读取W25Q32闪存芯片的ID* @param sid 存储制造商ID的指针* @param mid 存储设备ID的指针*/
void W25Q32_ReadId(uint8_t *sid,uint16_t *mid);/*** 等待W25Q32闪存芯片不忙* 原理是发送05h指令,循环读取状态寄存器(8位),直到第0位变为0,表示芯片不忙*/
void Inf_W25Q32_WaitNotBusy(void);/*** 使能W25Q32闪存芯片的写操作*/
void Inf_W25Q32_WriteEnable(void);/*** 禁止W25Q32闪存芯片的写操作*/
void Inf_W25Q32_WriteDisable(void);/*** 擦除W25Q32闪存芯片的指定扇区* @param block 块地址* @param sector 扇区地址*/
void Inf_W25Q32_SectorErase(uint8_t block,uint8_t sector);/*** 向W25Q32闪存芯片的指定页面写入数据* @param block 块地址* @param sector 扇区地址* @param page 页面地址* @param data 写入的数据缓冲区指针* @param len 写入的数据长度*/
void Inf_W25Q32_PageProgram(uint8_t block,uint8_t sector,uint8_t page,uint8_t data[],uint8_t len);/*** 从W25Q32闪存芯片的指定位置读取数据* @param block 块地址* @param sector 扇区地址* @param page 页面地址* @param buff 存储读取数据的缓冲区指针* @param len 读取的数据长度*/
void Inf_W25Q32_ReadData(uint8_t block,uint8_t sector,uint8_t page,uint8_t buff[],uint8_t len);
#endif //SPI_W25Q32_H
W25Q32.c
//
// Created by seven on 2024/9/2.
//#include "W25Q32.h"
void W25Q32_Init(void){MX_SPI1_Init();}
void w25q32_Stop(void){SPI_Stop();
}
void W25Q32_ReadId(uint8_t *sid,uint16_t *mid){// 1. 片选启动SPI_Start();// 2. 发送指令SPI_SwapByte(0x9f);// 3. 接收id// 3.1 首先接收制造商id*sid = SPI_SwapByte(0xff);// 3.2 接收设备id*mid = SPI_SwapByte(0xff) << 8;*mid |= SPI_SwapByte(0xff) << 0;// 4. 片选关闭SPI_Stop();
}// 等待忙状态
// 原理是调用05h指令 可以循环读取8位的状态寄存器 -> 第0位表示忙状态
// 当第0位变为0的时候表示它不忙
void Inf_W25Q32_WaitNotBusy(void){SPI_Start();SPI_SwapByte(0x05);while(SPI_SwapByte(0xff) & 0x01){}SPI_Stop();
}
// 打开写使能
void Inf_W25Q32_WriteEnable(void){SPI_Start();SPI_SwapByte(0x06);SPI_Stop();
}
// 关闭写使能
void Inf_W25Q32_WriteDisable(void){SPI_Start();SPI_SwapByte(0x04);SPI_Stop();
}
// 擦除方法
void Inf_W25Q32_SectorErase(uint8_t block,uint8_t sector){Inf_W25Q32_WaitNotBusy();Inf_W25Q32_WriteEnable();SPI_Start();SPI_SwapByte(0x20);uint32_t address = (block << 16) | (sector << 8);SPI_SwapByte(address >> 16);SPI_SwapByte(address >> 8);SPI_SwapByte(address >> 0);SPI_Stop();Inf_W25Q32_WriteDisable();
}
// 写入数据
void Inf_W25Q32_PageProgram(uint8_t block,uint8_t sector,uint8_t page,uint8_t data[],uint8_t len){Inf_W25Q32_WaitNotBusy();Inf_W25Q32_WriteEnable();SPI_Start();SPI_SwapByte(0x02);uint32_t address = (block << 16) | (sector << 8) | (page << 0);SPI_SwapByte(address >> 16);SPI_SwapByte(address >> 8);SPI_SwapByte(address >> 0);for(int i = 0; i < len; i++){SPI_SwapByte(data[i]);}SPI_Stop();Inf_W25Q32_WriteDisable();}
// 读数据 -> 不需要使能 但需要等待忙状态
void Inf_W25Q32_ReadData(uint8_t block,uint8_t sector,uint8_t page,uint8_t buff[],uint8_t len){Inf_W25Q32_WaitNotBusy();SPI_Start();SPI_SwapByte(0x03);uint32_t address = (block << 16) | (sector << 8) | (page << 0);SPI_SwapByte(address >> 16);SPI_SwapByte(address >> 8);SPI_SwapByte(address >> 0);for(int i = 0; i < len; i++){buff[i] = SPI_SwapByte(0xff);}SPI_Stop();
}
基于官方HAL库spi额外添加的函数
在spi.c
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
内添加下面代码
/*** @brief SPI通信启动函数** 该函数通过将片选(CS)信号置低来启动SPI通信。*/
void SPI_Start(void)
{// 将CS(片选)信号置低,启动SPI通信HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
}/*** @brief SPI通信停止函数** 该函数通过将片选(CS)信号置高来结束SPI通信。*/
void SPI_Stop(void)
{// 将CS(片选)信号置高,结束SPI通信HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
}/*** @brief SPI通信中字节交换函数** 该函数在SPI通信中交换一个字节,并返回接收到的字节。** @param byte 要发送和交换的字节* @return uint8_t 返回从SPI通信接收到的字节*/
uint8_t SPI_SwapByte(uint8_t byte)
{uint8_t rByte = 0;// 通过SPI通信发送字节并接收回应字节HAL_SPI_TransmitReceive(&hspi1, &byte, &rByte, 1, 1000);return rByte;
}
在spi.h的
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
内添加下面代码
// 初始化SPI通信
void SPI_Start(void);
// 停止SPI通信
void SPI_Stop(void);
// 数据位交换
// 将输入的8位数据进行位交换,例如0x01交换后变为0x80
uint8_t SPI_SwapByte(uint8_t byte);
这篇关于W25Q32驱动 基于HAL库的SPI的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!