RT-Thread SPI使用教程
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 SPI使用教程
RT-Thread SPI 使用教程 实验环境使用的是正点原子的潘多拉开发板。 SPI从机设备使用的是BMP280温湿度大气压传感器。 使用RT-Thread Studio搭建基础功能。 1. 创建工程 使用RT-Thread Studio IDE创建芯片级的工程。创建完成后,可以直接编译下载进行测试。 2.…...
shiro使用——整合spring
shiro使用——整合spring 1. 引入相关配置 <dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.9.1</version></dependency>2. 自定义Realm类 继承AuthorizingRealm 并重写相…...
2023-02-20 leetcode-AccountsMerge
摘要: 记录对leetcode-AccountsMerge的反思 要求: Given a list accounts, each element accounts[i] is a list of strings, where the first element accounts[i][0] is a name, and the rest of the elements are emails representing emails of the account. * Now, w…...
中国高速公路行业市场规模及未来发展趋势
中国高速公路行业市场规模及未来发展趋势编辑中国高速公路行业市场规模正在迅速增长。随着中国经济的快速发展和城市化的加速,对交通基础设施的需求也在不断增加。高速公路是最有效的交通工具,可以大大缩短交通时间,提高出行效率。因此&#…...
佳能iC MF645CX彩色激光多功能打印机报E302-0001故障码检修
故障现象: 一台佳能iC MF645CX彩色激光多功能一体机开机报E302-0001故障代码,如果设备未恢复,请联系经销商或客户支持中心。 维修分析: 佳能iC MF645CX彩色激光多功能一体机开机报E302-0001故障代码的...
加密越来越简单——用JavaScript实现数据加密和解密
加密越来越简单——用JavaScript实现数据加密和解密概念常用算法1. MD5加密算法2. SHA-1加密算法3. AES加密算法代码示例结论总结在当今互联网的世界中,安全性越来越受到关注,数据加密成为了必不可少的一环。Javascript作为前端开发的主要语言之一&#…...
线程池的使用场景
学习整理线程池的使用场景。...
图像分割算法
图像分割算法阈值分割固定阈值自适应阈值大津阈值(OTSU)最大熵阈值连通域分析区域生长分水岭阈值分割、连通域分析、区域生长、分水岭 阈值分割 固定阈值、自适应阈值(adaptiveThreshold)、大津阈值(OTSU)、最大熵阈值(KSW) 固定阈值 固定阈值的调用函数: //Input…...
《mysql技术内幕:innodb存储引擎》笔记
任何时候Why都比What重要;不要相信任何的“神话”,学会自己思考;不要墨守成规,大部分人都知道的事情可能是错误的;不要相信网上的传言,去测试,根据自己的实践做出决定;花时间充分地思考,敢于提出质疑。1.MYSQL被设计为一个单进程多…...
windows与linux系统ntp服务器配置
一. windows 打开windows终端(管理员),顺序输入以下指令 net stop w32time w32tm /unregister w32tm /register net start w32time w32tm /resync net stop w32time net start w32timewin r 输入regedit,打开注册表。 ①将HKEY_…...
html常用font-family设置字体样式
<table border"1" cellpadding"0" cellspacing"0" ><tr><td><h3 style"font-family: 黑体;">黑体:SimHei</h3></td><td><h3 style"font-family: 华文黑体;">华…...
数据库事务AICD以及隔离级别
目录一.事务的ACID二.隔离级别三.并发事务中的问题1.脏写2.脏读3.不可重复读4.幻读四.MVCC机制五.读锁与写锁六.大事务的影响七.事务优化一.事务的ACID 原子性(Atomicity):一个事务中的所有操作,要么全部成功,要么失败全部回滚,不…...
(4)VScode之ssh基础配置
VScode和SSH基础配置问题集合 Author:onceday date:2022年8月31日 本文记录linux的ssh和vscode开发环境搭建之路。 参考文档: 离线安装vscode Once Day CSDN博客关于x86、x86_64/x64、amd64和arm64/aarch64 Bogon 简书arm64和aarch64之间…...
springcloud-1环境搭建、service provider
搭建项目环境创建新项目,选择archetype-webapp,创建一个父项目,该父项目会去管理多个微服务模块(module)项目设置Settings->Editor->File Encoding:Global/Project Encoding 改为UTF-8Default encoding for properties files:默认属性文…...
光谱仪工作过程及重要参数定义
标题光谱仪工作过程CCD、PDA薄型背照式BT-CCD狭缝Slit暗电流Dark Current分辨率Resolution色散Dispersion光栅和闪耀波长Grating波长精度、重复性和准确度Precision带宽Band widthF数F/#光谱仪工作过程 CCD、PDA 电荷耦合器件(Charger Coupled Device,缩…...
W800|iot|HLK-W800-KIT-PRO|AliOS|阿里云| |官方demo|学习(1):板载AliOS系统快速上手
板载系统简介 HLK-W800-KIT-PRO 是海凌科电子面向开发者,采用了联盛德 w800 方案,带有一个RGB三色灯,集成了 CHT8305C 温湿度传感器的多功能开发板,用户可以在上面学习、研究嵌入式系统和物联网产品的开发,本套设备运行…...
字节终面,一道Linux题难住我了
以下是一道难道系数中高并且高频出现的linux面试题,题目具体要求如下: linux面试题: 某文件有多列数据,空格隔开,统计第n列单词,打印出现频率最高的5个单词。 解答这道面试题需要用到3个linux命令ÿ…...
三、NetworkX工具包实战2——可视化【CS224W】(Datawhale组队学习)
开源内容:https://github.com/TommyZihao/zihao_course/tree/main/CS224W 子豪兄B 站视频:https://space.bilibili.com/1900783/channel/collectiondetail?sid915098 斯坦福官方课程主页:https://web.stanford.edu/class/cs224w NetworkX…...
【MySQL】MySQL 架构
一、MySQL 架构 C/S 架构,即客户端/服务器架构。服务器程序直接和我们存储的数据打交道,多个客户端连接这个服务器程序。客户端发送请求,服务器响应请求。 MySQL 数据库实例 :即 MySQL 服务器的进程 (我们使用任务管理…...
Python日期时间模块
Python 提供了 日期和时间模块用来处理日期和时间,还可以用于格式化日期和时间等常见功能。 时间间隔是以秒为单位的浮点小数。每个时间戳都以自从 1970 年 1 月 1 日午夜(历元)经过了多长时间来表示。 一、time模块使用 Time 模块包含了大…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
