手把手:RT-Thread Studio 生成串口工程(STM32F407ZGT6),附完整源码

发布时间:2026/9/11 7:34:08

手把手:RT-Thread Studio 生成串口工程(STM32F407ZGT6),附完整源码 前言之前写过一篇利用 STM32CubeMX 裸机工程手动移植 RT-Thread 的文章。今天换一种更省事的方式——直接用 RT-Thread Studio 生成工程全程可视化操作不需要手动复制文件。本文面向第一次用 RT-Thread Studio 做 STM32 开发的同学目标新建工程 → 配置外设 → 写代码 → 在板子上跑通三个线程。目录前言一、开发环境二、下载 RT-Thread Studio三、新建 RT-Thread 工程四、STM32CubeMX配置4.1 打开 CubeMX Settings4.2 配置 RCC时钟源4.3 配置 SYS调试接口4.4 配置 GPIOLED4.5 配置 USART1串口4.6 配置时钟树4.7 工程管理配置4.8 生成代码五、编译六、编写应用代码6.1 将外设初始化搬到应用 main6.2 创建三个线程6.3 编译报错七、实验验证7.1 调试终端验证7.2 硬件验证八、总结一、开发环境主控芯片STM32F407ZGT6编译工具RT-Thread Studio2.3.0配置工具STM32CubeMX 6.17.0操作系统RT-Thread 4.0.3串口助手SSCOM V5.13.1二、下载 RT-Thread Studio进入RT-Thread Studio官网rt-thread.org/studio.html点击下载。推荐使用版本2.3.0对新手更友好网盘下载或官网下载均可。下载后默认安装即可。三、新建 RT-Thread 工程打开 RT-Thread Studio菜单栏选择文件--新建-- RT-Thread 项目。在弹出的对话框中填写工程信息如果首次使用没有安装 STM32F4 系列芯片支持包在SDK 管理器里搜索安装即可。安装完成后点击完成。一个基础的 RT-Thread 工程就创建成功了。注意目前工程使用的是芯片内部HSI 时钟8MHz精度一般。建议后续通过 CubeMX 切换到外部 HSE 晶振以获得准确的主频。四、STM32CubeMX配置RT-Thread Studio 内置了CubeMX Settings入口可以直接启动 CubeMX 并同步配置。4.1 打开 CubeMX Settings在工程根目录双击CubeMX Settings选择你安装的 STM32CubeMX.exe 路径。4.2 配置 RCC时钟源进入RCCHSE→ 选择Crystal/Ceramic Resonator4.3 配置 SYS调试接口进入SYSDebug→ 选择Serial Wire (SWD)占用 PA13/PA14与调试器通信警告调试接口一定要配成 SWD否则 PA13/PA14 被当成 GPIO 后 SWD 会连不上板子只能通过 BOOT 模式救砖。4.4 配置 GPIOLED在芯片引脚图上点击 PF9 和 PF10选择GPIO_Output用于控制板载 LED。4.5 配置 USART1串口选择USART1配置为异步串口通信参数保持默认115200-8-N-1。4.6 配置时钟树切换到Clock Configuration标签页输入 HSE 频率24 MHzPLLM 分频12PLLN 倍频168PLLP 分频2最终系统时钟168 MHz注意HSE要根据板子实际的外部晶振频率来。4.7 工程管理配置4.8 生成代码点击GENERATE CODE等待 CubeMX 生成完成。回到 RT-Thread Studio会提示检测到代码变更。验证时钟配置是否生效打开board/drv_clk.c可以看到它自动调用了 CubeMX 生成的SystemClock_Config()配置参数为24MHz 外部晶振锁相到 168MHz。void clk_init(char *clk_source, int source_freq, int target_freq) { /* * Use SystemClock_Config generated from STM32CubeMX for clock init * system_clock_config(target_freq); */ extern void SystemClock_Config(void); SystemClock_Config(); }void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState RCC_HSE_ON; RCC_OscInitStruct.PLL.PLLState RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM 12; RCC_OscInitStruct.PLL.PLLN 168; RCC_OscInitStruct.PLL.PLLP RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLQ 4; if (HAL_RCC_OscConfig(RCC_OscInitStruct) ! HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider RCC_HCLK_DIV4; RCC_ClkInitStruct.APB2CLKDivider RCC_HCLK_DIV2; if (HAL_RCC_ClockConfig(RCC_ClkInitStruct, FLASH_LATENCY_5) ! HAL_OK) { Error_Handler(); } }五、编译在写程序代码之前我们先构建项目。点击项目 → 全部构建CtrlB会看到几十个类似stm32f4xx_hal_conf.h: No such file or directory的错误。原因是CubeMX 生成代码时用完整版 HAL 库覆盖了 RT-Thread 的精简版但头文件路径不一致。这时候需要通过Sconscript文件进行构建加载更新软件包。Sconscriptimport os from building import * cwd GetCurrentDir() src Glob(*.c) add cubemx drivers src Split( Src/stm32f4xx_hal_msp.c Src/main.c ) path [cwd] path [cwd /Inc] group DefineGroup(cubemx, src, depend [], CPPPATH path) Return(group)然后再全部构建一下发现还有报错。双击错误提示处软件会自动跳转到出错的地方。发现原因就是新版drv_usart.c想读取cfg-flowcontrol判断硬件流控模式但旧版serial.h定义的结构体里根本没这个成员编译器直接报错。所以我们将这段switch注释掉就行了一般用不到硬件流控。然后重新构建。至此RT-Thread 工程已成功创建完成。接下来我们将开始编写应用程序代码。六、编写应用代码RT-Thread Studio 生成的模板工程里有两个main.c位置说明编译方式cubemx/Src/main.cCubeMX 生成的 main带__WEAK弱符号不会被调用applications/main.c你写代码的地方链接器优先使用这个因为 CubeMX 的 main 带__WEAK弱符号链接器会自动选择applications/main.c里的int main(void)作为入口。两个 main 不会冲突。查看cubemx/Src/main.c。__WEAK int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals / MX_GPIO_Init(); MX_USART1_UART_Init(); / USER CODE BEGIN 2 */ /* USER CODE END 2 */ /* Infinite loop / / USER CODE BEGIN WHILE / while (1) { / USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }再查看applications/main.c。/* * Copyright (c) 2006-2026, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2026-07-23 RT-Thread first version */ #include rtthread.h #define DBG_TAG main #define DBG_LVL DBG_LOG #include rtdbg.h int main(void) { int count 1; while (count) { LOG_D(Hello RT-Thread!); rt_thread_mdelay(1000); } return RT_EOK; }6.1 将外设初始化搬到应用 main把 CubeMX 生成的外设初始化函数搬到applications/main.c里#include rtthread.h #include gpio.h #include main.h #include usart.h int main(void) { /* CubeMX 初始化GPIO 模式、USART1 波特率/引脚 */ MX_GPIO_Init(); MX_USART1_UART_Init(); /* ... 后续创建线程 */ }6.2 创建三个线程分别实现三个功能线程功能周期thread1串口打印 Thread1 run每 2 秒thread2串口打印 Thread2 run每 3 秒thread3PF9LED0和 PF10LED1交替闪烁每 1 秒切换完整代码如下含详细注释/* * Copyright (c) 2006-2026, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2026-07-23 RT-Thread first version */ #include rtthread.h /* RT-Thread 内核头文件线程、信号量、rt_kprintf 等 */ #include gpio.h /* CubeMX 生成的 GPIO 初始化声明 */ #include main.h /* CubeMX 主头文件引脚定义、外设句柄 */ #include usart.h /* CubeMX 生成的 USART 初始化声明 */ static rt_thread_t thread1; /* 线程句柄指向 thread1 */ static rt_thread_t thread2; /* 线程句柄指向 thread2 */ static rt_thread_t thread3; /* 线程句柄指向 thread3 */ /*--------------------------------------------------------- * 线程 1 入口每 2 秒打印一次 Thread1 run *---------------------------------------------------------*/ static void thread1_entry(void *parameter) { while(1) { rt_kprintf(Thread1 run\r\n); /* 串口输出 */ rt_thread_mdelay(2000); /* 挂起 2 秒让出 CPU */ } } /*--------------------------------------------------------- * 线程 2 入口每 3 秒打印一次 Thread2 run *---------------------------------------------------------*/ static void thread2_entry(void *parameter) { while(1) { rt_kprintf(Thread2 run\r\n); rt_thread_mdelay(3000); /* 挂起 3 秒 */ } } /*--------------------------------------------------------- * 线程 3 入口LED 交替闪烁PF9 / PF10每 1 秒切换一次 *---------------------------------------------------------*/ static void thread3_entry(void *parameter) { while(1) { /* LED0 灭LED1 亮 */ HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_SET); rt_thread_mdelay(1000); /* 保持 1 秒 */ /* LED0 亮LED1 灭 */ HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_RESET); rt_thread_mdelay(1000); /* 保持 1 秒 */ } } /*--------------------------------------------------------- * 主函数初始化硬件创建并启动三个线程 *---------------------------------------------------------*/ int main(void) { /* CubeMX 初始化GPIO 模式、USART1 波特率/引脚 */ MX_GPIO_Init(); MX_USART1_UART_Init(); /* 创建并启动线程 1打印 thread1 */ thread1 rt_thread_create(thread1, /* 线程名称FinSH 可见 */ thread1_entry, /* 入口函数 */ RT_NULL, /* 入口参数 */ 512, /* 栈大小字节 */ 5, /* 优先级0~31越小越高 */ 15); /* 时间片线程一次能跑多久 */ if(thread1 ! RT_NULL) { rt_thread_startup(thread1); /* 将线程加入就绪队列 */ } /* 创建并启动线程 2打印 thread2 */ thread2 rt_thread_create(thread2, thread2_entry, RT_NULL, 512, 5, 15); if(thread2 ! RT_NULL) { rt_thread_startup(thread2); } /* 创建并启动线程 3LED 闪烁 */ thread3 rt_thread_create(thread3, thread3_entry, RT_NULL, 512, 5, 15); if(thread3 ! RT_NULL) { rt_thread_startup(thread3); } /* main 线程不能退出否则调度器会跑飞 */ /* 用 mdelay 循环挂起自己让 tshell 和其他线程能正常调度 */ while(1) { rt_thread_mdelay(1000); /* 挂起 1 秒让出 CPU */ } return RT_EOK; /* 实际上不会跑到这里 */ }6.3 编译报错全部构建发现报错。程序找不到这两个初始化函数定义的地方也就是说gpio.c和usart.c没有被编译。查看cubemx文件发现gpio.c和usart.c不见了是被排除构建了。为什么会造成这样的问题呢是因为SConscript 是一个Python 脚本是 scons 编译系统的花名册。它用src列表告诉 scons这个目录下只有这些 .c 要编译别的不管。src Glob(*.c) src Split( Src/stm32f4xx_hal_msp.c Src/main.c )这条命令的意思是总共只编译两个文件stm32f4xx_hal_msp.c和main.c。CubeMX 生成的gpio.c、usart.c——SConscript 眼里不存在。所以这导致了gpio.c和usart.c没有被构建。解决方案是我们手动把它们添加到构建里。将gpio.c和usart.c重新添加构建。再次编译0 errors0 warnings ✅七、实验验证7.1 调试终端验证RT-Thread Studio 自带终端。连接后复位板子可以看到输入list_thread查看线程状态7.2 硬件验证断开终端连接否则占用串口点击烧录按钮向下箭头图标将 USB Type-C线连接到板子打开串口助手115200-8-N-1勾选加回车换行按复位键看到开发板上两个 LED 交替闪烁串口助手有线程打印信息实验成功。八、总结从零到三个线程同时跑通核心就三步建工程RT-Thread Studio 新建基于芯片的模板配外设CubeMX 配置时钟 / GPIO / 串口生成代码写代码多线程交替打印 LED 闪烁RT-Thread Studio CubeMX 的组合是目前 STM32 开发可视化配置 RTOS 生态最快捷的路线之一。但两者之间有一些集成细节需要注意——本文踩的坑大部分都是 CubeMX 和 RT-Thread 之间约定不同导致的。掌握了这些以后用 CubeMX 配其他外设SPI、I2C、TIM也是同样的套路。通过网盘分享的文件Demo.zip链接: https://pan.baidu.com/s/1SaHbVXh7IT_oiTI3MCazXQ?pwdtaoq提取码: taoq--来自百度网盘超级会员v3的分享若发现文中疏漏欢迎指正交流。创作不易还望多多支持。
延伸阅读

