10.RTT-SPI设备

本期进行SPI学习,通过SPI读取开发板板载的W25Q128的ID号。

1.SPI简介

SPI(Serial Peripheral Interface,串行外设接口)是一种高速、全双工、同步通信总线,常用于短距离通讯,主要应用于 EEPROM、FLASH、实时时钟、AD 转换器、还有数字信号处理器和数字信号解码器之间。SPI 一般使用 4 根线通信,如下图所示:

  • MOSI –主机输出 / 从机输入数据线(SPI Bus Master Output/Slave Input)。
  • MISO –主机输入 / 从机输出数据线(SPI Bus Master Input/Slave Output)。
  • SCLK –串行时钟线(Serial Clock),主设备输出时钟信号至从设备。
  • CS –从设备选择线 (Chip select)。也叫 SS、CSB、CSN、EN 等,主设备输出片选信号至从设备。

SPI 以主从方式工作,通常有一个主设备和一个或多个从设备。通信由主设备发起,主设备通过 CS 选择要通信的从设备,然后通过 SCLK 给从设备提供时钟信号,数据通过 MOSI 输出给从设备,同时通过 MISO 接收从设备发送的数据。

如下图所示芯片有 2 个 SPI 控制器,SPI 控制器对应 SPI 主设备,每个 SPI 控制器可以连接多个 SPI 从设备。挂载在同一个 SPI 控制器上的从设备共享 3 个信号引脚:SCK、MISO、MOSI,但每个从设备的 CS 引脚是独立的。

主设备通过控制 CS 引脚对从设备进行片选,一般为低电平有效。任何时刻,一个 SPI 主设备上只有一个 CS 引脚处于有效状态,与该有效 CS 引脚连接的从设备此时可以与主设备通信。

2.工程配置及其引脚配置

 

这里只需要开启三根SPI专用线即可,CS片选线通过挂载函数进行设置。

3.代码

/*
 * 程序清单:这是一个 SPI 设备使用例程
 * 例程导出了 spi_w25q_sample 命令到控制终端
 * 命令调用格式:spi_w25q_sample spi10
 * 命令解释:命令第二个参数是要使用的SPI设备名称,为空则使用默认的SPI设备
 * 程序功能:通过SPI设备读取 w25q 的 ID 数据
*/

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#define W25Q_SPI_DEVICE_NAME     "spi20"


static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    rt_hw_spi_device_attach("spi2", "spi20", GPIOB, GPIO_PIN_12);

    if (RT_NULL == rt_sfud_flash_probe("W25Q128", "spi20"))
    {
        return -RT_ERROR;
    };

    return RT_EOK;
}
/* 导出到自动初始化 */
INIT_COMPONENT_EXPORT(rt_hw_spi_flash_init);



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]);

    }
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(spi_w25q_sample, spi w25q sample);

4.代码分析

4.1rt_hw_spi_flash_init();

SPI 驱动会注册 SPI 总线,SPI 设备需要挂载到已经注册好的 SPI 总线上。因此这是用于挂载w25q128flash(下文都用flash来代替)的初始化阶段代码。

rt_hw_spi_device_attach("spi2", "spi20", GPIOB, GPIO_PIN_12);

上面的函数作用是挂载flash到spi2,设备为spi2的0号设备,CS片选引脚为PB12。
rt_sfud_flash_probe("W25Q128", "spi20");

作用是将flash型号和设备名字联系起来,即w25q128就是设备spi20。

最后将整段代码导出到组件自动初始化中(即在使用flash前就进行初始化)。

4.2spi_w25q_sample();

本段代码首先就是寻找设备spi20,找到后利用两种方式对flash写命令从而获取ID号。

/* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */

rt_spi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);

/* 方式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);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式路上的流浪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值