RT-Thread SP使用教程
RT-Thread SPI 使用教程
实验环境使用的是正点原子的潘多拉开发板。
SPI从机设备使用的是BMP280温湿度大气压传感器。
使用RT-Thread Studio搭建基础功能。
1. 创建工程
使用RT-Thread Studio IDE创建芯片级的工程。创建完成后,可以直接编译下载进行测试。
2. 添加驱动
2.1 工程配置
工程创建完成后,在RT-Thread Studio的组建和服务层/Drivers/SPI中开启SPI驱动。

然后对SPI进行配置:

配置完成后,Ctrl+S保存配置会自动更新工程代码。
完成配置后,还需要在board.h中打开需要使用的那一路SPI的宏。

再在board.c中添加STM32的SPI初始化代码,可以通过配置CubeMX生成代码:
SPI_HandleTypeDef hspi2;/* SPI2 init function */
void MX_SPI2_Init(void)
{hspi2.Instance = SPI2;hspi2.Init.Mode = SPI_MODE_MASTER;hspi2.Init.Direction = SPI_DIRECTION_2LINES;hspi2.Init.DataSize = SPI_DATASIZE_8BIT;hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;hspi2.Init.NSS = SPI_NSS_SOFT;hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi2.Init.TIMode = SPI_TIMODE_DISABLE;hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi2.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi2) != HAL_OK){Error_Handler();}}void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(spiHandle->Instance==SPI2){/* USER CODE BEGIN SPI2_MspInit 0 *//* USER CODE END SPI2_MspInit 0 *//* SPI2 clock enable */__HAL_RCC_SPI2_CLK_ENABLE();__HAL_RCC_GPIOB_CLK_ENABLE();/**SPI2 GPIO ConfigurationPB13 ------> SPI2_SCKPB14 ------> SPI2_MISOPB15 ------> SPI2_MOSI*/GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);/* USER CODE BEGIN SPI2_MspInit 1 *//* USER CODE END SPI2_MspInit 1 */}
}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{if(spiHandle->Instance==SPI2){/* USER CODE BEGIN SPI2_MspDeInit 0 *//* USER CODE END SPI2_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_SPI2_CLK_DISABLE();/**SPI2 GPIO ConfigurationPB13 ------> SPI2_SCKPB14 ------> SPI2_MISOPB15 ------> SPI2_MOSI*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);/* USER CODE BEGIN SPI2_MspDeInit 1 *//* USER CODE END SPI2_MspDeInit 1 */}
}
完成后,SPI的驱动就算是添加完成了。
2.2 代码分析
2.2.1 SPI驱动使用流程
- SPI总线设备通过
rt_spi_bus_register()接口注册到SPI设备驱动框架中。 - SPI设备驱动框架通过
rt_device_register()接口将SPI总线设备注册到I/O设备管理器中。 - SPI从机驱动程序通过
rt_spi_bus_attach_device()接口将从设备挂载到SPI总线设备上,并注册到SPI设备驱动框架中。 - SPI从机驱动通过SPI设备接口访问SPI从机设备硬件。
2.2.2 代码
在drivers group中的drv_spi.c中:
int rt_hw_spi_init(void)
{stm32_get_dma_info();return rt_hw_spi_bus_init();
}
INIT_BOARD_EXPORT(rt_hw_spi_init);
通过这里的INIT_BOARD_EXPORT()申明,添加初始化代码到.rti_fn.1 段:
#define INIT_EXPORT(fn, level) \RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn." level) = fn
#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")
然后在board.c中的rt_hw_board_init() -> rt_components_board_init() 中集中去初始化设备驱动。
void rt_components_board_init(void)
{volatile const init_fn_t *fn_ptr;for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++){(*fn_ptr)();}
#endif
}
rt_hw_spi_bus_init() 又调用了rt_spi_bus_register() ,rt_spi_bus_register() 调用rt_spi_bus_device_init()去调用rt_device_register() 完成注册。
static rt_err_t spi_configure(struct rt_spi_device *device,struct rt_spi_configuration *configuration)
{RT_ASSERT(device != RT_NULL);RT_ASSERT(configuration != RT_NULL);struct stm32_spi *spi_drv = rt_container_of(device->bus, struct stm32_spi, spi_bus);spi_drv->cfg = configuration;return stm32_spi_init(spi_drv, configuration);
}static const struct rt_spi_ops stm_spi_ops =
{.configure = spi_configure,.xfer = spixfer,
};
HAL_SPI_Init()初始化在stm32_spi_init()中被完成,注册到了ops中。在attach后,直接调用rt_spi_configure() 来完成初始化。
注意,和i2c使用不同,SPI必须要通过attach绑定,才能使用SPI设备接口。
3. 使用SPI
完成bmp280的读取Device ID的代码编写,添加到文件中bmp280.c中,再将文件添加到工程中:
#include <rtthread.h>
#include <rtdevice.h>
#include <drv_spi.h>#define BME280_SPI_DEVICE_NAME "spi20"
#define BEM280_REG_ID 0XD0rt_bool_t initialnized = RT_FALSE;static void spi_bme280_demo(void)
{uint8_t data = BEM280_REG_ID | (1 << 7);rt_err_t err;struct rt_spi_device * spi_bme280;if (!initialnized) {initialnized = RT_TRUE;err = rt_hw_spi_device_attach("spi2", BME280_SPI_DEVICE_NAME, GPIOB, GPIO_PIN_12);if (err) {rt_kprintf("attach device error\r\n");return ;}}spi_bme280 = (struct rt_spi_device *)rt_device_find(BME280_SPI_DEVICE_NAME);if (spi_bme280 == RT_NULL) {rt_kprintf("find %s error\r\n", BME280_SPI_DEVICE_NAME);return ;}struct rt_spi_configuration cfg = {.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB,.data_width = 8,.max_hz = 1 * 1000 * 1000};err = rt_spi_configure(spi_bme280, &cfg);if (err != RT_NULL) {rt_kprintf("spi configurate error\r\n");return ;}uint8_t send_buf[5] = {data, 0xff};uint8_t recv_buf[5];if (rt_spi_transfer(spi_bme280, send_buf, recv_buf, 2) == 0) {rt_kprintf("spi transfer error\r\n");}rt_kprintf("bme280 id: 0x%02x\r\n", recv_buf[1]);
}MSH_CMD_EXPORT(spi_bme280_demo, read bme280 id);
这里我使用的CS Pin是PB12,注意attach接口参数。
4. 测试
BMP280的Device ID是0x58, BME280是0x60。
编译上述工程并烧录,输入命令进行验证:


