打印
[STM32F1]

STM32比较输出方波,频率超过40KHz之后波形紊乱

[复制链接]
3387|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
给位前辈,我在利用STM32同一个定时器比较输出模式产生4路不同的频率方波的实验中,遇到一个问题,请教各位:
思路:使用TIM3的比较输出,设置输出自动翻转,在中断中更新CCR寄存器,
          u32 PWM_M[8];                // 高频率PWM输出比较值,用来更新CCR寄存器
现象1:当新的比较值PWM_M[n]=300左右,即输出频率为40KHz后,波形紊乱(会有较长时间的高低电平,同时会夹杂着40KHz的波形)
现象2:修改TIM_TimeBaseStructure.TIM_Prescaler = 2为5后,更改PWM_M[n]=150,发现40KHz波形正确,但是PWM_M[n]继续调小增大波形后,在60KHz左右波形再次紊乱
           修改TIM_TimeBaseStructure.TIM_Prescaler = 5为11后,更改PWM_M[n]可以调出60KHz的波形,但是100KHz左右波形再次紊乱。

问题:理论上100khz的中断频率程序处理起来应该没问题,不知道为何我这个程序输出会紊乱;TIM_Prescaler不知道为何对输出有上述影响?请各位不吝赐教。



下面为程序片段
/*******************************************************************************
* Function Name  : RCC_Configuration
* Description    : Configures the different system clocks.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void RCC_Configuration(void)
{   
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);
       
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1);

    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div16);
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);

    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

    /* Enable PLL */
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
   /* Enable TIM1 clock */
  RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  /* Enable DMA1 clock */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  /* Enable ADC1 clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1  | RCC_APB2Periph_USART1, ENABLE);// 使能需要使用的IO时钟
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
}
/*******************************************************************************
//
//                设置定时器通道的输出比较值   比较输出方式  对应高频率
//
*******************************************************************************/
void PWM_Output_TIMx_Config(TIM_TypeDef* TIMx)
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        TIM_OCInitTypeDef  TIM_OCInitStructure;

        TIM_TimeBaseStructure.TIM_Period = 65535;
    TIM_TimeBaseStructure.TIM_Prescaler = 2;                                // 24M          
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;                                 // channel-1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OCInitStructure.TIM_Pulse = 0;                                               
        TIM_OC1Init(TIMx, &TIM_OCInitStructure);
        TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Disable);

    TIM_OCInitStructure.TIM_Pulse = 0;                                                                 // channel-2
    TIM_OC2Init(TIMx, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Disable);

    TIM_OCInitStructure.TIM_Pulse = 0;                                                                 // channel-3
    TIM_OC3Init(TIMx, &TIM_OCInitStructure);
    TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Disable);

    TIM_OCInitStructure.TIM_Pulse = 0;                                                                 // channel-4
    TIM_OC4Init(TIMx, &TIM_OCInitStructure);
    TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Disable);

    TIM_Cmd(TIMx, ENABLE);
}


//==========================
//
//        高速脉冲定时器中断 通道1-4
//
//==========================
void TIM3_IRQHandler(void)
{
        u16 capture = 0;
//        OS_ENTER_CRITICAL();                         // 关中断         

    if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 );
        capture = TIM_GetCapture1(TIM3);
        TIM_SetCompare1(TIM3, capture + PWM_M[0]);      
    }

    if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
        capture = TIM_GetCapture2(TIM3);
        TIM_SetCompare2(TIM3, capture + PWM_M[1]);         
    }

    if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
        capture = TIM_GetCapture3(TIM3);
        TIM_SetCompare3(TIM3, capture + PWM_M[2]);
        //        PWM_OUT2;            
    }

    if (TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET)
    {
        TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
        capture = TIM_GetCapture4(TIM3);
        TIM_SetCompare4(TIM3, capture + PWM_M[3]);     
    }
//   OS_EXIT_CRITICAL();                                                         // 开中断
}


