基质喷涂
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

#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);
}