stm32 spi读写w25q64
时间: 2025-05-28 21:22:09 浏览: 75
### STM32通过SPI接口对W25Q64进行读写的代码示例
为了实现STM32通过SPI接口对W25Q64存储器的操作,通常会采用软件模拟SPI的方式或者硬件SPI外设。以下是基于软件SPI方式的一个简单示例代码。
#### 宏定义部分
首先,在`W25Q64_Ins.h`头文件中定义W25Q64的相关指令码[^1]:
```c
#ifndef W25Q64_INS_H
#define W25Q64_INS_H
// W25Q64命令字定义
#define W25Q64_READ_STATUS_REG1 0x05 // 读取状态寄存器1
#define W25Q64_WRITE_ENABLE 0x06 // 写使能
#define W25Q64_SECTOR_ERASE 0xD8 // 扇区擦除 (4KB)
#define W25Q64_PAGE_PROGRAM 0x02 // 页面编程
#define W25Q64_FAST_READ 0x0B // 高速读取数据
#endif /* W25Q64_INS_H */
```
#### 初始化函数
初始化GPIO和SPI引脚配置如下所示[^2]:
```c
void W25Q64_SPI_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE(); // 启用GPIOA时钟
// SCK 引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_5; // PA5作为SCK
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// MOSI 引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_7; // PA7作为MOSI
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// MISO 引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_6; // PA6作为MISO
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 输入模式
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// SS/CS 引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_4; // PA4作为片选信号
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
```
#### 软件SPI传输函数
编写用于发送和接收单个字节的辅助函数:
```c
void W25Q64_SpiSendByte(uint8_t byte) {
uint8_t i, temp;
for(i=0;i<8;i++) {
if(byte & 0x80){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); // 发送高电平
}else{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET); // 发送低电平
}
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换SCK
HAL_DelayMicroseconds(1); // 延迟微秒级时间
byte <<= 1; // 左移准备下一个bit
}
while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)); // 等待完成
}
uint8_t W25Q64_SpiReceiveByte() {
uint8_t i, data = 0;
for(i=0;i<8;i++) {
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换SCK
data <<= 1; // 数据左移一位
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)) { // 如果接收到的是高电平
data |= 0x01; // 设置最低位为1
}
}
return data;
}
```
#### 实现读写操作
下面展示如何利用这些基础功能来执行具体的读写操作。
##### 写入数据到指定地址
```c
void W25Q64_PageProgram(uint32_t addr, uint8_t *data, uint16_t size) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS拉低
W25Q64_SpiSendByte(W25Q64_PAGE_PROGRAM); // 发送页面编程命令
W25Q64_SpiSendByte((addr >> 16) & 0xFF); // 发送高位地址
W25Q64_SpiSendByte((addr >> 8) & 0xFF); // 中间地址
W25Q64_SpiSendByte(addr & 0xFF); // 地址低位
for(int i=0;i<size;i++) {
W25Q64_SpiSendByte(data[i]); // 循环发送数据
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);// CS拉高结束本次通讯
}
```
##### 从指定地址读取数据
```c
void W25Q64_FastReadData(uint32_t addr, uint8_t *buffer, uint16_t length) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 片选激活
W25Q64_SpiSendByte(W25Q64_FAST_READ); // 发送快速读取命令
W25Q64_SpiSendByte((addr >> 16) & 0xFF); // 发送起始地址最高字节
W25Q64_SpiSendByte((addr >> 8) & 0xFF); // 发送中间地址字节
W25Q64_SpiSendByte(addr & 0xFF); // 发送最低有效地址字节
W25Q64_SpiSendByte(0); // 哑元(dummy)
for(int i=0;i<length;i++) {
buffer[i] = W25Q64_SpiReceiveByte(); // 接收数据并保存至缓冲区
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 取消片选
}
```
以上即为完整的STM32通过软件SPI驱动W25Q64芯片的基础框架以及具体的数据交互逻辑[^1][^2].
阅读全文
相关推荐



















