|
|
#include "pwm_control.h"
#include <cstdio>
#include <main.h>
#include "stm32f4xx_hal.h"
// 全局变量,用于存储频率和占空比
volatile uint32_t pwm_frequency = 1000; // 默认频率为1000Hz
volatile uint8_t pwm_duty_cycle = 50; // 默认占空比为50%
// 定时器句柄
TIM_HandleTypeDef htim;
// 定义定时器和通道
#define TIMx TIM4
#define TIMx_CLK_ENABLE __HAL_RCC_TIM4_CLK_ENABLE()
#define GPIOx GPIOD
#define GPIOx_CLK_ENABLE __HAL_RCC_GPIOD_CLK_ENABLE()
// 根据通道选择对应的定时器通道
uint32_t Get_TIM_Channel(PWM_Channel_TypeDef channel) { switch (channel) { case PWM_PUMP_PUL: return TIM_CHANNEL_1; case PWM_LASER: return TIM_CHANNEL_2; case PWM_GY: return TIM_CHANNEL_3; default: return 0; } }
// 根据通道选择对应的GPIO引脚
uint32_t Get_GPIO_Pin(PWM_Channel_TypeDef channel) { switch (channel) { case PWM_PUMP_PUL: return GPIO_PIN_12; case PWM_LASER: return GPIO_PIN_13; case PWM_GY: return GPIO_PIN_14; default: return 0; } }
// 初始化定时器和GPIO
void TIM_PWM_Init(void) { #if 0
TIM_OC_InitTypeDef sConfigOC = {0};
// 使能GPIO和定时器时钟
GPIOx_CLK_ENABLE; TIMx_CLK_ENABLE;
// 配置GPIO引脚为复用功能
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF2_TIM4; HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
// 配置定时器
htim.Instance = TIMx; htim.Init.Prescaler = 0; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 0; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; HAL_TIM_PWM_Init(&htim);
// 配置PWM通道
sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2); HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_3);
// 启动PWM输出
HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_3); #else
TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0};
// 使能GPIO和定时器时钟
GPIOx_CLK_ENABLE; TIMx_CLK_ENABLE;
// 配置GPIO引脚为复用功能
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF2_TIM4; HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
// 配置定时器
htim.Instance = TIM4; htim.Init.Prescaler = 32; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 1000; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&htim) != HAL_OK) { Error_Handler(); }
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim, &sClockSourceConfig) != HAL_OK) { Error_Handler(); }
if (HAL_TIM_PWM_Init(&htim) != HAL_OK) { Error_Handler(); }
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig) != HAL_OK) { Error_Handler(); }
sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } if (HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); }
// 启动PWM输出
HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_2); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_3); #endif
}
// 更新指定通道的PWM频率和占空比
void Update_PWM(PWM_Channel_TypeDef channel, uint32_t frequency, uint8_t duty_cycle) { #if 0
if (frequency == 0) { if (duty_cycle == 0) { // 关闭定时器,GPIO输出0
uint32_t tim_channel = Get_TIM_Channel(channel); uint32_t gpio_pin = Get_GPIO_Pin(channel); HAL_TIM_PWM_Stop(&htim, tim_channel); HAL_GPIO_WritePin(GPIOx, gpio_pin, GPIO_PIN_RESET); } else if (duty_cycle == 100) { // GPIO输出1
uint32_t tim_channel = Get_TIM_Channel(channel); uint32_t gpio_pin = Get_GPIO_Pin(channel); HAL_TIM_PWM_Stop(&htim, tim_channel); HAL_GPIO_WritePin(GPIOx, gpio_pin, GPIO_PIN_SET); } } else { // 计算定时器的周期和脉冲宽度
uint32_t timer_clock = HAL_RCC_GetPCLK1Freq() * 2; // TIM4挂载在APB1总线上,APB1预分频器为2时,定时器时钟为APB1时钟的2倍
uint32_t prescaler = (timer_clock / (frequency * 1000)) - 1; uint32_t period = 1000; uint32_t pulse = (period * duty_cycle) / 100;
// 配置定时器参数
htim.Instance->CR2 &= 0x00; htim.Instance->PSC = prescaler; htim.Instance->ARR = period;
uint32_t tim_channel = Get_TIM_Channel(channel); switch (tim_channel) { case TIM_CHANNEL_1:
htim.Instance->CCR1 = pulse; HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); break; case TIM_CHANNEL_2: htim.Instance->CCR2 = pulse; HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_2); break; case TIM_CHANNEL_3: htim.Instance->CCR3 = pulse; HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_3); break; } htim.Instance->CR2 &= 0x00; } #else
// 计算定时器的周期和预分频器
uint32_t timer_clock = HAL_RCC_GetPCLK1Freq() * 2; // TIM4挂载在APB1总线上,APB1预分频器为2时,定时器时钟为APB1时钟的2倍
uint32_t prescaler = (timer_clock / (frequency * 1000)) - 1; uint32_t period = 999; // 固定周期为999,通过调整预分频器实现频率变化
uint32_t tim_channel = Get_TIM_Channel(channel); uint32_t pulse = (period * duty_cycle) / 100; // HAL_TIM_PWM_Stop(&htim, tim_channel);
// TIM_OC_InitTypeDef sConfigOC;
// htim.Init.Period = period;
// sConfigOC.Pulse = pulse;
// sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
// sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
// HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, channel);
// HAL_TIM_PWM_Start(&htim, tim_channel);
// htim.Instance->CR2 &= 0x00;
// htim.Instance->PSC = prescaler;
// htim.Instance->ARR = period;
// htim.Instance->CCR1 = pulse;
// htim.Instance->CCR2 = pulse;
// htim.Instance->CCR3 = pulse;
__HAL_TIM_SET_PRESCALER(&htim, prescaler); __HAL_TIM_SET_AUTORELOAD(&htim, period); __HAL_TIM_SET_COMPARE(&htim, tim_channel, pulse); // 触发更新事件
HAL_TIM_GenerateEvent(&htim, TIM_EVENTSOURCE_UPDATE);
#endif
}
|