嵌入式技术论坛
直播中

罗星

8年用户 1505经验值
擅长:模拟技术
私信 关注
[经验]

使用基于rt thread studio的SPI三大步骤分享

使用SPI的三大步骤
一、创建和注册SPI总线设备
创建SPI总线
创建 SPI 总线设备 主要实现 SPI 总线设备 struct rt_spi_bus 的数据结构定义,并实现操作方法 struct rt_spi_ops ,也就是实例化SPI总线设备
注册SPI总线
SPI 总线设备被注册后,使用如下接口注册到 SPI 设备驱动框架中:
rt_err_t  rt_spi_bus_register(struct rt_spi_bus *bus,
                               const  char  *name,
                const  struct   rt_spi_ops  *ops);
具体操作如下:
1、在软件包中心 —>组件中,勾选SPI总线设备,如下图所示:

2、打开 board.h 文件,并按照 文件中 的 SPI CONFIG BEGIN 至 SPI CONFIG END 的内容进行相关配置即可。

二、创建和挂载从设备
创建 SPI 从设备主要是实现 SPI 从设备 struct rt_spi_device 的数据结构体定义,然后使用 rt_spi_bus_attach_device() 接口将从设备挂载在总线设备上。(此方法源自 官方撰写的一本书)
本示例使用另外一种方法,使用这个接口: rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_TypeDef* cs_gpiox, uint16_t cs_gpio_pin);
具体代码如下所示:
#include
#include
#include
#include
static  int  rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /*spi10表示挂载在 SPI1 总线上的设备,PB14是片选,这一步就可以将设备挂载到总线上 */
    rt_hw_spi_device_attach("spi1", "spi10", GPIOB, GPIO_PIN_14);
    /* 注册设备,这一步可以将外部flash抽象为系统的块设备 */
    if (RT_NULL==rt_sfud_flash_probe("w25q128","spi10"))
    {
        return  -RT_ERROR;
    }
    return  RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);
三、访问SPI从设备
1、查找设备 rt_device_find()
2、配置 SPI 模式、频率参数等,配置参数的结构体 struct rt_spi_configuration 原型如下:
struct  rt_spi_configuration
{
rt_uint8_t        mode;   /* SPI模式 */
rt_uint8_t        data_width;  /* 数据宽度 */
rt_uint16_t        reserved;     /* 保留 */
rt_uint8_t        max_hz;      /* 最大频率 */
};
3、发送接收数据
该部分具体代码如下:
//SPI1配置例程
void SPI1_INIT(void)
{
    struct rt_spi_device *spi_dev_w25q;
    char name[RT_NAME_MAX]="spi10";
    rt_uint8_t w25x_read_id = 0x90;//命令码
    rt_uint8_t id[5] = {0};
    /* 查找 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!
", name);
    }
    else
    {
        /*配置SPI通讯相关参数  */
        struct rt_spi_configuration cfg;
        cfg.data_width = 8;                                     /* 数据宽度 */
        cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;  /* 主从模式、时钟极性和时钟相位、数据传输顺序是MSB位在前还是LSB位在前 */
        cfg.max_hz = 20 * 1000 *1000;                           /* 20M */
        rt_spi_configure(spi_dev_w25q, &cfg);
        /* 方式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
", 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
", id[3], id[4]);
    }
}

原作者:The Subtly

更多回帖

发帖
×
20
完善资料,
赚取积分