WarisonLegency 2024-12-26 14:22 采纳率: 0%
浏览 17

定时器门控或者主从产生固定个数PWM有尖峰出现

各位朋友,最近调互补PWM遇到的问题,首先是使用的STM32F030C8T6,然后是TIM1为主定时器,TIM3为从定时器,进行固定数量的PWM波产生,但是我发现,每次波形结束都会有个小的尖峰,问问有没有办法解决。

img

void Master_PWM_Init(uint32_t TimerPsc,uint32_t TimerArr){
    GPIO_InitTypeDef GPIO_InitStructure; 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;    
    TIM_OCInitTypeDef TIM_OCInitStructure;
    
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);              
  /* 
        GPIOA Configuration:
     - TIM1_CH1P pin (PA.08)  
     - TIM1_CH1N pin (PA.07) 
    */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2);  //TIM1_CH1P
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_2); //TIM1_CH1N

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = TimerArr-1;
    TIM_TimeBaseStructure.TIM_Prescaler = TimerPsc-1;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
    TIM_InternalClockConfig(TIM1);
    
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_Pulse = TimerArr/2;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
    //空闲状态下都变成低电平
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    
    TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
    //TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_OC1);
    TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable);
    //TIM_SelectOnePulseMode(TIM1,TIM_OPMode_Single);

    
    TIM_ARRPreloadConfig(TIM1, ENABLE); //Enable:修改ARR值(周期值)会在当前周期就变了,Disable:修改ARR值(周期值)会在下一周期生效;
    TIM_OC1PreloadConfig(TIM1, ENABLE); //Enable:下一次更新事件时被更新;Disable:立即生效
    
    TIM_Cmd(TIM1, DISABLE);
  TIM_CtrlPWMOutputs(TIM1, DISABLE);
}
void Slave_TIM3_Init(uint32_t PulseNum){
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    TIM_TimeBaseStructure.TIM_Period = PulseNum-1;   
    TIM_TimeBaseStructure.TIM_Prescaler =0;    
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;     
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    TIM_InternalClockConfig(TIM3);
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;        
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
        
    TIM_SelectInputTrigger(TIM3, TIM_TS_ITR0);    
    //TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Gated);
    TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_External1);
    TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);
    TIM_Cmd(TIM3,DISABLE);
}
void Accurate_PWM_NumOutput(uint32_t TimerPsc,uint32_t TimerArr,uint32_t PulseNum){
    Slave_TIM3_Init(PulseNum);
    TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
    TIM_Cmd(TIM3, ENABLE);

    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);    

    Master_PWM_Init(TimerPsc,TimerArr);
    
    TIM_Cmd(TIM1, ENABLE);
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
void TIM3_IRQHandler(void){
    if(TIM_GetITStatus(TIM3,TIM_IT_Update)){
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
        TIM_Cmd(TIM3, DISABLE);
        TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);
        TIM_Cmd(TIM1, DISABLE);
        TIM_CtrlPWMOutputs(TIM1, DISABLE);
    }
}


  • 写回答

2条回答 默认 最新

  • 码农阿豪@新空间 新星创作者: 前端开发技术领域 2024-12-26 14:33
    关注
    让阿豪来帮你解答,本回答参考chatgpt3.5编写提供,如果还有疑问可以评论或留言
    对于波形最后出现的小尖峰问题,可能是由于定时器计数器溢出导致的。在每个PWM波周期结束时,定时器计数器会归零,若在归零的瞬间发生输出引脚电平变化,可能会导致小尖峰。解决方法可以通过调整定时器的初始化参数或者在中断处理函数中进行一定的处理。 一种可能的解决方法是在每个PWM波周期结束时添加一些延时操作,等待定时器计数器归零后再改变输出引脚电平。具体的延时时间可以根据实际情况进行调整。 另一种解决方法是在定时器中断处理函数中进行输出引脚状态的切换。在定时器计数器溢出时,先停止输出引脚的PWM信号,等定时器归零后再重新开始输出PWM信号。 下面是伪代码示例:
    // 在定时器中断处理函数中实现输出引脚电平的切换
    void TIM3_IRQHandler() {
        if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) {
            // 停止输出PWM信号
            TIM_CtrlPWMOutputs(TIM1, DISABLE);
            // 等待定时器计数器归零
            while (TIM_GetFlagStatus(TIM3, TIM_FLAG_Update) == RESET);
            // 重新开始输出PWM信号
            TIM_CtrlPWMOutputs(TIM1, ENABLE);
            TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
        }
    }
    // 主定时器初始化
    void Master_PWM_Init(uint32_t TimerPsc, uint32_t TimerArr){
        // 初始化定时器
        // 配置输出引脚等
    }
    // 从定时器初始化
    void Slave_TIM3_Init(uint32_t PulseNum){
        // 初始化定时器
        // 配置定时器中断
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    }
    

    在以上示例中,通过在定时器中断处理函数中,停止输出PWM信号并等待定时器归零后重新开始输出,可以避免小尖峰的产生。具体的延时时间和处理流程可以根据实际情况进行调整。

    评论

报告相同问题?

问题事件

  • 创建了问题 12月26日