[原创] RT-Thread设备框架学习之SPI设备

ID.LODA   2020-4-26 17:55 楼主

RT-Thread学习记录

1.Studio新建工程

2.控制台使用简述

3.PIN设备框架学习

4.UART设备框架学习

5.I2C设备框架学习

 

SPI设备

    RT-Thread的SPI驱动目前只支持硬件SPI/QSPI模式。

    首先在Components设置项下勾选SPI驱动框架,这里几个可选项分别为QSPI模式、SPI SD卡、SPI Flash、SPI以太网、SPI WiFi、这边我板载了QSPI的FLASH和SPI SD卡,所以两个都勾选了,如果设备不是以上选项可以直接跳过,如下图
image-20200424185308413.png

 

    然后在Samples设置项下勾选spi device例程, 保存,如下图可以看到spi的例程已添加入工程
image-20200424185421636.png

 

    打开例程文件,可以看到该例程的功能是通过SPI方式夺取Flash的设备ID,因为我板卡用的是qspi的Flash,所以例程不能用,需要自己重新实现。

image-20200426094606629.png

    首先我们先在board.h打开QSPI设备驱动的支持

image-20200426153048011.png

 

    然后在board.c文件或者其他任意源文件,添加对QSPI的引脚初始化,这边我先是在CubeMX下设置生成了代码之后拷贝过来的,具体如下图所示:

image-20200426153323091.png

    模仿之前添加进来的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

image-20200426153643551.png

    SPI的测试可以参考官网提供的示例程序,我这边没有相应的外设做测试,SD卡这个测试留到之后的文件系统组件一起测试。

    以上就是SPI驱动框架的使用说明。


此内容由EEWORLD论坛网友ID.LODA原创,如需转载或用于商业用途需征得作者同意并注明出处

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复