RT-Thread的SPI驱动目前只支持硬件SPI/QSPI模式。
首先在Components设置项下勾选SPI驱动框架,这里几个可选项分别为QSPI模式、SPI SD卡、SPI Flash、SPI以太网、SPI WiFi、这边我板载了QSPI的FLASH和SPI SD卡,所以两个都勾选了,如果设备不是以上选项可以直接跳过,如下图
然后在Samples设置项下勾选spi device例程, 保存,如下图可以看到spi的例程已添加入工程
打开例程文件,可以看到该例程的功能是通过SPI方式夺取Flash的设备ID,因为我板卡用的是qspi的Flash,所以例程不能用,需要自己重新实现。
首先我们先在board.h打开QSPI设备驱动的支持
然后在board.c文件或者其他任意源文件,添加对QSPI的引脚初始化,这边我先是在CubeMX下设置生成了代码之后拷贝过来的,具体如下图所示:
模仿之前添加进来的SPI例子简单的写一个测试例程
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_qspi.h"
#define W25Q_SPI_DEVICE_NAME "qspi10"
char w25qxx_read_status_register2(struct rt_qspi_device *device)
{
/* 0x35 read status register2 */
char instruction = 0x35, status;
rt_qspi_send_then_recv(device, &instruction, 1, &status, 1);
return status;
}
void w25qxx_write_enable(struct rt_qspi_device *device)
{
/* 0x06 write enable */
char instruction = 0x06;
rt_qspi_send(device, &instruction, 1);
}
void w25qxx_enter_qspi_mode(struct rt_qspi_device *device)
{
char status = 0;
/* 0x38 enter qspi mode */
char instruction = 0x38;
char write_status2_buf[2] = {0};
/* 0x31 write status register2 */
write_status2_buf[0] = 0x31;
status = w25qxx_read_status_register2(device);
if (!(status & 0x02))
{
status |= 1 << 1;
w25qxx_write_enable(device);
write_status2_buf[1] = status;
rt_qspi_send(device, &write_status2_buf, 2);
rt_qspi_send(device, &instruction, 1);
rt_kprintf("flash already enter qspi mode\n");
rt_thread_mdelay(10);
}
}
//static void usr_spi_hw_config(struct rt_spi_device* device)
//{
// struct rt_spi_configuration cfg;
//
// cfg.data_width = 8;
// cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
// cfg.max_hz = 50 * 1000 *1000; /* 50M */
//
// rt_spi_configure(device, &cfg);
//}
static void usr_qspi_hw_config(struct rt_qspi_device* device)
{
struct rt_qspi_configuration cfg;
cfg.parent.data_width = 8;
cfg.parent.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
cfg.parent.max_hz = 50 * 1000 *1000; /* 20M */
cfg.medium_size = 0x1000000;
cfg.ddr_mode = 0;
cfg.qspi_dl_width = 4;
rt_qspi_configure(device, &cfg);
}
static void qspi_w25q_sample(int argc, char *argv[])
{
struct rt_qspi_device *spi_dev_w25q;
char name[RT_NAME_MAX];
rt_uint8_t w25x_read_id = 0x90;
rt_uint8_t id[5] = {0};
stm32_qspi_bus_attach_device("qspi1", "qspi10", RT_NULL, 4, w25qxx_enter_qspi_mode, RT_NULL);
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_qspi_device *)rt_device_find(name);
if (!spi_dev_w25q)
{
rt_kprintf("spi sample run failed! can't find %s device!\n", name);
}
else
{
usr_qspi_hw_config(spi_dev_w25q);
/* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */
rt_qspi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);
rt_kprintf("use rt_qspi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]);
/* 方式2:使用 rt_spi_transfer_message()发送命令读取ID */
// struct rt_qspi_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_qspi_transfer_message(spi_dev_w25q, &msg1);
// rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", id[3], id[4]);
}
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(qspi_w25q_sample, qspi w25q sample);
保存,编译,运行,可以看到已经能读取到外部FLASH的设备ID
SPI的测试可以参考官网提供的示例程序,我这边没有相应的外设做测试,SD卡这个测试留到之后的文件系统组件一起测试。
以上就是SPI驱动框架的使用说明。
此内容由EEWORLD论坛网友ID.LODA原创,如需转载或用于商业用途需征得作者同意并注明出处