@[TOC](RT-Thread Studio学习(十二)W25Q128(SPI)的读写)
本文将基于STM32F407ZGT芯片介绍如何在RT-Thread Studio开发环境下访问W25Q128模块。
详细步骤参考文档《RT-Thread Studio学习(一)使用外部时钟系统》。
在STM32CubeMX中仅仅启用了USART1串口,配置了RCC晶体振和SYS下载方式。
查看原理图
在RT-Thread Studio的RT-Thread settings
中,开启SPI
和SFUD
。
在board.h
文件中,启用SPI1,
/*#define BSP_USING_SPI1*/
#define BSP_USING_SPI1
/*#define BSP_USING_SPI2*/
/*#define BSP_USING_SPI3*/
在stm32f0xx_hal_conf.h
中,打开 HAL 库对 SPI 的支持,
/* #define HAL_MMC_MODULE_ENABLED */
#define HAL_SPI_MODULE_ENABLED
/* #define HAL_TIM_MODULE_ENABLED */
双击工程的CubeMX Settings
,配置接口SPI1,如下图:
重新生成代码后,将工程下源文件cubemx/src/spi.c
的HAL_SPI_MspInit
函数复制到board.h
,
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* SPI1 clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI1 GPIO Configuration
PB3 ------> SPI1_SCK
PB4 ------> SPI1_MISO
PB5 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
修改main.c
的代码为:
main.c
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-07-19 RT-Thread first version
*/
#include
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include
#include "board.h"
#include
#include "spi_flash.h"
#include "./sfud/inc/sfud.h"
#define W25Q_SPI_DEVICE_NAME "spi10"
static void spi_w25q_sample(int argc, char *argv[])
{
struct rt_spi_device *spi_dev_w25q;
char name[RT_NAME_MAX];
rt_uint8_t w25x_read_id = 0x90;
rt_uint8_t id[5] = {0};
if (argc == 2)
{
rt_strncpy(name, argv[1], RT_NAME_MAX);
}
else
{
rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX);
}
/* 查找 spi 设备获取设备句柄 */
spi_dev_w25q = (struct rt_spi_device *)rt_device_find(name);
if (!spi_dev_w25q)
{
rt_kprintf("spi sample run failed! can't find %s device!\n", name);
}
else
{
/* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */
rt_spi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);
rt_kprintf("use rt_spi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]);
/* 方式2:使用 rt_spi_transfer_message()发送命令读取ID */
struct rt_spi_message msg1, msg2;
msg1.send_buf = &w25x_read_id;
msg1.recv_buf = RT_NULL;
msg1.length = 1;
msg1.cs_take = 1;
msg1.cs_release = 0;
msg1.next = &msg2;
msg2.send_buf = RT_NULL;
msg2.recv_buf = id;
msg2.length = 5;
msg2.cs_take = 0;
msg2.cs_release = 1;
msg2.next = RT_NULL;
rt_spi_transfer_message(spi_dev_w25q, &msg1);
rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", id[3], id[4]);
}
}
static int rt_hw_spi_flash_init(void)
{
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
rt_hw_spi_device_attach("spi1", "spi10", GPIOB, GPIO_PIN_14);
// rt_hw_spi_device_attach("spi1", "spi10", GPIOD, GPIO_PIN_6);
if (RT_NULL == rt_sfud_flash_probe("W25Q128", "spi10"))
{
return -RT_ERROR;
};
return RT_EOK;
}
static void spi_w25q_sf_sample(int argc, char *argv[])
{
uint8_t *read_data; // 读取到的数据
uint8_t *write_data; // 将要写入的数据
sfud_flash *sfud_dev = NULL;
sfud_err ret;
sfud_dev = rt_sfud_flash_find("spi10"); // 获取 sfud_dev
// 或者 sfud_dev = rt_sfud_flash_find_by_dev_name("W25Q128");
write_data = rt_malloc(32);
rt_memset(write_data, '1', 32);
ret = sfud_erase_write(sfud_dev, 0, 32, write_data); // 将数据 32 字节的 write_data 从 0 开始写入 flash
if(ret == SFUD_SUCCESS)
{
rt_kprintf("sfud write data at 0 is:%s\n", write_data);
}
else
{
rt_kprintf("sfud write data failed\n");
}
read_data = rt_malloc(32);
ret = sfud_read(sfud_dev, 0, 32, read_data); // 读取从 0 开始的 32 字节,存入 read_data
if(ret == SFUD_SUCCESS)
{
rt_kprintf("sfud read data at 0 is:%s\n", read_data);
}
else
{
rt_kprintf("sfud read data failed\n");
}
}
int main(void)
{
LOG_D("Hello RT-Thread!");
while (1)
{
rt_thread_mdelay(1000);
}
return RT_EOK;
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample);
MSH_CMD_EXPORT(spi_w25q_sf_sample, spi w25q sf sample);
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
后接入了另一块QSPI模块,使用PD6作为片选,测试结果如下:
对于这个问题,有网友认为是SFUD的问题。这个需要后面在测试。