文章目录
- 前言
- 一、软硬件准备
- 二、定时器与PWM原理解析
- (一)定时器
- 1.什么是定时器
- 2. 核心运作参数
- (二)PWM
- 1.什么是PWM
- 2.核心概念
- 3.机制
- 三、定时器控制LED灯
- 1.STM32CubeMX 配置
- 2.添加核心代码
- 3.实验效果视频
- 四、PWM模式实现呼吸灯
- 1.STM32CubeMX 重新配置
- 2.核心代码编写
- 3.配置步骤
- 4.实验效果视频
- 五、总结
前言
为深入了解STM32定时器原理,掌握脉宽调制pwm生成方法,本文将以STM32F103C8T6,搭配 STM32CubeMX 和 Keil MDK5实现两个基础的趣味实验:定时器中断控制LED闪烁 与 PWM输出实现呼吸灯(使用keil虚拟示波器观察pwm波形)。
一、软硬件准备
硬件板卡:STM32F103C8T6 最小系统核心板(Blue Pill)
调试工具:ST-Link V2 下载器
测试引脚:选择 PA1(对应 TIM2 的通道 2)连接 LED
开发软件:STM32CubeMX、Keil MDK5 (使用 HAL 库)
二、定时器与PWM原理解析
(一)定时器
1.什么是定时器
单片机里的定时器其实就是一个硬件的计数器,工作时就像我们自己数数一样,从1开始累加下去。定时器是在晶振(时钟信号)的驱动下,按照固定的节拍不断累加计数。当计数达到我们想要的目标值时,他就会触发一个命令或者执行一个动作,达到我们想要的情况。
2. 核心运作参数
- 输入时钟 (Clock):实验中配置的72MHz。
- 预分频器:如果把 PSC 设为 7199,那么实际给计数器的时钟频率就是 72MHz / (7199+1) = 10kHz(1秒钟跳1万次)。
- 自动重装载寄存器:就是实验中配置的Counter Period,它是定时器的“目标值”。当计数器从 0 数到 ARR 设置的值(比如 9999)时,就会发生溢出,产生中断,并重新回到 0 开始下一轮数数。
(二)PWM
1.什么是PWM
单片机的引脚只能输出数字信号:要么是 3.3V(纯高电平,全亮),要么是 0V(纯低电平,全灭)。那怎么让 LED 呈现出“半亮”或者“渐亮”的效果呢?
这就是PWM发挥作用的地方。它通过极其快速地不断开关引脚,利用人眼的视觉暂留效应(或者电容电感的平滑作用),让我们“感觉”到电压被降低了。
如果 1 秒内,开关各占一半时间,LED 看起来就是 50% 的亮度。
如果 1 秒内,90% 的时间开,10% 的时间关,LED 看起来就是 90% 的亮度。
2.核心概念
频率: 1 秒钟内开关循环的次数。频率太低,LED 就会闪烁(肉眼能看出来);频率足够高(比如 1kHz),人眼就只能感觉到亮度的变化。PWM 的频率由定时器的 ARR 决定。
占空比: 在一个周期内,高电平(开)持续的时间占总时间的比例。占空比直接决定了等效输出电压的大小,也就是 LED 的亮度。
3.机制
STM32 的定时器内部还有一个非常重要的寄存器:捕获/比较寄存器 (Compare Register, 简称CCR)。定时器产生PWM时,计数器CNT与寄存器CCR开始工作:
- 假设 ARR = 999,CCR = 300。
- 当计数器 CNT 开始从 0 往上数,只要 CNT < 300,引脚输出高电平。
- 当 CNT 继续数,变成 300 到 999 之间时,引脚自动切换为低电平。
- 数到 999 溢出后,一切重来。
这样,占空比就是 300 / 1000 = 30%。在呼吸灯实验中,我们在 while(1) 循环里不断改变的,正是这个 CCR 的值!通过让 CCR 慢慢变大再慢慢变小,占空比跟着变化,就实现了优美的呼吸效果。
三、定时器控制LED灯
1.STM32CubeMX 配置
打开cubeMX,选择我们的STM32F103C8Tx,然后分别操作
System Core -> RCC:高速时钟 (HSE) 选择 Crystal/Ceramic Resonator。
System Core -> SYS:Debug 选择 Serial Wire。
在右侧的引脚图中,选择pa1引脚,设置为GPIO_Output。然后左侧菜单进入 Timers -> TIM2,Clock Source 选择 Internal Clock。
Prescaler (预分频) 设为 7199,Counter Period (重装载值) 设为 9999
切换到 Clock Configuration,HCLK 输入 72 并回车。
Project Manager 中设置工程名,IDE 选择 MDK-ARM,点击 GENERATE CODE。
2.添加核心代码
打开 Keil 工程,在 main.c 中添加以下代码:
在 /* USER CODE BEGIN 2 */ 中开启定时器中断:
/* USER CODE BEGIN 2 */HAL_TIM_Base_Start_IT(&htim2);/* USER CODE END 2 */在文件末尾 /* USER CODE BEGIN 4 */ 中重写中断回调函数:
/* USER CODE BEGIN 4 */voidHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef*htim){if(htim->Instance==TIM2){HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);}}/* USER CODE END 4 */此时编译并下载到stm32,即可实现LED2秒周期闪烁。
3.实验效果视频
定时器控制LED
四、PWM模式实现呼吸灯
1.STM32CubeMX 重新配置
更改引脚复用功能:
在右侧芯片图中,左键点击 PA1,必须将模式从 GPIO_Output 更改为 TIM2_CH2。
定时器 PWM 设置:
- 进入 Timers -> TIM2。
- Channel2 选择 PWM Generation CH2。
- 修改参数以产生适合呼吸灯的 PWM 频率(如 1kHz):
Prescaler 设为 71 (此时定时器频率为 72M/72 = 1MHz)
Counter Period (ARR) 设为 999 (PWM频率 = 1M/1000 = 1kHz)
Pulse 保持 0。
最后重新生成代码并覆盖原工程。
2.核心代码编写
在 main.c 中添加控制占空比动态变化的逻辑:
定义全局变量 (在 /* USER CODE BEGIN 1 */ 中):
/* USER CODE BEGIN 1 */uint16_tpwm_val=0;// 记录当前占空比uint8_tdir=1;// 呼吸方向:1为渐亮,0为渐灭/* USER CODE END 1 */开启 PWM 输出 (在 /* USER CODE BEGIN 2 */ 中):
/* USER CODE BEGIN 2 */HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);/* USER CODE END 2 */主循环逻辑 (放在 while(1) 内部):
/* Infinite loop *//* USER CODE BEGIN WHILE */while(1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */if(dir==1){pwm_val+=5;}else{pwm_val-=5;}// 阈值判断,ARR设定的是999,最大占空比限制在1000以内if(pwm_val>=1000){dir=0;pwm_val=1000;}elseif(pwm_val==0){dir=1;}// 修改比较寄存器 CCR2 的值,动态改变占空比__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,pwm_val);// 延时调节呼吸速度 (每次增减5,一个完整周期约需 400步 * 4ms = 1.6秒)HAL_Delay(4);}/* USER CODE END 3 */3.配置步骤
切换为软件仿真模式:
点击魔术棒 Options for Target -> Debug。
勾选左侧的 Use Simulator。
确保左下角 Dialog DLL 为 DARMSTM.DLL,Parameter 为 -pSTM32F103C8。
设置逻辑分析仪:
点击 Debug 图标 (红色的 d) 进入调试界面。
菜单栏选择 View -> Analysis Windows -> Logic Analyzer。
点击左上角 Setup,新建信号输入 PORTA.1 并按回车。
选中 PORTA.1,将下方的 Display Type 修改为 Bit,点击 Close。
4.实验效果视频
基于stm32-定时器PWM控制的led呼吸灯
五、总结
本次实验通过 STM32CubeMX 和 Keil MDK5 平台,成功完成了基于 STM32F103C8T6 的定时器中断控制 LED 闪烁与 PWM 呼吸灯的两个核心项目。