02_STM32软件+硬件SPI读写W25Q64(HAL库)

目录

1、SPI简介

2、SPI时序单元

2.1 模式0(应用最多)

2.2 模式1

2.3 模式2

2.4 模式3

3、SPI移位示意图

4、简单软件SPI代码(HAL库)

5、简单硬件SPI读写W25Q64(HAL库)

6、例程下载

1、SPI简介

2、SPI时序单元

2.1 模式0(应用最多)

2.2 模式1

2.3 模式2

模式2与模式0类似,区别在于CPOL=1,SCK初始为高电平,其他完全一致

2.4 模式3

模式3与模式1类似,区别在于CPOL=1,SCK初始为高电平,其他完全一致

3、SPI移位示意图

4、简单软件SPI代码(HAL库)

①软件SPI

#include "stm32f1xx_hal.h"                  // Device header
#include "MySPI.h"
/*引脚配置层*/
#define SPI_SS_PORT GPIOB
#define SPI_SS_PIN GPIO_PIN_9

#define SPI_SCK_PORT GPIOA
#define SPI_SCK_PIN GPIO_PIN_5

#define SPI_MOSI_PORT GPIOA
#define SPI_MOSI_PIN GPIO_PIN_7

#define SPI_MISO_PORT GPIOA
#define SPI_MISO_PIN GPIO_PIN_6

/**
  * 函    数:SPI写SS引脚电平
  * 参    数:BitValue 协议层传入的当前需要写入SS的电平,范围0~1
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SS为低电平,当BitValue为1时,需要置SS为高电平
  */
void MySPI_W_SS(uint8_t BitValue)
{
	HAL_GPIO_WritePin(SPI_SS_PORT, GPIO_PIN_9, (GPIO_PinState)BitValue);		//根据BitValue,设置SS引脚的电平
}

/**
  * 函    数:SPI写SCK引脚电平
  * 参    数:BitValue 协议层传入的当前需要写入SCK的电平,范围0~1
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SCK为低电平,当BitValue为1时,需要置SCK为高电平
  */
void MySPI_W_SCK(uint8_t BitValue)
{
	HAL_GPIO_WritePin(SPI_SCK_PORT, SPI_SCK_PIN, (GPIO_PinState)BitValue);		//根据BitValue,设置SCK引脚的电平
}

/**
  * 函    数:SPI写MOSI引脚电平
  * 参    数:BitValue 协议层传入的当前需要写入MOSI的电平,范围0~0xFF
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置MOSI为低电平,当BitValue非0时,需要置MOSI为高电平
  */
void MySPI_W_MOSI(uint8_t BitValue)
{
	HAL_GPIO_WritePin(SPI_MOSI_PORT, GPIO_PIN_7, (GPIO_PinState)BitValue);		//根据BitValue,设置MOSI引脚的电平,BitValue要实现非0即1的特性
}

/**
  * 函    数:I2C读MISO引脚电平
  * 参    数:无
  * 返 回 值:协议层需要得到的当前MISO的电平,范围0~1
  * 注意事项:此函数需要用户实现内容,当前MISO为低电平时,返回0,当前MISO为高电平时,返回1
### 使用 STM32 HAL 通过 SPI 接口读写 W25Q64 #### 初始化 SPI 外设配置 为了使能 SPI 功能并初始化外设,需先设置 SPI 的工作模式、数据方向以及波特率等参数。具体操作可以通过 `MX_SPI1_Init` 函数完成,在该函数内部调用了 HAL 提供的相关 API 来设定这些属性[^1]。 ```c static void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = DISABLE; hspi1.Init.CRCCalculation = DISABLE; hspi1.Init.CRCPolynomial = 7; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } } ``` #### 定义辅助宏定义和全局变量 对于简化编程逻辑来说,预先声明一些用于控制片选信号(Chip Select)、延时处理以及其他常用指令的宏是非常有帮助的。此外还需要创建一个指向 SPI 句柄类型的指针以便后续访问 SPI 设备。 ```c #define W25QXX_CS_LOW() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET) #define W25QXX_CS_HIGH() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET) extern SPI_HandleTypeDef hspi1; uint8_t buffer[256]; ``` #### 实现等待 Flash 写入完毕的功能 当向 Flash 执行擦除或写入命令之后,必须确保当前的操作已经完全结束才能继续下一步骤。下面这段代码展示了如何利用状态寄存器来判断是否还有正在进行中的写周期: ```c void BSP_W25Qxx_Wait_for_Write_End(void){ uint8_t state = 0; uint8_t cmd = W25X_ReadStatusReg; // 假定已正确定义此常量 W25QXX_CS_LOW(); // 片选有效 HAL_SPI_Transmit(&hspi1, &cmd, 1, W25Qxx_TIMEOUT_VALUE); do { HAL_SPI_Receive(&hspi1, &state, 1, W25Qxx_TIMEOUT_VALUE); } while ((state & BUSY_FLAG) == SET); // 这里假设BUSY_FLAG已经被适当定义 W25QXX_CS_HIGH(); // 结束传输 } ``` #### 编写读取和写入扇区的具体方法 针对不同的应用场景可能需要设计专门的数据交换流程,比如按页读取或者整块擦除后再批量写入新内容。这里给出两个简单的例子说明怎样发送特定命令序列给 W25Q64 并接收响应数据流。 ##### 写入单字节到指定地址 ```c void Write_Single_Byte(uint32_t addr,uint8_t data){ uint8_t wr_cmd[]={ W25X_WriteEnable, W25X_PageProgram, (addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF,data}; W25QXX_CS_LOW(); HAL_SPI_Transmit(&hspi1,&wr_cmd,sizeof(wr_cmd),W25Qxx_TIMEOUT_VALUE); W25QXX_CS_HIGH(); BSP_W25Qxx_Wait_for_Write_End(); } ``` ##### 从指定位置开始连续读取多个字节 ```c void Read_Multi_Bytes(uint32_t addr,uint8_t* pBuf,uint16_t num){ uint8_t rd_cmd[]={W25X_FastReadCmd, (addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF,DUMMY_BYTE}; W25QXX_CS_LOW(); HAL_SPI_Transmit(&hspi1,rd_cmd,sizeof(rd_cmd)-1,W25Qxx_TIMEOUT_VALUE); HAL_SPI_Receive(&hspi1,pBuf,num,W25Qxx_TIMEOUT_VALUE); W25QXX_CS_HIGH(); } ``` 以上就是基于 HAL 实现 STM32 对 W25Q64 存储芯片进行基本读写操作的方法介绍[^2][^3]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值