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);

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值