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

物联沃分享整理
物联沃-IOTWORD物联网 » STM32使用主从定时器实现移相全桥(HAL库)

发表回复