相关文章:
RT-Thread SP使用教程
RT-Thread SPI 使用教程 实验环境使用的是正点原子的潘多拉开发板。 SPI从机设备使用的是BMP280温湿度大气压传感器。 使用RT-Thread Studio搭建基础功能。 1. 创建工程 使用RT-Thread Studio IDE创建芯片级的工程。创建完成后,可以直接编译下载进行测试。 2.…...
LeetCode 2363. 合并相似的物品
给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质: items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 ,weighti 表示第 i 件物品的 重量 。 items 中每件物品的价值都是 唯一的 。 请你…...
numpy 中常用的数据保存、fmt多个参数
在经常性读取大量的数值文件时(比如深度学习训练数据),可以考虑现将数据存储为Numpy格式,然后直接使用Numpy去读取,速度相比为转化前快很多 一、保存为二进制文件(.npy/.npz) (1)numpy.save(file, arr, allow_pickleTrue, fix_importsTrue) file:文件名…...
从0到1一步一步玩转openEuler--19 openEuler 管理服务-特性说明
文章目录19 管理服务-特性说明19.1 更快的启动速度19.2 提供按需启动能力19.3 采用cgroup特性跟踪和管理进程的生命周期19.4 启动挂载点和自动挂载的管理19.5 实现事务性依赖关系管理19.6 与SysV初始化脚本兼容19.7 能够对系统进行快照和恢复19 管理服务-特性说明 19.1 更快的…...
23美赛E题:光污染(ICM)完整思路Python代码
问题E(综合评价与仿真题):光污染(ICM) 背景 光污染用于描述过度或不良使用人造光。我们称之为光污染的一些现象包括光侵入、过度照明和光杂波。在大城市,太阳落山后,这些现象最容易在天空中看到;然而,它们也可能发生在更偏远的地区。 光污染会改变我们对夜空的看法,…...
快速排序的描述以及两种实现方案
一、快速排序描述 每一轮排序选择一个基准点(pivot)进行分区 1.1. 让小于基准点的元素的进入一个分区,大于基准点的元素的进入另一个分区 1.2. 当分区完成时,基准点元素的位置就是其最终位置在子分区内重复以上过程,直…...
算力引领 数“聚”韶关——第二届中国韶关大数据创新创业大赛圆满收官
为进一步促进数字经济领域创新创业发展,推动国家数据中心集群建设,构建大数据领域资源专业平台,促进大湾区大数据科技成果和创新创业人才转化落地,为韶关大数据领域创新型产业集群的打造、大数据科技成果和创新创业人才的转化落地…...
MySQL 记录锁+间隙锁可以防止删除操作而导致的幻读吗?
文章目录什么是幻读?实验验证加锁分析总结什么是幻读? 首先来看看 MySQL 文档是怎么定义幻读(Phantom Read)的: The so-called phantom problem occurs within a transaction when the same query produces different sets of r…...
【分库分表】企业级分库分表实战方案与详解(MySQL专栏启动)
📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于…...
(考研湖科大教书匠计算机网络)第五章传输层-第五节:TCP拥塞控制
获取pdf:密码7281专栏目录首页:【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一:拥塞控制概述二:拥塞控制四大算法(1)慢开始和拥塞避免A:慢启动(slow start)…...
13.使用自动创建线程池的风险,要自己创建为好
自动创建线程池就是直接调用 Executors去new默认的那几个线程池,但是会出现一定的风险,线程池里面会用到队列,也会跟线程池自身有关,所以要从队列和线程池两个方面去解析。 1.了解线程池的队列 线程池的内部结构主要由四部分组成…...
【项目设计】—— 负载均衡式在线OJ平台
目录 一、项目的相关背景 二、所用技术栈和开发环境 三、项目的宏观结构 四、compile_server模块设计 1. 编译服务(compiler模块) 2. 运行服务(runner模块) 3. 编译并运行服务(compile_run模块) 4…...
Docker学习笔记
1:docker安装步骤Linux 2:docker安装步骤Windows 3:docker官方文档 4:docker官方远程仓库 docker常用命令 1: docker images----查看docker中安装的镜像 2: docker pull nginx------在docker中安装Nginx镜…...
【爬虫理论实战】详解常见头部反爬技巧与验证方式 | 有 Python 代码实现
以下是常见头部反爬技巧与验证方式的大纲: User-Agent 字段的伪装方式,Referer 字段的伪装方式,Cookie 字段的伪装方式。 文章目录1. ⛳️ 头部反爬技巧1.1. User-Agent 字段&User-Agent 的作用1.2. 常见 User-Agent 的特征1.3. User-Age…...
基于SpringBoot+Vue的鲜花商场管理系统
【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、…...
华为OD机试 - 静态扫描最优成本(JS)
静态扫描最优成本 题目 静态扫描快速识别源代码的缺陷,静态扫描的结果以扫描报告作为输出: 文件扫描的成本和文件大小相关,如果文件大小为 N ,则扫描成本为 N 个金币扫描报告的缓存成本和文件大小无关,每缓存一个报告需要 M 个金币扫描报告缓存后,后继再碰到该文件则不…...
多层感知机
多层感知机理论部分 本文系统的讲解多层感知机的pytorch复现,以及详细的代码解释。 部分文字和代码来自《动手学深度学习》!! 目录多层感知机理论部分隐藏层多层感知机数学逻辑激活函数1. ReLU函数2. sigmoid函数3. tanh函数多层感知机的从零…...
python在windows调用svn-pysvn
作为EBS开发人员,开发工具用的多,部署代码类型多,管理程序麻烦,操作繁琐,一直是我最讨厌的事情。部署一次程序要使用好几个工具,改来改去,上传下载,实在难受。 扣了一下python&#…...
office365 word 另存为 pdf 的注意事项和典型设置
0. 操作环境介绍 Office 版本:Office 365 版本 不同版本的操作可能有所不同 1. 基本操作 – 另存为 pdf 【文件】 --> 【另存为】,选择适当的文件路径、文件名保存类型选择【PDF】点击【保存】 1. 导出的pdf包含目录标签 word中,可使用…...
Spring IoC容器之常见常用注解以及注解编程模型简介
一、全文概览 本篇文章主要学习记录Spring中的核心注解,罗列常见常用的注解以及Spring中的注解编程模型介绍 二、核心注解 1、Spring模式注解 常用注解场景描述Spring起始支持版本Component通用组件模式注解,是所有组件类型注解的元注解Spring 2.5Repo…...
小白也能懂的Qwen3-VL微调教程:图文识别模型定制化入门
小白也能懂的Qwen3-VL微调教程:图文识别模型定制化入门 1. 为什么需要微调Qwen3-VL模型? Qwen3-VL是阿里云推出的新一代视觉语言模型,它能同时理解图片和文字内容。这个模型预训练时已经学会了很多通用技能,比如识别常见物体、理…...
如何在macOS上免费获得专业级音质:eqMac终极音频均衡器指南
如何在macOS上免费获得专业级音质:eqMac终极音频均衡器指南 【免费下载链接】eqMac macOS System-wide Audio Equalizer & Volume Mixer 🎧 项目地址: https://gitcode.com/gh_mirrors/eq/eqMac 想让你的MacBook或iMac音质瞬间提升到专业水准…...
全平台数据采集工具:BarrageGrab直播弹幕实时抓取解决方案
全平台数据采集工具:BarrageGrab直播弹幕实时抓取解决方案 【免费下载链接】BarrageGrab 抖音快手bilibili直播弹幕wss直连,非系统代理方式,无需多开浏览器窗口 项目地址: https://gitcode.com/gh_mirrors/ba/BarrageGrab 在数字直播时…...
Android与SpringBoot的轻量级数据桥梁——OkHttp3实战解析
1. OkHttp3与SpringBoot的黄金组合 第一次用OkHttp3对接SpringBoot后端时,我盯着满屏的404错误差点崩溃。后来才发现,原来是因为手机和电脑不在同一个WiFi下。这种看似低级的错误,恰恰是新手最容易踩的坑。OkHttp3作为Android端最流行的网络请…...
ThinkPHP6+UniApp实战:手把手教你用宝塔面板部署Niushop V5.5.0多门店商城(含全插件配置)
ThinkPHP6UniApp实战:宝塔面板部署Niushop V5.5.0多门店商城全流程解析 在数字化转型浪潮中,电商系统的快速部署能力已成为技术团队的核心竞争力之一。本文将带您深入实战,从零开始完成Niushop V5.5.0多门店商城系统的完整部署。不同于基础教…...
基于RIME-CNN-LSSVM回归模型的优化与预测应用——以MATLAB环境为例
RIME-CNN-LSSVM回归 基于霜冰优化算法优化卷积神经网络(CNN)结合最小二乘向量机(LSSVM)的数据回归预测(可以更换为分类/单、多变量时序预测/回归,前私我),Matlab代码,可直接运行,适合小白新手 程序已经调试好,无需更改…...
OpenClaw本地知识图谱:GLM-4.7-Flash构建个人关系网络
OpenClaw本地知识图谱:GLM-4.7-Flash构建个人关系网络 1. 为什么需要个人知识图谱 去年整理项目资料时,我发现自己收藏的200多篇技术文章和50多个开源项目早已形成"信息孤岛"。当需要跨领域参考时,只能靠模糊记忆在文件夹里大海捞…...
HY-Motion 1.0应用案例:为AR试衣间生成‘转身→抬手→比划’交互动作流
HY-Motion 1.0应用案例:为AR试衣间生成转身→抬手→比划交互动作流 1. 项目背景与需求 AR试衣间正在改变传统购物体验,但如何让虚拟服装在用户身上自然流动,一直是个技术难题。传统方案要么动作生硬不连贯,要么需要复杂的动作捕…...
3分钟上手!AI驱动的代码学习助手完全指南
3分钟上手!AI驱动的代码学习助手完全指南 【免费下载链接】Tutorial-Codebase-Knowledge Turns Codebase into Easy Tutorial with AI 项目地址: https://gitcode.com/gh_mirrors/tu/Tutorial-Codebase-Knowledge Tutorial-Codebase-Knowledge是一款AI驱动的…...
Rufus高效使用实战指南:精通ext2/ext3/ext4文件系统格式化
Rufus高效使用实战指南:精通ext2/ext3/ext4文件系统格式化 【免费下载链接】rufus The Reliable USB Formatting Utility 项目地址: https://gitcode.com/GitHub_Trending/ru/rufus 在Linux系统管理和开发工作中,USB设备的格式化与启动盘制作是一…...
