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); |
作用:
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); |
``` | ``` |
作用:
TIM_OC_InitTypeDef
配置输出比较模式,并通过 HAL_TIM_PWM_ConfigChannel
应用到定时器。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); |
``` | ``` |
作用:
TIM_HandleTypeDef
统一管理定时器实例和初始化参数,代码清晰。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_TIM_PWM_Start
启动指定通道的 PWM 输出。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); |
``` | ``` |
作用:
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.