STM32使用主从定时器实现移相全桥(HAL库)
自己做个记录
对于F103或者F405这些不带非对称模式的芯片,需要使用传统的主从定时器实现移相全桥。
代码:结构体
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim8;
I/O初始化
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1 )
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_TIM1_CLK_ENABLE(); /* 开启定时器X时钟 */ /* 开启定时器X时钟 */
gpio_init_struct.Pin = GPIO_PIN_8; /* 通道Tim1 ch1的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 高速 */
gpio_init_struct.Alternate = GPIO_AF1_TIM1; /* IO复用为定时器功能 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 初始化IO */
gpio_init_struct.Pin = GPIO_PIN_13; /* 通道Tim1 ch1n的GPIO口 */
HAL_GPIO_Init(GPIOB, &gpio_init_struct); /* 初始化IO */ /* 初始化IO */
}
if (htim->Instance == TIM8 )
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_TIM8_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_6; /* 通道Tim1 ch1的GPIO口 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLDOWN; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; /* 高速 */
gpio_init_struct.Alternate = GPIO_AF3_TIM8; /* IO复用为定时器功能 */
HAL_GPIO_Init(GPIOC, &gpio_init_struct); /* 初始化IO */
gpio_init_struct.Pin = GPIO_PIN_7; /* 通道Tim1 ch1n的GPIO口 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 初始化IO */
}
}
定时器初始化:
void atim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
{
TIM_OC_InitTypeDef g_timx_oc_pwm_chy = {0}; /* 定时器PWM输出配置 */
TIM_OC_InitTypeDef shift_pwm_chy = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/*
使用TIM1,TIM8定时器进行移相
全桥配置:
TIM1 CH1 GATE2 TIM8 CH1 GATE2
TIM1 CH1N GATE3 TIM8 CH1N GATE4
TIM1 CH1 TIM8 CH1 使用PWM1模式,实际值小于比较值输出有效电平,有效电平为高电平,占空比设为50%,额外添加死区。
TIM1为主定时器,使用 CH2 的 OC2REF 触发 TIM8定时器重置
TIM8 处于从定时器模式,必须在接受到 OC2REF 高电平的时候才会工作,OC2REF为低,TIM8停止输出。
TIM1 CH2 使用PWM2模式,实际值大于比较值输出有效电平,有效电平为高,触发TIM8启动。
要确保 OC2REF 会拉低,所以CH2的CCR2寄存器最小必须为1,不然无法重置TIM8,更改移相角
要确保 OC2REF 置高的时间必须大于TIM8高电平的时间,所以CCR2值不能大于50%的周期
不要使用PWM ACTIVE模式,此模式下,OC2REF始终为高,无法重置TIM8。
程序中直接修改CCR2值,可以更改移相角。
*/
htim1.Instance = TIM1; /* 定时器1 */
htim1.Init.Prescaler = psc; /* 定时器分频 */
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式*/
htim1.Init.Period = arr; /* 自动重装载值 */
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 时钟分频因子 */
htim1.Init.RepetitionCounter = 0; /* 重复计数0*/
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_PWM_Init(&htim1);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF; /*主定时器,使用OC2REF作为触发*/
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);
g_timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1; /* 模式选择PWM1 */
g_timx_oc_pwm_chy.Pulse = (arr+1)/2-1; /* 设置比较值,此值用来确定占空比50 */
g_timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_timx_oc_pwm_chy.OCIdleState = TIM_OCIDLESTATE_RESET;
g_timx_oc_pwm_chy.OCNPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_timx_oc_pwm_chy.OCNIdleState = TIM_OCIDLESTATE_RESET;
g_timx_oc_pwm_chy.OCFastMode = TIM_OCFAST_ENABLE;
HAL_TIM_PWM_ConfigChannel(&htim1, &g_timx_oc_pwm_chy, TIM_CHANNEL_1); /* 配置TIMx通道y */
sBreakDeadTimeConfig.DeadTime = DEADPULSE; /* 配置死区 */
HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
shift_pwm_chy.OCMode = TIM_OCMODE_PWM2; /* 模式选择PWM2 */
shift_pwm_chy.Pulse = SHIFTBASIC; /* 设置比较值,此值用来确定移相角,最小为1,理论上这里会产生一定的移相角偏差,但是由于死区的关系,问题不大*/
HAL_TIM_PWM_ConfigChannel(&htim1, &shift_pwm_chy, TIM_CHANNEL_2); /* 配置TIMx通道y */
htim8.Instance = TIM8; /* 定时器8 */
htim8.Init.Prescaler = psc; /* 定时器分频 */
htim8.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
htim8.Init.Period = arr; /* 自动重装载值 */
htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 时钟分频因子 */
htim8.Init.RepetitionCounter = 0; /* 重复计数0*/
htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_PWM_Init(&htim8);
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET; /*从定时器,重置模式*/
sSlaveConfig.InputTrigger = TIM_TS_ITR0; /*ITR0为TIM1*/
HAL_TIM_SlaveConfigSynchro(&htim8, &sSlaveConfig);
g_timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1; /* 模式选择PWM1 */
g_timx_oc_pwm_chy.Pulse = (arr+1)/2-1; /* 设置比较值,此值用来确定占空比50%*/
g_timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_timx_oc_pwm_chy.OCIdleState = TIM_OCIDLESTATE_RESET;
g_timx_oc_pwm_chy.OCNPolarity = TIM_OCPOLARITY_HIGH; /* 输出比较极性为高 */
g_timx_oc_pwm_chy.OCNIdleState = TIM_OCIDLESTATE_RESET;
g_timx_oc_pwm_chy.OCFastMode = TIM_OCFAST_ENABLE;
HAL_TIM_PWM_ConfigChannel(&htim8, &g_timx_oc_pwm_chy, TIM_CHANNEL_1); /* 配置TIMx通道y */
sBreakDeadTimeConfig.DeadTime = DEADPULSE; /* 配置死区 */
HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); /* 开启对应PWM通道1 */
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); /* 开启对应PWM通道1N */
HAL_TIM_PWM_Start(&htim8, TIM_CHANNEL_1); /* 开启对应PWM通道1 */
HAL_TIMEx_PWMN_Start(&htim8, TIM_CHANNEL_1); /* 开启对应PWM通道1N */
HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 1, 0); /* 设置中断优先级,抢占优先级1,子优先级0 */
HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); /* 开启ITMx中断 */
HAL_TIM_Base_Start_IT(&htim1);
}
配置参数:
#define PWMARR 8399
#define DEADPULSE 100
#define SHIFTBASIC 1
更改移相角:
htim1.Instance->CCR2=SHIFT; /*SHIFT:0-4199*/
PWM波20kHZ,死区500nS
作者:knightsam