1. 项目概述与准备工作
作为一名嵌入式开发者,拿到一块新的开发板后,第一个"Hello World"往往就是让板载LED闪烁起来。这次我使用的是STM32L562 Discovery Kit开发板,搭配STM32CubeMX和MDK-ARM工具链,带大家完整走一遍从工程创建到LED闪烁的实现过程。
STM32L5系列是ST推出的超低功耗安全微控制器,基于Arm Cortex-M33内核,主频可达110MHz。相比其他STM32系列,L5在保持低功耗特性的同时增强了安全功能,非常适合物联网终端设备开发。开发板上的两颗LED分别连接在PG12(绿灯)和PD3(红灯),我们将通过GPIO控制实现交替闪烁效果。
所需工具清单:
- STM32CubeMX v6.x(ST官方免费配置工具)
- MDK-ARM v5.x(Keil开发环境)
- STM32L562E-DK开发板
- USB Type-C数据线(用于供电和调试)
提示:建议安装最新版STM32CubeMX,确保支持L5系列芯片。MDK-ARM需要安装对应的STM32L5 Device Family Pack(DFP)。
2. 工程创建与基础配置
2.1 新建STM32CubeMX工程
启动STM32CubeMX后,有两种方式创建新工程:
- 基于MCU选择器:适用于自定义硬件设计
- 基于开发板选择器:直接匹配官方开发板配置
这里我们选择第二种方式,在"Board Selector"选项卡中搜索"STM32L562E-DK",双击开发板图标进入配置界面。
关键配置步骤:
- 工程命名(如"LED_Blink")
- 存储路径(建议使用英文路径)
- 选择Toolchain/IDE为"MDK-ARM V5"
- 勾选"Initialize all peripherals with their default Mode"

2.2 代码生成设置
在"Project Manager" → "Code Generator"选项卡中,建议做如下配置:
- 勾选"Generate peripheral initialization as a pair of '.c/.h' files per peripheral"
- 勾选"Backup previously generated files when re-generating"
- 取消勾选"Generate under root"以保持目录整洁
这种配置方式会让每个外设的初始化代码生成独立的.c/.h文件,便于后期维护。例如GPIO的初始化代码会放在gpio.c和gpio.h中,而不是全部堆在main.c里。
3. 时钟系统配置
3.1 启用外部时钟源
STM32L562开发板搭载了24MHz外部晶振,我们首先在"Pinout & Configuration" → "RCC"中启用HSE:
- High Speed Clock (HSE): Crystal/Ceramic Resonator

注意:如果使用内部时钟(HSI)可以跳过此步,但外部晶振能提供更精确的时钟基准。
3.2 时钟树配置
进入"Clock Configuration"选项卡,我们需要配置系统时钟为最高110MHz:
- 在HSE输入框输入24(开发板晶振频率为24MHz)
- 将PLL Source Mux选择为HSE
- 配置PLL分频和倍频参数:
- PLLM = 3 (HSE先3分频得到8MHz)
- PLLN = 55 (8MHz × 55 = 440MHz)
- PLLR = 4 (440MHz / 4 = 110MHz)
- 系统时钟选择PLLCLK
- 确认APB1/APB2时钟不超过110MHz限制

时钟配置原理:
STM32L5的时钟树相对复杂,但核心思路是通过PLL将低频晶振时钟倍频到更高频率。我们选择PLLR作为系统时钟源是因为:
- PLLR专为系统时钟设计,输出稳定
- 110MHz是STM32L5的最高运行频率
- APB总线时钟自动分频,确保外设不超频
4. GPIO配置与代码生成
4.1 确定LED引脚
查阅开发板原理图可知:
- 绿色LED连接PG12,低电平点亮
- 红色LED连接PD3,低电平点亮
在CubeMX的引脚图中找到对应引脚:
- PG12 → 配置为GPIO_Output
- PD3 → 配置为GPIO_Output

引脚配置技巧:
- 右键点击引脚可选择功能
- 建议为每个GPIO设置用户标签(如LED_GREEN/LED_RED)
- 输出模式默认选择"Push Pull",无特殊需求不用改
4.2 生成初始化代码
点击"GENERATE CODE"按钮,CubeMX会自动:
- 生成完整的MDK-ARM工程
- 创建所有外设初始化代码
- 包含必要的HAL库文件
- 生成.ioc配置文件(后续可重新修改配置)

