一、引言
在 STM32 微控制器的众多应用中,PWM(脉冲宽度调制)功能是一项非常实用的技术。PWM 可以通过控制信号的占空比来实现对输出功率的精确控制,其应用范围广泛,从电机速度控制、灯光亮度调节到音频信号的生成等。其中,使用 PWM 制作呼吸灯是一个经典的入门示例,能够帮助我们很好地理解 PWM 的原理和 STM32 的相关配置与编程方法。呼吸灯效果通过不断改变 LED 的亮度,使其呈现出由暗到亮,再由亮到暗的渐变效果,就像人的呼吸一样,给人一种柔和、流畅的视觉感受。
二、PWM 原理概述
PWM 信号是一种周期性的方波信号,它的一个周期由高电平和低电平组成。占空比是指一个周期内高电平持续的时间与整个周期时间的比值,通常用百分比表示。通过改变占空比,可以改变平均输出电压,进而实现对连接到该输出的负载(如 LED)的功率控制。对于呼吸灯,我们将通过逐渐增加和逐渐减小占空比,使 LED 的亮度产生周期性的变化。
三、硬件连接
对于 STM32 微控制器,通常需要将一个 LED 连接到一个具有 PWM 功能的引脚。例如,在 STM32F4 系列中,可以使用 TIM(定时器)的输出比较通道来生成 PWM 信号。假设我们将一个 LED 的正极通过一个限流电阻连接到 STM32 的 PA8 引脚,该引脚可作为 TIM1 的通道 1 的输出。
四、STM32 软件实现
以下是使用 STM32 的 HAL 库实现呼吸灯的示例代码:
#include "stm32f4xx_hal.h"
// 定义定时器句柄
TIM_HandleTypeDef htim1;
// 定时器初始化函数
void MX_TIM1_Init(void)
{
// 配置定时器基本参数
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1000;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_PWM_Init(&htim1)!= HAL_OK)
{
Error_Handler();
}
}
// 配置 PWM 通道
void MX_PWM_Init(void)
{
TIM_OC_InitTypeDef sConfigOC;
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1)!= HAL_OK)
{
Error_Handler();
}
}
// 错误处理函数
void Error_Handler(void)
{
while(1);
}
// 启动 PWM
void PWM_Start(void)
{
if (HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1)!= HAL_OK)
{
Error_Handler();
}
}
// 呼吸灯函数
void Breath_Light(void)
{
int i;
for (i = 0; i < 1000; i++)
{
// 增加占空比,使 LED 变亮
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, i);
HAL_Delay(1);
}
for (i = 1000; i > 0; i--)
{
// 减小占空比,使 LED 变暗
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, i);
HAL_Delay(1);
}
}
int main(void)
{
HAL_Init();
// 配置系统时钟
SystemClock_Config();
// 初始化定时器
MX_TIM1_Init();
// 初始化 PWM 通道
MX_PWM_Init();
// 启动 PWM
PWM_Start();
while (1)
{
// 调用呼吸灯函数
Breath_Light();
}
}
代码解释:
- 头文件引入:
stm32f4xx_hal.h
是 STM32 的 HAL 库头文件,包含了操作 STM32 所需的各种函数和数据类型。
- 定时器句柄定义:
TIM_HandleTypeDef htim1;
用于管理和操作 TIM1 定时器。
- 定时器初始化函数:
MX_TIM1_Init()
函数对 TIM1 定时器进行初始化,设置其预分频器为 0,计数器模式为向上计数,周期为 1000。预分频器和周期的设置决定了 PWM 信号的频率。这里将Period
设置为 1000 意味着计数器从 0 计数到 1000,形成一个周期。
- PWM 通道配置函数:
MX_PWM_Init()
函数配置 TIM1 的通道 1 的 PWM 模式,初始脉冲宽度(占空比)为 0,输出极性为高电平,关闭快速模式。OCMode
设置为TIM_OCMODE_PWM1
表示使用 PWM 模式 1,在该模式下,当计数器的值小于比较值时输出高电平,否则输出低电平。
- 错误处理函数:
Error_Handler()
函数在出现错误时进入一个无限循环,便于调试时定位问题。
- 启动 PWM 函数:
PWM_Start()
函数使用HAL_TIM_PWM_Start()
启动 TIM1 的通道 1 的 PWM 输出。
- 呼吸灯函数:
Breath_Light()
函数实现呼吸灯效果。首先通过一个for
循环将占空比从 0 逐渐增加到 1000(对应Period
),每次增加后调用HAL_Delay(1)
延迟 1 毫秒,使 LED 逐渐变亮。然后另一个for
循环将占空比从 1000 逐渐减小到 0,使 LED 逐渐变暗。
五、配置系统时钟
为了保证定时器和 PWM 功能正常工作,需要正确配置系统时钟。以下是一个简单的系统时钟配置示例:
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
// 配置时钟源
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
{
Error_Handler();
}
// 配置系统时钟
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHCLKDivider = 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();
}
}
代码解释:
- 时钟源配置:
RCC_OscInitStruct
结构体用于配置时钟源,这里使用内部高速时钟(HSI)作为输入,开启 PLL 并设置其参数,将其倍频到更高频率,以满足系统和定时器的时钟需求。
- 系统时钟配置:
RCC_ClkInitStruct
结构体用于配置系统时钟的不同分频器,包括 HCLK、SYSCLK、PCLK1 和 PCLK2 的分频,以确保各个模块得到合适的时钟频率。
六、注意事项
- 确保硬件连接正确,特别是 LED 的极性和限流电阻的取值,以防止损坏 LED 和 STM32 引脚。
- 对于不同的 STM32 型号,定时器和 PWM 引脚的映射可能不同,需要根据具体的数据手册进行调整。
- 在配置定时器和 PWM 时,要根据所需的 PWM 频率和分辨率来调整预分频器和周期的值。例如,如果需要更高的频率,可以减小周期并适当调整预分频器;反之,如果需要更高的分辨率,可以增大周期。
七、总结
通过使用 STM32 的 PWM 功能,我们可以方便地实现呼吸灯效果,这个示例展示了如何使用 HAL 库对定时器进行初始化和配置,如何设置 PWM 通道,以及如何通过改变占空比来实现 LED 亮度的渐变。在实际开发中,可以根据具体的需求对 PWM 的频率、占空比范围和呼吸灯的速度进行调整。同时,PWM 技术在其他许多领域都有广泛的应用,理解和掌握 PWM 的原理和实现方法对于 STM32 的开发非常重要。
上述代码只是一个基础示例,在实际应用中,可能需要根据不同的 STM32 系列和具体的应用场景进行优化和扩展。例如,可以使用中断来控制 PWM 的更新,避免使用 HAL_Delay()
函数,以提高系统的实时性和效率。
✅作者简介:热爱科研的嵌入式开发者,修心和技术同步精进
❤欢迎关注我的知乎:对error视而不见
代码获取、问题探讨及文章转载可私信。
☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。
标签:定时器,HAL,呼吸,STM32,TIM,PWM,RCC From: https://blog.csdn.net/duierrorshuobu/article/details/145192772