rtthread studio与正点原子apollo(11)--SPI设备之flash存储器


前言

本文介绍RT-Thread中SPI设备的使用方法,通过访问APOLLO板载FLASH芯片W25Q256演示SPI具体操作。


一、SPI简介

SPI(Serial Periperal Interface,串行外设接口)是一种高速全双工同步串行总线,采用主(Master)从(Slave)工作模式,通信双方最多采用四线连接,分别为MOSI(主出从入)、MISO(主如从出)、SCK(串行时钟)和CS(片选),总线上可以有一个主机和多个从机,SPI总线常应用于EEPROM、Flash、实时时钟(RTC)、数模转换器(ADC)。
在这里插入图片描述
主机控制CS为低电平选择要访问的从机,任何时刻,一个 SPI 主机上只有一个 CS 引脚处于有效状态,与该有效 CS 引脚连接的从机此时被选中,可以与主机通信。
主机同时为从机提供同步时钟SCK,用于确定通信双方的通信速率。
MOSI将主机数据发送给从机,而MISO是将从机数据发送给主机。
SPI总线的工作时序由CPOL(Clock Polarity,时钟极性)和 CPHA(Clock Phase,时钟相位)之间的相位关系决定。CPOL 表示时钟信号的初始电平的状态,CPOL 为 0 表示时钟信号初始状态为低电平,为 1 表示时钟信号的初始电平是高电平。CPHA 表示在哪个时钟沿采样数据,CPHA 为 0 表示在首个时钟变化沿采样数据,而 CPHA 为 1 则表示在第二个时钟变化沿采样数据。根据 CPOL 和 CPHA 的不同组合共有 4 种工作时序模式:①CPOL=0,CPHA=0、②CPOL=0,CPHA=1、③CPOL=1,CPHA=0、④CPOL=1,CPHA=1。
在这里插入图片描述

二、访问SPI设备

SPI设备的使用可以参考RT-Thread官方网站
SPI设备

1.配置SPI设备

在进行SPI通信前,需要先将与主机连接的SPI从机挂载到SPI总线上。

static int rt_hw_spi_flash_init(void)
{
    rt_hw_spi_device_attach("spi5", W25Q_SPI_DEVICE_NAME, GPIOF, GPIO_PIN_6);
    if (RT_NULL == rt_sfud_flash_probe("W25Q256", W25Q_SPI_DEVICE_NAME))
    {
       return -RT_ERROR;
     }
    return RT_EOK;
}

2.操作SPI设备

1.访问SPI设备
在使用 SPI 设备前需要根据 SPI 设备名称获取设备句柄,进而才可以操作 SPI 设备。

#define W25Q_SPI_DEVICE_NAME     "spi50"   /* SPI 设备名称 */
struct rt_spi_device *spi_dev_w25q;     /* SPI 设备句柄 */

/* 查找 spi 设备获取设备句柄 */
spi_dev_w25q = (struct rt_spi_device *)rt_device_find(W25Q_SPI_DEVICE_NAME);

2.自定义SPI传输数据
获取到 SPI 设备句柄就可以使用 SPI 设备管理接口访问 SPI 设备器件,进行数据收发。
代码如下(示例):

struct rt_spi_message msg1, msg2;
rt_uint8_t w25x_read_id = 0x90;         /* 命令 */
rt_uint8_t id[5] = {0};
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);

除此之外还有其他数据传输API函数,具体使用方法参考官方文档
在这里插入图片描述
3.获取总线
在多线程的情况下,同一个 SPI 总线可能会在不同的线程中使用,为了防止 SPI 总线正在传输的数据丢失,从设备在开始传输数据前需要先获取 SPI 总线的使用权,获取成功才能够使用总线传输数据,可使用如下函数获取 SPI 总线

rt_err_t rt_spi_take_bus(struct rt_spi_device *device);

4.选中片选
从设备获取总线的使用权后,需要设置自己对应的片选信号为有效,可使用如下函数选中片选

rt_err_t rt_spi_take(struct rt_spi_device *device)

5.释放片选
从设备数据传输完成后,需要释放片选,可使用如下函数释放片选

rt_err_t rt_spi_release(struct rt_spi_device *device)

6.释放总线
从设备不在使用 SPI 总线传输数据,必须尽快释放总线,这样其他从设备才能使用 SPI 总线传输数据,可使用如下函数释放总线

rt_err_t rt_spi_release_bus(struct rt_spi_device *device);

三、访问SPI设备举例

打开board.h文件,按提示配置SPI设备
在这里插入图片描述
1.环境设置中启动SPI功能
在这里插入图片描述
2.开启宏定义

#define BSP_USING_SPI5

3.在STMCUBEMX中配置spi功能,将生成代码

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)

复制到board.c文件后
4.代开文件stm32f7xx_hal_conf.h,开启宏定义
在这里插入图片描述
至此,SPI设备功能已经启动,接下来写代码实现具体功能即可,参考代码如下

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#define W25Q_SPI_DEVICE_NAME     "spi50"   /* SPI 设备名称 */
struct rt_spi_device *spi_w25q;

static int rt_hw_spi_flash_init(void)
{
    rt_hw_spi_device_attach("spi5", W25Q_SPI_DEVICE_NAME, GPIOF, GPIO_PIN_6);
    if (RT_NULL == rt_sfud_flash_probe("W25Q256", W25Q_SPI_DEVICE_NAME))
    {
       return -RT_ERROR;
     }
    return RT_EOK;
}

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

rt_uint8_t id[5]={0};
int spi5_w25q_init(void)
{
    rt_uint8_t w25q_read_id = 0x90;

    spi_w25q=(struct rt_spi_device *)rt_device_find(W25Q_SPI_DEVICE_NAME); /* 查找 spi 设备获取设备句柄 */
    /* 配置SPI,如果与默认值相同,此处可不做配置*/
    struct rt_spi_configuration cfg;
    cfg.data_width = 8;
    cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_3 | RT_SPI_MSB;
    cfg.max_hz = 20 * 1000 *1000;                           /* 20M */
    rt_spi_configure(spi_w25q, &cfg);
    rt_thread_mdelay(1000);
    struct rt_spi_message msg1, msg2;

            msg1.send_buf   = &w25q_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_w25q, &msg1);
    return RT_EOK;
}


总结

此处介绍了SPI设备的配置方法及步骤,实现了简单的W25Q芯片ID的读取,关于W25Q具体的操作需要编写代码驱动,会在后续文章中介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值