STM32的hal库与标准库定时器输出PWM波区别

HAL库

void PWM_Init(void) {
    __HAL_RCC_TIM3_CLK_ENABLE(); // 启用 TIM3 时钟
    __HAL_RCC_GPIOA_CLK_ENABLE(); // 启用 GPIOA 时钟

    // 配置 GPIOA PIN6 为 TIM3 CH1 输出
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF_TIM3;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 配置 TIM3
    TIM_HandleTypeDef htim3 = {0};
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 8399; // 10kHz
    htim3.Init.Period = 999; // 1kHz
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    HAL_TIM_PWM_Init(&htim3);

    // 配置 TIM3 CH1 为 PWM 输出
    TIM_OC_InitTypeDef sConfigOC = {0};
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 500; // 占空比 50%
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);

    // 启动 PWM
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
}

标准库

#include "stm32f4xx.h"

void PWM_Init(void) {
    // 1. 启用时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  // TIM3 时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // GPIOA 时钟

    // 2. 配置 GPIOA PIN6 为 TIM3 CH1 PWM 输出
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置 GPIO 复用功能
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM3);

    // 3. 配置 TIM3 时基
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Prescaler = 8399;            // 10kHz (假设系统时钟为 84MHz)
    TIM_TimeBaseStructure.TIM_Period = 999;                // PWM 频率 1kHz
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // 4. 配置 TIM3 CH1 PWM 输出
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;      // PWM 模式 1
    TIM_OCInitStructure.TIM_Pulse = 500;                  // 占空比 50%
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);              // 应用到 CH1

    // 5. 启动 TIM3
    TIM_Cmd(TIM3, ENABLE);

    // 6. 启用 TIM3 CH1 PWM 输出
    TIM_CtrlPWMOutputs(TIM3, ENABLE);  // 启用高级功能输出
}

1. 定时器时钟初始化

HAL 库 SPL
__HAL_RCC_TIMx_CLK_ENABLE(); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIMx, ENABLE);
作用:
  • 开启对应定时器的时钟。
  • HALSPL 的实现类似,差别仅在命名的简洁性
  •  

    2. 配置定时器为 PWM 模式

    HAL 库 SPL
    ```c ```c
    TIM_OC_InitTypeDef sConfigOC = {0}; TIM_OCInitTypeDef TIM_OCInitStructure;
    sConfigOC.OCMode = TIM_OCMODE_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    sConfigOC.Pulse = 500; TIM_OCInitStructure.TIM_Pulse = 500;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_1); TIM_OC1Init(TIMx, &TIM_OCInitStructure);
    ``` ```
    作用:
  • HAL 库
  • 使用 TIM_OC_InitTypeDef 配置输出比较模式,并通过 HAL_TIM_PWM_ConfigChannel 应用到定时器。
  • 配置简洁,统一管理 PWM 通道。
  • SPL
  • 使用 TIM_OCInitTypeDef 配置 PWM 输出模式,并手动调用 TIM_OCxInit 函数(如 TIM_OC1Init)。
  • 灵活性高,但需要手动针对每个通道初始化。
  •  

    3. 配置定时器参数

    HAL 库 SPL
    ```c ```c
    TIM_HandleTypeDef htimx; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    htimx.Instance = TIMx; TIM_TimeBaseStructure.TIM_Prescaler = 8399;
    htimx.Init.Prescaler = 8399; TIM_TimeBaseStructure.TIM_Period = 999;
    htimx.Init.Period = 999; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    htimx.Init.CounterMode = TIM_COUNTERMODE_UP; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    HAL_TIM_PWM_Init(&htimx); TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);
    ``` ```
    作用:
  • HAL 库
  • 使用 TIM_HandleTypeDef 统一管理定时器实例和初始化参数,代码清晰。
  • SPL
  • 分离时基配置(TIM_TimeBaseInit)和 PWM 输出配置(TIM_OCInit),需要更多代码来完成初始化。
  •  

    4. 开启 PWM 输出

    HAL 库 SPL
    HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_1); TIM_Cmd(TIMx, ENABLE);
    TIM_CCxCmd(TIMx, TIM_Channel_1, ENABLE);
    作用:
  • HAL 库
  • 调用 HAL_TIM_PWM_Start 启动指定通道的 PWM 输出。
  • 代码简洁,函数内部自动完成相关设置。
  • SPL
  • 使用 TIM_Cmd 启动定时器,并通过 TIM_CCxCmd 启用对应通道。
  • 更接近硬件,需要手动调用多个函数
  • 5. GPIO 引脚配置

    HAL 库 SPL
    ```c ```c
    GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStruct.Pin = GPIO_PIN_x; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.Alternate = GPIO_AF_TIMx; GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_TIMx);
    HAL_GPIO_Init(GPIOx, &GPIO_InitStruct); GPIO_Init(GPIOx, &GPIO_InitStructure);
    ``` ```
    作用:
  • 配置定时器的 GPIO 输出引脚。
  • 两者基本相同,HAL 库通过 Alternate 字段配置复用功能,而 SPL 使用 GPIO_PinAFConfig 设置复用功能。
  •  

    6. 中断(可选)

    如需使用 PWM 输出时的中断功能:

    HAL 库 SPL
    使用回调函数: 手动配置中断:
    ```c ```c
    void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { void TIMx_IRQHandler(void) {
    if (htim->Instance == TIMx) { if (TIM_GetITStatus(TIMx, TIM_IT_Update)) {
    // PWM 完成事件处理 TIM_ClearITPendingBit(TIMx, TIM_IT_Update);
    } // PWM 完成事件处理
    } }
    ``` ```

    作者:荔枝litchi.

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32的hal库与标准库定时器输出PWM波区别

    发表回复