目录
- 一、前言
- [二、STM32CubeIDE 是什么](#二、STM32CubeIDE 是什么)
- 三、创建工程的关键步骤
- 四、生成的项目目录结构
- [五、main.c 的结构](#五、main.c 的结构)
- [六、第一个程序:GPIO 点灯](#六、第一个程序:GPIO 点灯)
- 七、编译、下载与调试
- 八、总结
- 九、结尾
一、前言
大家好,这里是 Hello_Embed。
本篇文章是"AI编程"系列的第三篇,也是"全场景工业互联设备管理系统"正式进入编码阶段的起点。本文借助 Claude Code 辅助生成,结合项目工程源码进行梳理。
前两篇分别完成了 Claude Code 的安装配置和整个项目的学习总览。从本篇开始,我们正式进入 STM32 开发实践------从一个空工程开始,在 STM32CubeIDE 中完成第一个工程的创建、配置、编译和下载。
本篇覆盖的内容对应课程阶段2的第一节。
二、STM32CubeIDE 是什么
STM32CubeIDE 是 ST 官方推出的免费集成开发环境,集成了三个核心功能:
| 功能 | 说明 |
|---|---|
| CubeMX 图形化配置 | 通过 .ioc 文件可视化配置时钟树、引脚、外设,自动生成初始化代码 |
| Eclipse IDE | 代码编辑、编译(GCC-based)、调试(GDB + OpenOCD) |
| HAL/LL 驱动库 | ST 官方硬件抽象层,一套 API 覆盖全系列 STM32 |
简单说:画图配外设 → 自动生成代码 → 编译 → 下载 → 调试,一个工具全搞定。
STM32CubeIDE 最大的价值在于代码生成不是一次性的 ------后续随时修改 .ioc 文件(比如新增 UART、SPI),CubeIDE 会重新生成代码,并且通过 USER CODE 标记保护你写的用户代码不被覆盖。
三、创建工程的关键步骤
3.1 选择芯片
打开 CubeIDE,File → New → STM32 Project,在芯片选择界面输入 STM32H563RIV6(本项目中控使用的型号)。
关键参数:
- 内核:Cortex-M33,带 TrustZone
- 主频:最高 250MHz
- Flash:2MB(双 Bank)
- SRAM:640KB
3.2 配置时钟树
进入 .ioc 文件的 Clock Configuration 标签页。STM32H5 的时钟源关系:
HSI (内部 64MHz RC)
CSI (内部 4MHz RC) ──► PLL1 ──► SYSCLK (最高 250MHz)
├──► HCLK (AHB 总线)
├──► APB1/2/3 (外设总线)
└──► FCLK (Cortex 自由运行时钟)
HSI48 (内部 48MHz) ──► USB / RNG 专用时钟
首次创建工程时,CubeIDE 会自动生成一个合理的默认时钟配置------通常用 CSI (4MHz) 作为 PLL 源,经 PLL 倍频后得到 250MHz 的 SYSCLK。对于入门阶段,保留默认配置即可,后续章节会根据需要调整。
解析 :STM32H5 上电后默认使用 HSI (64MHz),启动过程中
SystemClock_Config()将时钟源切换到 PLL,达到 250MHz 的主频。这套时钟配置代码由 CubeIDE 根据.ioc中的时钟树自动生成。
3.3 配置引脚
在 Pinout & Configuration 标签页配置 GPIO:
- 本项目开发板上的 LED 连接在 PC12(或查看原理图确认)
- 在芯片引脚图上找到 PC12,右键 →
GPIO_Output - 在左侧 GPIO 配置面板中,可设置初始电平、输出模式(推挽/开漏)、上下拉等
3.4 生成代码
保存 .ioc 文件(Ctrl+S),CubeIDE 会自动重新生成代码。生成的代码严格遵守 USER CODE BEGIN / USER CODE END 标记------你写在标记之间的代码不会被覆盖,标记之外的代码每次保存 .ioc 都会被刷新。
四、生成的项目目录结构
demo/
├── demo.ioc # CubeMX 配置文件(图形化编辑的入口)
├── Core/
│ ├── Inc/ # 头文件
│ │ ├── main.h # 主头文件
│ │ ├── gpio.h # GPIO 初始化声明
│ │ ├── stm32h5xx_hal_conf.h # HAL 模块裁剪配置
│ │ └── stm32h5xx_it.h # 中断服务函数声明
│ └── Src/
│ ├── main.c # 主函数入口
│ ├── gpio.c # GPIO 初始化实现
│ ├── stm32h5xx_hal_msp.c # 外设 MSP(引脚/时钟)初始化
│ ├── stm32h5xx_it.c # 中断服务函数实现
│ └── system_stm32h5xx.c # 系统初始化(启动文件调用)
├── Drivers/
│ ├── STM32H5xx_HAL_Driver/ # HAL 库源码
│ └── CMSIS/ # ARM Cortex-M 核心支持文件
└── MDK-ARM/ # Keil 工程(可选,本课程同时提供)
关键文件说明
| 文件 | 作用 | 你需要关心的程度 |
|---|---|---|
demo.ioc |
图形化外设配置,改引脚/时钟/外设都在这操作 | 必须会用 |
main.c |
主函数入口,用户代码的起点 | 核心文件 |
gpio.c / gpio.h |
GPIO 初始化,由 .ioc 自动生成 | 了解即可 |
stm32h5xx_it.c |
中断服务函数,后期会频繁修改 | 前期了解 |
stm32h5xx_hal_msp.c |
外设级引脚/时钟初始化,一般不改 | 了解即可 |
stm32h5xx_hal_conf.h |
按需裁剪 HAL 模块(开关宏),按需修改 | 偶尔修改 |
五、main.c 的结构
CubeIDE 生成的 main.c 遵循固定的执行流程:
c
int main(void)
{
// 1. HAL 库初始化:Flash 预取、SysTick 配置
HAL_Init();
// 2. 系统时钟配置:根据 .ioc 的时钟树设置
SystemClock_Config();
// 3. 外设初始化:由 .ioc 中启用的外设决定
MX_GPIO_Init(); // GPIO 始终会有
// MX_USART2_UART_Init(); // 如果配置了 UART
// MX_SPI2_Init(); // 如果配置了 SPI
// 4. 用户初始化代码(写在 USER CODE BEGIN 2 内)
// ...
// 5. 主循环
while (1)
{
// 用户代码(写在 USER CODE BEGIN WHILE 内)
}
}
这个流程是整个项目中每一个工程 的模板。后面章节无论加了 UART、USB、FreeRTOS 还是 Modbus,main.c 的主干都是这五步,只是 MX_xxx_Init() 中间会多出几行。
USER CODE 标记规则
CubeIDE 用成对的注释标记来保护用户代码:
c
/* USER CODE BEGIN 2 */ // ← 这行之外的代码会被 CubeIDE 覆盖
LCD_Init(1); // ← 你的代码放在 BEGIN 和 END 之间
Draw_Init(); // ← 这些代码在重新生成后仍然保留
/* USER CODE END 2 */
常用的标记区域:
| 标记 | 位置 | 用途 |
|---|---|---|
USER CODE BEGIN Includes |
文件头部 | 添加自己的 #include |
USER CODE BEGIN PV |
变量区 | 定义全局变量 |
USER CODE BEGIN 2 |
main() 内,外设初始化之后 |
用户初始化代码 |
USER CODE BEGIN WHILE |
while(1) 循环体 |
主循环代码 |
USER CODE BEGIN 4 |
文件尾部 | 添加自定义函数 |
六、第一个程序:GPIO 点灯
在 main.c 的主循环中添加以下代码:
c
while (1)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); // LED 亮
HAL_Delay(500); // 延时 500ms
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); // LED 灭
HAL_Delay(500); // 延时 500ms
}
涉及的 HAL API
c
// 写 GPIO 引脚
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
// PinState 取值:GPIO_PIN_SET (高电平) / GPIO_PIN_RESET (低电平)
// 毫秒级延时(基于 SysTick 中断)
void HAL_Delay(uint32_t Delay);
解析 :
HAL_Delay是阻塞式延时,延时时 CPU 空转等待。它的精度依赖 SysTick 中断,默认每 1ms 触发一次,在stm32h5xx_it.c中的SysTick_Handler()里调用HAL_IncTick()递增计数器。后续学 FreeRTOS 时会用非阻塞的任务延时osDelay()替代它。
七、编译、下载与调试
编译
- CubeIDE:
Project → Build All(或Ctrl+B) - Keil:
Project → Build Target(或F7)
编译输出在 Debug/(CubeIDE)或 MDK-ARM/(Keil)目录下,产物包含 .elf / .hex / .bin 文件。
下载
- 通过调试器(DAP-Link / ST-Link)连接开发板
- CubeIDE:
Run → Debug(自动编译 + 下载 + 进入调试模式) - Keil:
Flash → Download(F8)
调试
| 操作 | CubeIDE 快捷键 | 用处 |
|---|---|---|
| 设置断点 | 双击行号 | 让程序停在指定位置 |
| 单步执行 | F5 / F6 | Step Into(进入函数)/ Step Over(跳过函数) |
| 观察变量 | 右键 → Add Watch | 实时查看变量值 |
| 外设寄存器 | SFRs 窗口 | 直接查看 GPIO/UART 等外设的寄存器状态 |
八、总结
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1 | 新建工程 | 选择 STM32H563RIV6 芯片 |
| 2 | 配时钟 | 默认 CSI → PLL → 250MHz,入门阶段保留默认 |
| 3 | 配引脚 | PC12 设为 GPIO_Output(LED) |
| 4 | 生成代码 | 保存 .ioc,自动生成 HAL 初始化代码 |
| 5 | 写逻辑 | 在 USER CODE 区域内写 GPIO 点灯代码 |
| 6 | 编译下载 | Build + Debug,验证 LED 闪烁 |
这是整个项目中最简单的工程,但它建立的工作流 会贯穿后续所有章节。后续加 UART、USB、FreeRTOS 时,操作模式完全一样------在 .ioc 中启用新外设,重新生成代码,然后在 USER CODE 标记区域内写自己的逻辑。
九、结尾
本篇完成了从空的 CubeIDE 工作区到第一个 LED 闪烁程序的全流程。核心不是点灯本身,而是建立"配 .ioc → 生成代码 → 在 USER CODE 区域写逻辑"的工作习惯。
这篇文章和下一篇《同步传输与异步传输》一起,构成了**阶段2(STM32H5入门)**的基础。
Hello_Embed 在 AI 辅助嵌入式的路上与你同行。