stm32-定时器与PWM

发布于 2024-10-19  2037 次阅读


定时器与脉冲宽度调制(PWM)

1. 定时器概述

  • 定时器是 STM32F103 微控制器中的重要外设,用于实现 计时计数事件产生 等功能。
  • STM32F103 提供了多个通用定时器(如 TIM2、TIM3、TIM4 等),每个定时器都有多达 4 个通道,可用于捕获/比较、PWM 输出等。
  • 定时器可配置为多种工作模式:
    • 输入捕获模式:用于测量输入信号的周期、频率或脉宽。
    • 输出比较模式:当计数器的值与预设的比较值匹配时,产生事件或输出信号。
    • PWM 模式:通过调节脉冲的 占空比,实现对负载的精确控制。

2. PWM 原理

  • PWM(Pulse Width Modulation,脉冲宽度调制)是一种通过改变脉冲信号 占空比 来控制平均输出功率的技术。
  • 占空比 是指脉冲高电平持续时间与周期的比值。通过调整占空比,可以控制负载所获得的能量。
  • PWM 应用领域
    • 电机控制:调节电机的转速和转矩。
    • LED 调光:控制 LED 的亮度,实现从全暗到全亮的平滑过渡。
    • 音频信号:用于数字音频的合成与放大。

3. PWM 配置步骤

要在 STM32F103 上配置 PWM 输出,需要按照以下步骤进行:

  1. 使能时钟:开启对应的定时器和 GPIO 时钟。

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);   // 使能 TIM3 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  // 使能 GPIOA 时钟
  2. 配置 GPIO 引脚为复用功能输出:将用于 PWM 输出的 GPIO 引脚设置为复用推挽输出模式。

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;           // 选择 PA6 引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     // 复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   // GPIO 速度
    GPIO_Init(GPIOA, &GPIO_InitStructure);
  3. 初始化定时器:设置计数模式、周期(ARR)、预分频器(PSC)等参数。

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 999;                // 自动重装载值(决定 PWM 周期)
    TIM_TimeBaseStructure.TIM_Prescaler = 71;              // 预分频器(决定计数器时钟)
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    计算说明

    • 定时器频率 = 主频 / (预分频器 + 1)
    • PWM 频率 = 定时器频率 / (自动重装载值 + 1)
    • 以主频 72MHz 为例,预分频器为 71,则定时器频率为 1MHz。自动重装载值为 999,则 PWM 频率为 1kHz。
  4. 配置 PWM 模式:设置输出比较模式、输出极性和占空比(比较值)。

    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;        // PWM 模式 1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 499;                     // 比较值(占空比 50%)
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 输出极性为高有效
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);                 // 配置 TIM3 通道 1

    占空比计算

    • 占空比(%) = (比较值 / (自动重装载值 + 1)) × 100%
    • 例如,比较值为 499,占空比约为 50%。
  5. 启动定时器:使能定时器计数和 PWM 输出。

    TIM_Cmd(TIM3, ENABLE);  // 使能 TIM3
    // 对于高级定时器(如 TIM1、TIM8),需要使能 PWM 输出:TIM_CtrlPWMOutputs(TIM3, ENABLE);

4. 示例:使用 TIM3 产生 PWM 信号

以下是完整的代码示例,演示如何使用 TIM3 通道 1 (PA6) 产生占空比为 50% 的 PWM 信号。

#include "stm32f10x.h"

void PWM_Init(void) {
    // 1. 使能时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);    // 使能 TIM3 时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   // 使能 GPIOA 时钟

    // 2. 配置 GPIOA Pin6 为复用推挽输出
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;           // PA6
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;     // 复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   // 速度 50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 3. 初始化定时器
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 999;                 // 自动重装载值(ARR)
    TIM_TimeBaseStructure.TIM_Prescaler = 71;               // 预分频器(PSC)
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // 4. 配置 PWM 模式
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;        // PWM 模式 1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 输出使能
    TIM_OCInitStructure.TIM_Pulse = 499;                     // 比较值(占空比 50%)
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 高电平有效
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);                 // 配置 TIM3 通道 1

    // 5. 启动定时器
    TIM_Cmd(TIM3, ENABLE);  // 使能定时器
}

int main(void) {
    PWM_Init();  // 初始化 PWM

    while (1) {
        // 主循环,可在此调整占空比等参数
    }
}

调整占空比

在实际应用中,可能需要动态调整 PWM 的占空比。例如,通过改变比较值 TIM_OCInitStructure.TIM_Pulse,可以调整输出信号的占空比。

示例:

void Set_PWM_DutyCycle(uint16_t duty) {
    if (duty <= 999) {
        TIM_SetCompare1(TIM3, duty);  // 设置 TIM3 通道 1 的比较值
    }
}

// 在主循环中调用
int main(void) {
    PWM_Init();  // 初始化 PWM

    while (1) {
        for (uint16_t i = 0; i <= 999; i++) {
            Set_PWM_DutyCycle(i);  // 增加占空比
            Delay(1);              // 自定义延时函数
        }
        for (uint16_t i = 999; i > 0; i--) {
            Set_PWM_DutyCycle(i);  // 减小占空比
            Delay(1);
        }
    }
}

注意: Delay() 为自定义的延时函数,需要根据具体情况实现。

5. 注意事项

  • GPIO 引脚选择:确保所选的 GPIO 引脚支持定时器的 PWM 功能,不同的定时器通道对应的 GPIO 详见 STM32F103 的数据手册。
  • 定时器时钟源:定时器的时钟频率受 APB 总线的预分频影响,需要确认定时器实际工作频率。
  • 高级定时器:对于高级定时器(如 TIM1、TIM8),在使能定时器后还需要使能 PWM 输出:
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
  • 占空比范围:占空比的比较值应在 0TIM_Period 范围内。
最后更新于 2024-11-17