1. 开发环境与硬件准备
作为一名嵌入式开发者,我最近在做一个基于STM32F103RC的项目,选择了RT-Thread Studio和STM32CubeMX这套开发组合。这套工具链用下来确实能提高不少开发效率,今天就把我的完整搭建过程和经验分享给大家。
先说说硬件准备:
- 主控芯片:STM32F103RC开发板(我用的是正点原子的Mini板)
- 下载调试器:ST-Link V2(建议用正版,盗版经常出各种奇怪问题)
- 串口工具:CH340 USB转TTL模块(记得买带自动下载电路的)
- 其他:杜邦线若干,LED和按键(用于后续功能验证)
软件环境:
- RT-Thread Studio V2.2.6(目前最新稳定版)
- STM32CubeMX V6.8.1(注意版本兼容性)
- 串口终端工具(推荐MobaXterm或SecureCRT)
重要提示:安装CubeMX时建议使用默认路径,否则RT-Thread Studio可能无法正确调用。我曾在D盘安装遇到路径识别问题,折腾了半天才发现是权限问题。
2. 工程创建与基础配置
2.1 新建RT-Thread工程
打开RT-Thread Studio后:
- 点击左上角"File"→"New"→"RT-Thread Project"
- 在弹出窗口中配置关键参数:
- 工程名:建议用英文(如MyF103_Project)
- 模板类型:选择"基于芯片"
- RT-Thread版本:选最新稳定版(目前是5.0.0)
- 芯片厂商:STMicroelectronics
- 芯片系列:STM32F1
- 具体型号:STM32F103RC(务必与开发板一致)
这里有个容易踩的坑:控制台串口默认是USART1,但不同开发板可能使用不同串口。我的板子用的是USART2,需要在这里提前修改,否则后面msh shell无法使用。
2.2 工程结构解析
生成后的工程包含几个关键目录:
applications:用户代码存放处,main.c就在这里drivers:板级驱动,包含串口、GPIO等基础驱动libraries:HAL库和CMSIS核心文件rt-thread:内核源码,不建议直接修改
我习惯在applications下新建/user文件夹存放业务代码,保持工程整洁。同时建议立即设置代码版本控制(Git),我在第一次调试时就因为误操作丢失过代码。
3. CubeMX外设配置
3.1 基础外设初始化
在RT-Thread Studio中右键工程,选择"STM32CubeMX Settings"启动配置:
- Pinout界面配置GPIO:
- PA8(LED1)→ GPIO_Output
- PD2(LED2)→ GPIO_Output
- PA0(KEY0)→ GPIO_Input
- PC5(KEY1)→ GPIO_Input
配置技巧:点击引脚选择模式时,可以右键选择"Enter User Label"添加注释,这样生成的代码可读性更好。
3.2 时钟树配置
这是最容易出错的部分,我的配置步骤:
- RCC选项卡启用HSE(外部8MHz晶振)
- 切换到Clock Configuration标签
- 在HCLK输入框键入72(单位MHz)
- 回车后系统会自动计算各总线分频
实测发现:如果直接使用默认配置,系统时钟只有64MHz。必须手动设置才能达到STM32F103的最高主频72MHz。
3.3 调试接口设置
在System Core→SYS中:
- Debug选择Serial Wire(SWD模式)
- Timebase Source选SysTick(RT-Thread依赖它)
这里有个隐藏坑点:如果不配置Debug接口,第二次烧录时会提示"No ST-Link detected",必须按住复位键才能重新连接。我因此浪费了两小时排查。
4. 代码生成与工程整合
4.1 生成代码配置
在Project Manager选项卡:
- Toolchain选择"MDK-ARM"(虽然我们用RT-Thread Studio编译)
- 勾选"Generate peripheral initialization as a pair of .c/.h files"
- Code Generator中勾选"Generate peripheral initialization as a pair of .c/.h files"
点击GENERATE CODE后,务必先关闭CubeMX,否则RT-Thread Studio无法检测到变更。我就因为没关导致后续配置无法同步。
4.2 工程结构调整
回到RT-Thread Studio后:
- 右键main.c→"Resource Configurations"→"Exclude from Build"
- 在applications文件夹新建main_app.c
- 复制原main.c内容到新文件
为什么要这么做?因为CubeMX生成的main.c会被覆盖,把业务逻辑写在独立文件更安全。我曾在更新配置后丢失过全部用户代码。
5. 定时器功能实现
5.1 硬件定时器配置
在CubeMX中:
- 启用TIM3(通用定时器)
- 时钟源选择Internal Clock
- Prescaler设为7199(72MHz/7200=10KHz)
- Counter Period设为5000(0.5秒中断)
生成代码后,需要在stm32f1xx_hal_msp.c中确认HAL_TIM_Base_MspInit()是否被正确生成。
5.2 RT-Thread软件定时器
在main_app.c中添加:
c复制static struct rt_timer led_timer;
static void led_timeout(void *param)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);
}
int main(void)
{
rt_timer_init(&led_timer, "led_tmr",
led_timeout, RT_NULL,
500, RT_TIMER_FLAG_PERIODIC);
rt_timer_start(&led_timer);
return 0;
}
两种定时器对比:
- 硬件定时器:精度高,占用CPU资源少
- 软件定时器:使用简单,可动态创建/删除
实际项目中,我用硬件定时器做电机PWM控制,软件定时器处理UI刷新。
6. 下载调试与问题排查
6.1 下载配置
在RT-Thread Studio中:
- 点击工具栏"Debug Configurations"
- 新建STM32 Cortex-M配置
- 选择正确的ST-Link接口(SWD)
- 在Startup勾选"Reset and Delay"(解决部分板子无法识别问题)
遇到下载失败时,我的排查步骤:
- 检查ST-Link驱动(设备管理器显示为ST-Link Debug)
- 测量目标板3.3V供电是否正常
- 尝试按住复位键点击下载
- 换用J-Link或DAP-Link测试
6.2 常见问题解决
-
msh无输出:
- 检查CubeMX中串口配置
- 确认board.h中的BSP_USING_UARTx定义
- 测量TX引脚电压(应有3.3V电平变化)
-
程序跑飞:
- 检查栈大小(RT-Thread默认2K可能不够)
- 在rtconfig.h中增大HEAP大小
- 使用HardFault调试工具定位错误地址
-
外设不工作:
- 确认时钟使能(__HAL_RCC_GPIOA_CLK_ENABLE())
- 检查CubeMX生成代码是否被调用(MX_GPIO_Init())
- 测量引脚实际电平
7. 进阶开发建议
7.1 多线程实现
RT-Thread的精髓在于多任务管理,典型创建方式:
c复制static void thread_entry(void *param)
{
while(1) {
rt_thread_mdelay(100);
}
}
int demo_init(void)
{
rt_thread_t tid = rt_thread_create("demo",
thread_entry,
NULL,
512,
20,
10);
if(tid) rt_thread_startup(tid);
return 0;
}
MSH_CMD_EXPORT(demo_init, startup demo thread);
7.2 使用FinSH控制台
通过msh可以动态管理线程:
- list_thread:查看所有线程状态
- free:显示内存使用情况
- 自定义命令(用MSH_CMD_EXPORT导出)
我经常用list_device命令查看驱动注册情况,快速判断外设是否初始化成功。
7.3 性能优化技巧
- 关闭未使用的外设时钟节省功耗
- 将频繁调用的函数放在RAM中执行(attribute((section(".fast_code"))))
- 使用内存池替代动态内存分配
- 关键代码禁用中断(rt_hw_interrupt_disable/enable)
这套开发流程我已经在三个量产项目中使用,稳定性值得信赖。刚开始可能会觉得配置复杂,但熟悉后开发效率比裸机提高至少50%。特别是RT-Thread的组件生态,可以直接使用文件系统、网络协议栈等成熟模块,避免重复造轮子。