沙发
airwill| | 2014-4-8 14:08 | 只看该作者
这种问题, 通常是因为更改了 CCR 以后, 同一个周期中再次发生比较中断引起的.

可以考虑使用预装载寄存器和更新事件来更新的办法解决.
当然软件也会相应要变化.

使用特权

评论回复
板凳
chb080042|  楼主 | 2014-4-9 11:34 | 只看该作者
是不是中断太频繁了,影响到程序了呢?

使用特权

评论回复
地板
airwill| | 2014-4-9 16:16 | 只看该作者
不是, 举例吧, 假如你的 CCR1=1, PWM_M=150, ARR = 900.

运行中, CNT =1 时中断了. 中断服务将 CCR1改为了 151. 此时 CNT 的值也许才到90中断就退出了, 当 CNT 到 151 的时候, 又发生比较中断. 这个时候, 间隔才 150, 按 36MHz 算, 过了才 4.17uS.
由此, 下面再过 4.17uS 又可能发生翻转, 这样便出现了杂波了.

使用特权

评论回复
5
chb080042|  楼主 | 2014-4-9 17:38 | 只看该作者
如果PWM_M=150,那么4.17uS翻转是对的呀。
附件贴了一个70KHz的波形图,其中密集的那部分是70khz的波形,其他的好像是按照65535翻转一次的波形

30khz-C1-C5.jpg (108.05 KB )

30khz-C1-C5.jpg

使用特权

评论回复
6
chb080042|  楼主 | 2014-4-10 09:58 | 只看该作者
试过了DMA方式,倒是可以得到很好的100khz波形

使用特权

评论回复
7
icecut| | 2014-4-10 13:45 | 只看该作者
100K次中断已经是很高的频率了.

使用特权

评论回复
8
adssee| | 2023-5-6 10:04 | 只看该作者
chb080042 发表于 2014-4-10 09:58
试过了DMA方式,倒是可以得到很好的100khz波形

楼主的例程可以借鉴下吗

使用特权

评论回复
9
langgq| | 2023-5-15 19:48 | 只看该作者
更改了 CCR 以后, 同一个周期中再次发生比较中断

使用特权

评论回复
10
hanwe| | 2023-5-15 19:50 | 只看该作者
可以考虑使用预装载寄存器和更新事件来更新的办法解决.

使用特权

评论回复
11
llljh| | 2023-5-15 19:52 | 只看该作者
中断太频繁了

使用特权

评论回复
12
zhuhuis| | 2023-5-15 19:54 | 只看该作者
影响到程序了

使用特权

评论回复
13
tian111| | 2023-5-15 19:56 | 只看该作者
4.17uS翻转是对的

使用特权

评论回复
14
hanwe| | 2023-5-15 19:58 | 只看该作者
100K次中断已经是很高的频率了.

使用特权

评论回复
15
dingy| | 2023-5-15 19:59 | 只看该作者
楼主的例程可以借鉴下吗

使用特权

评论回复
16
帛灿灿| | 2024-3-8 07:20 | 只看该作者

它是由两个尺寸相同、匝数相同的线圈对称地绕制在同一个铁氧体环形磁芯

使用特权

评论回复
17
周半梅| | 2024-3-8 10:19 | 只看该作者

这种电路结构的特点是:由四只相同的开关管接成电桥结构驱动脉冲变压器原边。

使用特权

评论回复
18
童雨竹| | 2024-3-8 13:18 | 只看该作者

模块电源灌封操作之所以重要,主要是由于其涉及到模块电源的防护及热设计

使用特权

评论回复
19
Wordsworth| | 2024-3-8 14:21 | 只看该作者

得到不同测试条件下的输出电流和电压值,分析数据并进行比较

使用特权

评论回复
20
Clyde011| | 2024-3-8 15:24 | 只看该作者

这样可以获得更光滑的表面。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

8

帖子

0

粉丝