Rtthread学习笔记(九)RT-Thread Studio的开启SPI1总线,外部flash(W25Q64)做从机设备

23 篇文章 78 订阅

一、步骤

1.打开RT-Thread Setting中软件模拟I2C

在这里插入图片描述
在这里插入图片描述

2.开启board.h/stm32F1xx_hal_config.h中关于SPI的宏定义

在这里插入图片描述
在这里插入图片描述

3.用stm32cube初始化spi相关内容(或直接复制RT文件夹下对应的bsp中代码)

复制cube中stm32f1xx_hal_msp.c中的void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)到board.c中,HAL库会自动初始化该函数,因为本来存在虚函数。

此部分代码也可从rtthread文件夹中对应的bsp目录中,直接打开stm32f1xx_hal_msp.c,进行复制对应部分的代码进行修改。
在这里插入图片描述

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(hspi->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    /**SPI3 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }

}

在这里插入图片描述
像rt_hw_spi_init(void)这种初始化SPI的函数,在drv_spi.c的最后面已经为我们自动写好了,会根据初始化的配置进行编译,所以不需要进行改动。
在这里插入图片描述

编译下载,到此处已经将SPI总线设备注册到系统中
在这里插入图片描述

4.SPI从设备驱动编写

SPI的总线设备已经注册完毕,接下来需要进行SPI从设备驱动编写,这里直接使用板载的SPI Flash W25Q64进行测试,新建app_spi.c。

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


static int rt_hw_spi_flash_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
    rt_hw_spi_device_attach("spi1", "spi10", GPIOC, GPIO_PIN_0);// spi10 表示挂载在 spi3 总线上的 0 号设备,PC0是片选,这一步就可以将从设备挂在到总线中。

    if (RT_NULL == rt_sfud_flash_probe("W25Q64", "spi10"))  //注册块设备,这一步可以将外部flash抽象为系统的块设备
    {
        return -RT_ERROR;
    };

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

编译下载
在这里插入图片描述

5.在main.c中main()函数中初始化SPI例程

总线设备、从设备都已经注册完毕,接下来就是在从设备上测试spi通讯配置、读写,实现最终的使用。更多的使用接口函数参照官方SPI部分。RT官方SPI参考资料

//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!\n", 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\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]);

    }

}

在这里插入图片描述

另外配置SPI通讯相关参数的部分可以替换成下面的部分,就是直接使用HAL库初始化SPI通讯。
在这里插入图片描述

SPI_HandleTypeDef hspi1;
static void MX_SPI1_Init(void)
{

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi1.Init.NSS = SPI_NSS_SOFT;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值