新闻详情

新闻详情

首页 / 资讯中心 / 详情

RTThread学习记录13——关于要使用一个外设,RTThread与cubemx到底要怎么配合?

发布时间:2026/10/2 13:57:02来源:尧图网络
RTThread学习记录13——关于要使用一个外设,RTThread与cubemx到底要怎么配合?
一、遇到的问题我学习RTThread到IO设备模型时先是学习了怎么使用UART和PIN设备再学习了ADC和PWM这种外包型外设就遇到一个疑惑为什么突然到初始化ADC时就要使用到cubemx生成代码了为什么生成代码之后要放到board.c?为什么UART和PIN设备就不需要呢还有我最近也在搞RTThread相关的项目就遇到一个问题就是我按照我的理解我用到了pwm我需要线在RTThread里打开pwm然后在board.h里面#define要用到的pwm及其通道然后使用cubemx生成pwm的引脚和时钟硬件初始化代码再把这些代码粘贴到board.c里面去但是我就遇到了一个问题就是编译的时候报错提示pwm的引脚和时钟硬件初始化代码重复定义了这和我之前遇到的情况完全不一样之前学习到pwm时也是类似的操作这次却出问题为什么呢。后面我用DeepSeekv4.1Flash让它带我看懂底层逻辑我才搞懂。二、为什么 UART 和 PIN 不用 CubeMX,而 ADC 和 PWM 要用首先我们要明白大部分的外设要使用分成底层驱动方向和软件驱动方向底层驱动就类似于配置某个外设的时钟和引脚偏向硬件和底层的驱动/初始化而软件驱动方向就类似于设置这个参数的初始值、配置相关的调用这个外设的函数等等偏向代码层面不太涉及直接控制硬件寄存器。所以UART和PIN外设不需要cubemx配置是因为在RTThread中UART和PIN外设是直接被完全配置的而ADC和PWM外设的底层驱动对硬件引脚和时钟的初始化也就是HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数RTThread是没有配置的RTThread只配置了软件驱动cubemx负责底层驱动。为什么要怎么做三、为什么官方教程需要复制那2个函数其本意是什么前面我们知道RTThread要用一个外设需要两个方向的驱动但是在硬件引脚和时钟方面的初始化RTThread有2种方式。第一种就是非常简单直接的比如你要初始化定时器3的PWM通道是4那就找到初始化定时器3的PWM通道为4的时钟及其硬件引脚的代码也就是下面的代码把它粘贴到board.c里面这样就能让RTThread自己初始化硬件引脚和时钟了。void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm) { if(htim_pwm-InstanceTIM3) { /* USER CODE BEGIN TIM3_MspInit 0 */ /* USER CODE END TIM3_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_TIM3_CLK_ENABLE(); /* USER CODE BEGIN TIM3_MspInit 1 */ /* USER CODE END TIM3_MspInit 1 */ } } void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim) { GPIO_InitTypeDef GPIO_InitStruct {0}; if(htim-InstanceTIM3) { /* USER CODE BEGIN TIM3_MspPostInit 0 */ /* USER CODE END TIM3_MspPostInit 0 */ __HAL_RCC_GPIOB_CLK_ENABLE(); /**TIM3 GPIO Configuration PB1 ------ TIM3_CH4 */ GPIO_InitStruct.Pin GPIO_PIN_1; GPIO_InitStruct.Mode GPIO_MODE_AF_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, GPIO_InitStruct); /* USER CODE BEGIN TIM3_MspPostInit 1 */ /* USER CODE END TIM3_MspPostInit 1 */ } }其实这种方式也就是和board.h里面的指示意思一样就是需要你自己找到初始化这个外设的底层驱动函数这样RTThread就能自己脱离cubemx使用外设了。缺点就是这个初始化底层的代码需要自己找要么ai要么查资料。但是最方便的方式其实就是使用cubemx生成某个外设的全套初始化代码包括初始化这个外设的时钟、这个外设的硬件引脚这个外设的初始值设置这个外设其他的管理函数等等.....但是RTThread其实只需要初始化这个外设的时钟、初始化这个外设的硬件引脚的代码其他的初始化RTThread自己能搞定所以就需要RTThread排除掉cubemx生成的无用的东西不让无用的代码参与编译然后把初始化这个外设的时钟、初始化这个外设的硬件引脚的代码复制粘贴到board.c里面这样就能正常使用一个外设了这才是board.h里那4个步骤的本意四、cubemx到底有什么用为什么RTThread需要用到cubemxcubemx对于RTThread目前我总结出有2个作用。1.RTThread独立不依赖cubemx首先cubemx能帮助RTThread生成外设的底层初始化的代码也就是HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数省得RTThread又去找。就像上面举的例子就是cubemx生成代码RTThread取自己需要的就行不依赖cubemx。2.RTThread配合cubemx依赖于cubemx其次就是直接由cubemx接管所以的硬件初始化简单来说就是不管什么外设UART、PWM、PIN、ADC等等全部在cubemx里面配置好参数通道模式等等直接生成代码由cubemx接管外设的初始化。RTThread只需要在RTThread-setting里面打开要用到外设就行此时RTThread就是深度依赖于cubemx了。五、为什么之前能成功现在不行关键在于RTThread屏蔽的代码有哪些和cubemx生成代码放哪里的问题。在以前使用cubemx开发时我们会经常要勾选Generate peripheral initialization as a pair of .c/.h files per peripheral目的是为了把每个外设的初始化文件xxx.c/xxx.h分开放不要全部放到stm32f1xx_hal_msp.c文件里能够方便我们管理。在RTThreadRTThread恰好屏蔽的代码文件就包括每个外设自己的的初始化文件xxx.c/xxx.h而不会屏蔽stm32f1xx_hal_msp.c这个文件因为里面还包含的是整个板子HAL库及底层硬件的初始化代码RTThread不能屏蔽同时在cubemx眼里你不勾选Generate peripheral initialization as a pair of .c/.h files per peripheral意思就是要把所有外设的初始化代码包含了HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数及该外设的初始值、模式、通道初始化放到stm32f1xx_hal_msp.c这个文件里这样因为RTThread没有屏蔽stm32f1xx_hal_msp.c这个文件就会调用里面对该外设的底层驱动初始化的代码也就是HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数这也是第四个问题里RTThread依赖cubemx的实现原理就是cubemx在生成代码时不勾选然后把外设所有的初始化代码放一起让RTThread自己调用。那么RTThread不依赖cubemx自己初始化外设的原理就和上面相反了就是勾选Generate peripheral initialization as a pair of .c/.h files per peripheral让外设的初始化代码分别存放这样我们需要用到哪个外设就直接去对于外设的初始化代码把里面的HAL_xxx_MspPostInit()和HAL_xxx_MspInit()函数复制粘贴出来放到board.c里面就行了。cubemx在这单纯只是一个代码生成器没有其他作用了。所以总的来说为什么我之前的项目能成功但是现在却不行了成功的原因就是我之前的项目勾选了RTThread就自动屏蔽掉cubemx生成的代码了然后我就按照board.h里面指示的复制HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数到board.c里面完全符合流程和原理就没出现问题。失败的原因有2个我一开始遇到的问题是说HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数重复定义了是因为我在cubemx里面没有勾选然后我又把HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数复制到board.c里面导致RTThread在编译时发现HAL_xxx_MspPostInit()和HAL_xxx_MspInit()这2个函数定义了两次就报了这个错。第二个问题就是六、总结与拓展总的来说这次有加深了我对于IO设备从应用上的理解DeepSeek确实也是一个很好的自学工具让我很快理解了教程里一带而过但是深有其意的细节之处它还给我拓展了很多的知识。拓展部分关于弱定义函数RT-Thread 里像 ADC、PWM这类外设,执行和他们有关的库函数时会去找一个固定名字的配套初始化函数来开时钟、配引脚。一般cubemx生成的代码在RTThread里都会被加载成弱定义函数比如_weak int main()函数就是典型例子cubemx也会生成main函数但是会加上_weak前缀表示是弱定义这样就只会执行RTThread里面的main()函数了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