更多相关文章

2026/9/11 13:08:04

RAG 在专利检索中的应用:技术特征提取和跨语言专利比对方案

RAG 在专利检索中的应用:技术特征提取和跨语言专利比对方案 一、深度引言与场景痛点 前段时间帮一个做知识产权服务的朋友看他们的专利检索系统,问题比想象中严重。专利检索和普通文档检索有本质区别:专利文献有独特的技术特征表述方式——…

2026/9/10 6:28:44

基于CNN-GRU的DOA分类预测与SHAP可解释性分析

1. 项目概述:基于深度学习的DOA分类预测与可解释性分析这个项目将传统波达方向(DOA)估计问题转化为分类任务,创新性地结合CNN-GRU混合神经网络进行特征提取与序列建模,并引入SHAP值分析实现模型决策的可视化解释。我在实际雷达信号处理项目中…

2026/9/12 2:49:37

直流电气铁路谐波治理与单调谐滤波器设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/12 2:49:37

如何用WeChatMsg永久保存微信聊天记录

如何用WeChatMsg永久保存微信聊天记录 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatMsg 上次换手机时迁移…

2026/9/12 2:49:37

AI Agent记忆系统:跨会话连续性的工程实践与架构设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/12 2:49:37

使用Pydantic与JSON Schema高效验证JSONL数据

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/12 2:05:33

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/10 11:16:38

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/12 0:04:17

MATLAB仿生优化框架:长鼻浣熊算法多策略融合实现

简介:本资源是一份面向智能优化算法研究者与MATLAB初学者的仿生智能算法实践代码包,聚焦于长鼻浣熊优化算法(COA)的多策略改进与性能验证。针对传统COA易陷局部最优、收敛精度不足等问题,作者融合Circle映射初始化提升…

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 JavaWeb 的校园一卡通管理系统的设计与实现 基于 JavaWeb 的校园卡业务管理系统(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/12 0:04:17

【JAVA毕设源码分享】基于 Java 的图书馆借阅管理平台的搭建与实现 基于 Java 的图书馆综合管理系统(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/9/10 12:32:02

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/10 15:19:50

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/10 15:49:53

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码