打印
[STM32F1]

使用STM32F103实现PWM输出控制:详解与实践

[复制链接]
52|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Clyde011|  楼主 | 2025-1-13 07:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1. 项目背景PWM(Pulse Width Modulation,脉宽调制)是一种通过调节信号的宽度(占空比)来实现控制的技术,在嵌入式系统中得到了广泛应用。无论是在电机控制、LED亮度调节,还是在音频信号生成中,PWM都扮演着重要角色。
STM32F103是一款基于ARM Cortex-M3核心的微控制器,具有丰富的外设和强大的计算能力,能够轻松实现PWM信号的生成。今天,我们将介绍如何在STM32F103上使用PWM输出控制一个LED的亮度。
2. 开发环境搭建要完成本项目,我们需要准备以下工具和设备:
  • 开发板:STM32F103C8T6开发板(俗称蓝色小开发板)。
  • 开发工具
    • STM32CubeMX:用于外设配置和代码生成。
    • STM32CubeIDE:编写和编译代码。
  • 硬件
    • LED灯和适当的电阻(建议220Ω)。
    • 杜邦线(用于连接开发板和LED)。
3. 配置PWM外设我们将在STM32F103上使用定时器(Timer)来生成PWM信号。定时器通过不同的占空比来控制PWM输出,从而调节LED的亮度。
步骤:
  • 打开STM32CubeMX并选择STM32F103C8T6芯片。
  • 进入Peripherals菜单,选择TIM3(作为PWM输出)。
  • 配置TIM3为PWM模式,设置预分频器和自动重装载寄存器(ARR)来确定PWM的周期。
  • 配置PA6为TIM3的输出引脚。
  • 生成代码,选择STM32CubeIDE作为开发环境。
4. 代码实现生成代码后,我们可以在STM32CubeIDE中编写应用程序代码。以下是一个完整的代码示例,用于控制LED的亮度。
#include "main.h"

// 定义PWM占空比
uint32_t pwmDutyCycle = 0;

// 初始化定时器
void Timer_Init(void)
{
    // TIM3定时器配置
    TIM_HandleTypeDef htim3;
    TIM_OC_InitTypeDef sConfigOC;

    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 72 - 1;  // 1 MHz的定时器时钟
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 1000 - 1;   // PWM周期为1ms
    htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim3.Init.RepetitionCounter = 0;

    if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
    {
        Error_Handler();
    }

    // 配置PWM通道1(PA6)
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = pwmDutyCycle;  // 初始化占空比为0
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

    if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
    }

    // 启动PWM
    if (HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1) != HAL_OK)
    {
        Error_Handler();
    }
}

// 调节PWM占空比
void Set_PWM_DutyCycle(uint32_t dutyCycle)
{
    if (dutyCycle <= 1000)
    {
        pwmDutyCycle = dutyCycle;
        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, pwmDutyCycle);
    }
}

// 主程序
int main(void)
{
    // HAL库初始化
    HAL_Init();

    // 系统时钟配置
    SystemClock_Config();

    // 初始化GPIO、定时器
    Timer_Init();

    // 循环调节PWM占空比来改变LED亮度
    while (1)
    {
        for (uint32_t i = 0; i <= 1000; i += 10)
        {
            Set_PWM_DutyCycle(i);
            HAL_Delay(50);  // 延迟50ms
        }

        for (uint32_t i = 1000; i > 0; i -= 10)
        {
            Set_PWM_DutyCycle(i);
            HAL_Delay(50);  // 延迟50ms
        }
    }
}
5. 代码解释
  • Timer_Init:配置定时器TIM3以生成PWM信号。通过设置预分频器和ARR寄存器,我们决定PWM信号的周期为1ms。
  • Set_PWM_DutyCycle:根据传入的占空比调整TIM3的比较寄存器,进而改变PWM的占空比。
  • 主程序:在主循环中,我们通过改变占空比使LED逐渐亮起和变暗,从而实现LED的亮度渐变效果。
6. 调试与测试
  • 将代码编译并烧录到STM32F103开发板中。
  • 将PA6引脚连接到LED的正极,并连接适当的限流电阻(如220Ω)。
  • 通过调试,我们可以看到LED的亮度逐渐从暗到亮,再从亮到暗,形成渐亮渐暗的效果。
7. 常见问题与解决方案
  • 问题:LED无法正常亮起或亮度不变。解决方案:检查定时器和PWM配置,确保PA6引脚已正确配置为定时器的输出引脚。
  • 问题:LED亮度变化不平滑。解决方案:检查PWM周期和占空比设置,确保周期足够长,且占空比调节的步进足够小,以实现平滑过渡。
  • 问题:LED闪烁不稳定。解决方案:检查定时器的初始化配置,确保定时器时钟和PWM频率设置正确。

8. 总结在STM32F103微控制器上使用PWM进行LED亮度控制是一个简单而常见的应用。通过配置定时器生成PWM信号并调节占空比,我们可以灵活地控制LED的亮度。此技术不仅在LED调光中有应用,还可以扩展到电机控制、音频调节等多个领域。

使用特权

评论回复
沙发
公羊子丹| | 2025-1-13 07:43 | 只看该作者
这篇帖子太实用了!终于能用STM32控制LED亮度了!从来没做过PWM,感觉好像学会了一个新技能。

使用特权

评论回复
板凳
周半梅| | 2025-1-13 07:44 | 只看该作者
楼主讲解得很清晰,特别是代码里的注释,刚开始接触嵌入式的我很受用。

使用特权

评论回复
地板
帛灿灿| | 2025-1-13 07:44 | 只看该作者
直接用这个代码控制LED的亮度,效果挺好的。就是调试时需要多注意定时器的参数。

使用特权

评论回复
5
童雨竹| | 2025-1-13 07:44 | 只看该作者
这个PWM的应用不止可以调节LED亮度吧?我试了一下,控制舵机也可以。

使用特权

评论回复
6
万图| | 2025-1-13 07:44 | 只看该作者
看了这篇帖子,我学会了如何在STM32上用定时器做PWM输出,真是大开眼界!

使用特权

评论回复
7
Wordsworth| | 2025-1-13 07:45 | 只看该作者
刚开始用STM32做PWM,感觉这个教程帮我节省了不少时间,感谢楼主!

使用特权

评论回复
8
Bblythe| | 2025-1-13 07:45 | 只看该作者
学习到了!STM32F103的PWM调节真是好用,LED亮度调节得特别顺畅。

使用特权

评论回复
9
Pulitzer| | 2025-1-13 07:45 | 只看该作者
控制LED亮度的效果非常好,PWM输出的精度也高,调节很细腻,支持楼主!

使用特权

评论回复
10
Uriah| | 2025-1-13 07:46 | 只看该作者
这个教程对我来说很有帮助。之前做PWM输出时总是遇到问题,看看这篇教程后解决了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

3480

帖子

0

粉丝