#include "pwm_control.h" #include #include #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 }