常见问题:如果代码生成失败,检查路径是否包含中文/特殊字符,或者尝试以管理员身份运行CubeMX。
5. 应用程序开发
5.1 工程结构解析
生成的MDK工程包含以下关键部分:
- Application/User: 用户代码区(main.c, gpio.c等)
- Drivers: HAL库和CMSIS核心文件
- MDK-ARM: 工程文件和启动脚本
- STM32CubeMX: 配置文件(.ioc)
特别重要的是main.c中的代码结构:
c复制/* USER CODE BEGIN PV */
// 变量定义放在这里
/* USER CODE END PV */
/* USER CODE BEGIN PFP */
// 函数声明放在这里
/* USER CODE END PFP */
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
// 初始化后代码
/* USER CODE END 2 */
while (1) {
/* USER CODE BEGIN 3 */
// 主循环代码
/* USER CODE END 3 */
}
}
重要提示:所有用户代码必须写在USER CODE BEGIN/END注释对之间,否则重新生成代码时会被覆盖。
5.2 LED控制实现
在main.c中添加以下代码:
- 初始化LED状态(放在USER CODE BEGIN 2处):
c复制HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET);
- 主循环中实现交替闪烁(放在USER CODE BEGIN 3处):
c复制HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
HAL_Delay(1000); // 1秒延时
代码解析:
HAL_GPIO_WritePin()用于设置GPIO输出状态HAL_GPIO_TogglePin()翻转当前GPIO状态HAL_Delay()提供毫秒级延时(基于SysTick定时器)
实测技巧:如果LED亮灭状态与预期相反,检查开发板原理图确认LED是低电平还是高电平驱动。
6. 编译与调试
6.1 工程编译
- 在MDK-ARM中点击"Rebuild"按钮编译整个工程
- 确认输出窗口显示"0 Error(s), 0 Warning(s)"
- 生成的hex文件位于Objects目录下
常见编译问题解决:
- 如果提示缺少头文件,检查是否安装了正确的Device Family Pack
- 如果HAL库函数未定义,确认在CubeMX中生成了所有必要的外设初始化代码
- 内存不足错误可能需要调整优化等级(Options for Target → C/C++)
6.2 程序下载与调试
- 使用USB线连接开发板的ST-LINK端口
- 在MDK-ARM中选择ST-LINK调试器
- 点击"Load"按钮下载程序
- 复位开发板观察LED闪烁

调试技巧:
- 可以在GPIO翻转代码前后设置断点
- 使用逻辑分析仪查看GPIO实际输出波形
- 如果无法连接调试器,尝试更新ST-LINK固件
7. 进阶优化与问题排查
7.1 降低功耗的改进方案
虽然简单的LED闪烁对功耗不敏感,但作为L5系列的低功耗实践,我们可以:
- 在延时期间进入低功耗模式:
c复制HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
- 降低系统时钟频率(当不需要110MHz时)
- 配置未使用的GPIO为模拟输入模式
7.2 常见问题速查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| LED不亮 | 1. 程序未运行 2. GPIO配置错误 3. 硬件连接问题 |
1. 检查复位电路 2. 确认CubeMX配置 3. 用万用表测量电压 |
| 闪烁频率不对 | 1. 时钟配置错误 2. 延时函数不准确 |
1. 检查时钟树配置 2. 使用示波器校准延时 |
| 无法下载程序 | 1. 调试器连接问题 2. 芯片保护 |
1. 检查USB连接 2. 尝试芯片擦除 |
7.3 使用寄存器直接控制GPIO
除了HAL库,我们还可以直接操作寄存器实现更高效率的控制:
c复制// 快速翻转PG12
GPIOG->ODR ^= GPIO_ODR_OD12;
这种方式的优点是执行速度快,适合对时序要求严格的场景,但可移植性较差。
8. 项目扩展思路
完成基础LED控制后,可以考虑以下扩展实验:
- 实现PWM调光控制LED亮度
- 添加按键控制改变闪烁模式
- 通过串口命令控制LED状态
- 使用定时器中断实现精确时间控制
- 结合低功耗模式实现电池供电场景优化
每次重新修改.ioc配置后,记得重新生成代码并合并用户代码区。建议使用版本控制工具(如Git)管理工程,方便回溯和比较修改。