You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
6.0 KiB
185 lines
6.0 KiB
#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) {
|
|
|
|
// 计算定时器的周期和预分频器
|
|
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);
|
|
}
|