@[TOC](RT-Thread Studio学习(十二)W25Q128(SPI)的读写)
一、简介
本文将基于STM32F407ZGT芯片介绍如何在RT-Thread Studio开发环境下访问W25Q128模块。
- 操作系统:WIN10 x64
- 硬件电路:正点原子探索者开发板,主芯片为STM32F407ZGT6
- 软件开发环境:STM32CubeMX v6.6.1,RT-Thread Studio v2.2.4
二、新建RT-Thread项目并使用外部时钟
详细步骤参考文档《RT-Thread Studio学习(一)使用外部时钟系统》。 在STM32CubeMX中仅仅启用了USART1串口,配置了RCC晶体振和SYS下载方式。
三、设置W25Q128的驱动框架
查看原理图
在RT-Thread Studio的RT-Thread settings 中,开启SPI 和SFUD 。
在board.h 文件中,启用SPI1,
#define BSP_USING_SPI1
在stm32f0xx_hal_conf.h 中,打开 HAL 库对 SPI 的支持,
#define HAL_SPI_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)
{
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
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);
}
}
修改main.c 的代码为:
main.c
#include <rtthread.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "board.h"
#include <rtdevice.h>
#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_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
{
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]);
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);
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");
write_data = rt_malloc(32);
rt_memset(write_data, '1', 32);
ret = sfud_erase_write(sfud_dev, 0, 32, write_data);
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);
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_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的问题。这个需要后面在测试。
参考资料
- SPI设备
- RT-Thread SPI 设备使用 - 简书
- RT-thread SPI SFUD读写W25Q128
|