大模型预训练数据质量过滤实战:基于MindSpore的流水线设计与调参 2026/10/2 14:37:36

大模型预训练数据质量过滤实战:基于MindSpore的流水线设计与调参

1. 为什么数据质量过滤是大模型预训练的第一道生死线做过大模型预训练的人都有一个共识:模型效果的上限,在数据准备阶段就已经被决定了。你后面用多少张卡、跑多少天、调多少超参,都只是在逼近这个上限而已。而数据质量过滤,就是决…

阅读更多 →
Spring Boot端口冲突排查全链路指南:从netstat到application.yml 2026/10/2 14:37:35

Spring Boot端口冲突排查全链路指南:从netstat到application.yml

1. 这个报错不是程序问题,而是系统资源冲突的明确信号“Web server failed to start. Port 8080 was already in use.”——这行红色错误日志,几乎每个用过Spring Boot、Node.js或任何本地Web开发框架的人都见过。它不像空指针异常那样指向某一行代码逻辑…

阅读更多 →
PDF页面尺寸不一致与福昕右键菜单缺失排查修复 2026/10/2 14:37:29

PDF页面尺寸不一致与福昕右键菜单缺失排查修复

上周帮同事收拾一份108页的投标文件,前面96页是规规矩矩的A4,最后硬塞进来几张A3施工图。在屏幕上看挺正常,一送进打印店就出事了:A4那部分被缩成了巴掌大,A3那几张又被裁掉了图框边。同一份PDF文件内部页面大小不一致…

阅读更多 →
Hive复杂查询报错排查指南:数据倾斜、窗口函数与UDF避坑手册 2026/10/2 14:37:29

Hive复杂查询报错排查指南:数据倾斜、窗口函数与UDF避坑手册

开头做数据分析这些年,和Hive打交道最多的一句话就是:复杂查询又报错了。报错信息五花八门,有的是执行到一半直接FAILED: SemanticException,有的是跑了一个小时突然Container killed by the ApplicationMaster,还有的…

阅读更多 →
解决 CMake 交叉编译 arm-none-eabi 不在 PATH 的报错 2026/10/2 14:37:29

解决 CMake 交叉编译 arm-none-eabi 不在 PATH 的报错

上周帮同事看一个 STM32 的工程,他从仓库里 clone 下来,直接 cmake -B build ,屏幕上甩出一行红字: The CMAKE_CXX_COMPILER arm-none-eabi is not a full path and was not found in the PATH. 他第一反应是“我明明装了工具…

阅读更多 →
flutter_auto_localizations鸿蒙适配实录:ARB多语言代码生成与构建集成全攻略 2026/10/2 14:37:29

flutter_auto_localizations鸿蒙适配实录:ARB多语言代码生成与构建集成全攻略

1. 项目背景与痛点拆解 1.1 把减速带的位置先画出来 最近在把一套已经上线的 Flutter 应用迁移到鸿蒙端,接这个任务之前我预想最麻烦的会是各种原生插件的鸿蒙适配,结果真正卡了我一个多星期的,反而是 flutter_auto_localizations 这个纯 Da…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