你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【基于STM32的 rt-thread SPI使用】

[复制链接]
andeyqi 发布时间:2019-10-20 17:26
因为项目上需要使用SPI和SOC通信,所以了解下RTthread的这部分功能。
官方的说明资料:

如何添加SPI外设驱动选项

SPI驱动介绍

rt-thread 的SPI驱动框架的代码主要是\rt-thread\components\drivers\spi文件夹下的spi_core.c和spi_dev.c文件:
spi_core.c 和 spi_dev.c是驱动框架的核心代码,spi_core.c 主要实现的是SPI总线的相关的处理,spi_dev.c主要是针对挂载在总线上的设备相关的处理。spi_core.c文件中相关关键函数的说明如下:
rt_spi_bus_register(struct rt_spi_bus *bus,const char *name,const struct rt_spi_ops *ops)//像系统注册SPI总线类设备及操作函数
spi_bus_register.png


rt_spi_bus_attach_device:往总线上挂载设备

spi_device_attach.png


rt_err_t rt_spi_configure(struct rt_spi_device  *device, struct rt_spi_configuration *cfg)
设置SPI总线设备参数模式。
spi_config.png



rt_spi_send_then_send(),rt_spi_send_then_recv(),rt_spi_transfer(),rt_spi_transfer_message()这几个接口都是用来发送,接收,发送/接收数据的接口具体的实现原理基本相同,rtthread将总线上的传输数据抽象成message的方式就行传送和linux相似,消息发送接收控制的结构如下:
  1. struct rt_spi_message
  2. {
  3.     const void *send_buf;           /* 发送缓冲区指针 */
  4.     void *recv_buf;                 /* 接收缓冲区指针 */
  5.     rt_size_t length;               /* 发送 / 接收 数据字节数 */
  6.     struct rt_spi_message *next;    /* 指向继续发送的下一条消息的指针 */
  7.     unsigned cs_take    : 1;        /* 片选选中 */
  8.     unsigned cs_release : 1;        /* 释放片选 */
  9. };
复制代码

说完了上面的spi驱动框架层的代码,接下来要说的就是需要BSP来实现的东西了,rtt基于stm32的支持已经做的很好了,从\rt-thread\bsp\stm32\libraries\HAL_Drivers路径可知最新的rtt代码中已经包含了SPI相关的底层BSP驱动代码,上面提到的需要BSP给驱动框架注册的函数已经在对应的spi驱动中实现了,如下代码会在board初始化阶段,自动调用其中会对SPI总线进行初始化。
  1. int rt_hw_spi_init(void)
  2. {
  3.     stm32_get_dma_info();
  4.     return rt_hw_spi_bus_init();
  5. }
  6. INIT_BOARD_EXPORT(rt_hw_spi_init);
复制代码

rt_hw_spi_init.png
通过以上的分析可以看出来,rtt对SPI的操作已经支持的很到位了,我们只需要看懂代码,根据现有的代码添加设备即可。我们只需要往总线上挂接各设备,传输前配置下参数即可使用,如下是我本地的测试代码,没有驱动具体的芯片,只是使用总线测试的发送数据。

  1. #include <board.h>
  2. #include <drv_spi.h>
  3. #include <rtdevice.h>
  4. #include <rthw.h>
  5. #include <finsh.h>

  6. static int rt_hw_spi_communication_init(void)
  7. {
  8.     rt_hw_spi_device_attach("spi1", "spi10", GPIOB, GPIO_PIN_6);

  9.     return RT_EOK;
  10. }
  11. INIT_PREV_EXPORT(rt_hw_spi_communication_init);


  12. static void spisend(int argc, char**argv)
  13. {
  14.     static rt_uint8_t isconfigflag = 0,sendsize;
  15.     static struct rt_spi_device *spi_dev_com;     /* SPI 设备句柄 */
  16.     struct rt_spi_configuration cfg;
  17.     rt_err_t ret;
  18.     rt_uint8_t sendbuff[100];
  19.    
  20.     cfg.data_width = 8;
  21.     cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
  22.     cfg.max_hz = 20*1000*1000;                           /* 20M */

  23.     if (argc < 2)
  24.     {
  25.         rt_kprintf("Not input send data will send 0X55 0XAA'\n");
  26.         sendbuff[0] = 0x55;
  27.         sendbuff[1] = 0xaa;
  28.         sendbuff[2] = 0x55;
  29.         sendbuff[3] = 0xaa;
  30.         sendbuff[4] = 0x55;
  31.         sendbuff[5] = 0xaa;
  32.         sendbuff[6] = 0x55;
  33.         sendbuff[7] = 0xaa;
  34.         sendbuff[8] = 0x55;
  35.         sendbuff[9] = 0xaa;
  36.         sendbuff[10] = 0x55;
  37.         sendbuff[11] = 0xaa;
  38.     }
  39.     else
  40.     {
  41.         rt_kprintf("Start send data\n");
  42.     }
  43.     if(!isconfigflag)
  44.     {
  45.         /* 查找 spi 设备获取设备句柄 */
  46.         spi_dev_com = (struct rt_spi_device *)rt_device_find("spi10");
  47.         if(!spi_dev_com)
  48.         {
  49.             rt_kprintf("Not find spi10 device\n");
  50.         }
  51.         ret = rt_spi_configure(spi_dev_com, &cfg);
  52.         if(ret != RT_EOK)
  53.         {
  54.             rt_kprintf("Config spi10 failed\n");
  55.         }
  56.     }
  57.     sendsize = rt_spi_transfer(spi_dev_com,(void *)sendbuff,NULL,12);
  58.     rt_kprintf("SPI BUS send data len is %d\n",sendsize);
  59. }

  60. MSH_CMD_EXPORT(spisend, spisend sample: spisend <data>);
复制代码

代码编译后,会发现系统里会出现spi1 bus总线设备,spi10设备,通过spi10往总线上发送数据,个人基本不用作什么就可以把SPI设备跑起来,这里感谢下官方的支持,大大减少了开发者的开发时间。本地使用了F446的开发板,示波器看了下发送的数据(CLK和MOSI),和期待的完全一致。
f446.jpg



rtt_spi.jpg




收藏 2 评论4 发布时间:2019-10-20 17:26

举报

4个回答
3111272 回答时间:2019-10-24 13:27:54
不是SPI1 SPI10两个设备,通过finsh应该可以看到  SPI1 是BUS SPI10才是device
andeyqi 回答时间:2019-10-24 14:11:06
3111272 发表于 2019-10-24 13:27
不是SPI1 SPI10两个设备,通过finsh应该可以看到  SPI1 是BUS SPI10才是device

指摘的对,描述的有些问题,是两个不同类型的设备,总线类型的设备我理解的也是个设备只是设备的类型为总BUS。
weiyuliang 回答时间:2020-9-1 22:05:21
请教一下,需要读取指定地址数据怎么操作
andeyqi 回答时间:2020-9-2 15:48:28
weiyuliang 发表于 2020-9-1 22:05
请教一下,需要读取指定地址数据怎么操作

SPI 是个双工的通信接口,rt_spi_transfer 接口发送数据的同时也会接收数据,按照手册发送指令数据会在接收数据的buff带回来

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似分享

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版