使用VSCode+CubeMx开发STM32,这里介绍SPI接口读写Flash模块W25Q64;

1.建立工程

1.1 创建项目文件

从已有的仓库中创建一个工程:

1
git clone https://github.com/makerinchina-iot/vscode_stm32cubemx_hello.git w25q64_flash

使用VSCode打开工程后,需要更改如下名字:

  • 文件夹根目录下CMakeLists.txt 文件中修改工程名字为w25q64_flash:
1
set(CMAKE_PROJECT_NAME w25q64_flash)
  • stm32cubemx配置文件更改为 w25q64_flash.ioc ,并更改以下文件名:
1
2
3
4
...
ProjectManager.ProjectFileName=w25q64_flash.ioc
ProjectManager.ProjectName=w25q64_flash
...
1.2 引脚配置

使用STM32CubeMx打开ioc配置文件,然后配置对应的SPI引脚;

  • SPI1配置好时钟和时钟极性等模式;
  • 这里SPI速度配置需要注意:如果选择比较高速的时钟波特率,那么对应GPIO也需要配置为高速,否则SPI会工作不正常:

2. 编写代码

2.1 基本的Flash操作

Flash操作的命令根据规格书定义通过SPI传输,主要为 HAL_SPI_Transmit 和 HAL_SPI_TransmitReceive 两个API函数;

  • 读取Flash ID信息:

读取ID信息,需要发送 JECED ID命令,程序如下:

1
2
3
4
5
6
7
8
9
/* 1. 读 ID */
log_info("Read Flash ID...");
uint8_t tx[4] = {0x9F, 0xFF, 0xFF, 0xFF};
uint8_t rx[4] = {0};
CS_LOW();
spi_txrx(tx, rx, 4);
CS_HIGH();
uint32_t id = (rx[1] << 16) | (rx[2] << 8) | rx[3]; // 应=0xEF4017
log_debug("Flash ID: %08X", id);

SPI时序如下:

  • 写入和读取数据

写入数据前,需要擦除在写入数据,写入数据和擦除操作都需要发送write enable命令,然后等待写入状态完成再进行下一步操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void w25_wait_busy(void)
{
uint8_t tx[2] = {0x05, 0xFF};
uint8_t rx[2];
do
{
CS_LOW();
spi_txrx(tx, rx, 2);
CS_HIGH();
} while (rx[1] & 0x01);
}

void w25_write_enable(void)
{
uint8_t tx = CMD_WREN;
CS_LOW();
HAL_SPI_Transmit(&hspi1, &tx, 1, 1000);
CS_HIGH();
}
  • 擦除然后写入和读取测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/* 2. 擦除首扇区 */
log_info("Erase Flash...");
w25_write_enable();
uint8_t erase[4] = {CMD_SE, 0x00, 0x00, 0x00};
CS_LOW();
HAL_SPI_Transmit(&hspi1, erase, 4, 1000);
CS_HIGH();
w25_wait_busy();

/* 3. 写 4 字节 */
log_info("Write Flash...");
w25_write_enable();
uint8_t write[8] = {CMD_PP, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD};
CS_LOW();
HAL_SPI_Transmit(&hspi1, write, 8, 1000);
CS_HIGH();
w25_wait_busy();

/* 4. 读回 4 字节 */
log_info("Read Flash...");
uint8_t read[8] = {CMD_READ, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
CS_LOW();
HAL_SPI_TransmitReceive(&hspi1, read, read, 8, 1000);
CS_HIGH();
log_info("Read Data: %02X %02X %02X %02X", read[4], read[5], read[6], read[7]);

3.编译并烧录代码

3.1 编译和烧录
  • 点击生成按键即可编译工程;

  • 在VSCode中执行task:openocd-flash烧录;

3.2 硬件连接与结果
  • 按照如下方式连接硬件:
STM32 W25Q64 Flash
3.3V VCC
GND GND
PA4 - SPI1_NSS CS
PA5 - SPI1_SCK CLK
PA6 - SPI1_MISO DO
PA7 - SPI1_MOSI DI
  • 运行程序后结果如下:

可以看到写入到FLash的数据和读取的一致;