打印

定时器计数之怪状

[复制链接]
1729|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
siatliuliu|  楼主 | 2011-8-3 10:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 siatliuliu 于 2011-8-3 10:36 编辑


平台:火牛开发板STM32F103VBT6  MDK3.8
功能:
1.TIM1 PWM2方式产生频率变化的脉冲
2.TIM2定时每5ms 在更新中断中改变TIM1的频率(ARR),打印出TIM1在上一个5ms周期里的脉冲数。

现象及问题:
通过示波器可以看到:TIM1输出脉冲每隔5ms 频率按设定的频率变化,问题是计数不准确(如下)。

第n周期   第1&2方式脉冲数  第3方式脉冲数  理论脉冲数   TIM1频率
nStep : 1, pulseNum : 6        506             10          2k
nStep : 2, pulseNum : 11        21             20          4k
nStep : 3, pulseNum : 21        46             40          8k   
nStep : 4, pulseNum : 42        92             80         16k  
nStep : 5, pulseNum : 47       128             90         18k   
nStep : 6, pulseNum : 52       142            100         20k   
nStep : 7 ,pulseNum : 78       187            150         30k   
nStep : 8, pulseNum : 104      263            200         40k  
nStep : 9, pulseNum : 125      337            250         50k  
nStep : 0, pulseNum : 250      680            500        100k

计数方式:
1.在TIM1的更新中断里计数(算不上严格意义上的计数,只是验证一下)
/* * @file TIM/
/stm32f10x_it.c  **************************************************************/
#include "stm32f10x_it.h"

//对应频率:2k, 4k, 8k, 16k, 18k, 20k, 30k, 40k, 50k, 100k
uint16_t ARR_Buffer[10] = {36000, 18000, 9000, 4500, 4000, 3600, 2400, 1800, 1440, 720};

u32 nStep= 0 ;
u32 pulseNum = 0;


//TIM1 计脉冲数
void TIM1_UP_IRQHandler(void)
{  if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)
  {
      TIM_ClearITPendingBit(TIM1, TIM_IT_Update );
      pulseNum++;                         //计脉冲数
  }
}

//TIM2 5ms中断计时, 更改TIM1频率,打印上一阶段脉冲数
void TIM2_IRQHandler(void){
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update );
           TIM1->CCR1 =  ARR_Buffer[nStep] / 2;     //更改TIM1占空比
           TIM1->ARR =   ARR_Buffer[nStep];         //更改TIM1脉冲频率
          printf("\nnStep : %d,pulseNum : %d\n", nStep, pulseNum);  //打印上个5ms TIM1的脉冲数

        pulseNum = 0;                      //脉冲数清零
        nStep++;                           

        if(nStep >9)                       //10个一循环
           nStep = 0;
  }
}                                                                  




/* main.c *********************************************************************************/

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
TIM_ICInitTypeDef  TIM_ICInitStructure;
ErrorStatus HSEStartUpStatus;

int main(void)
{
  /* System Clocks Configuration */
  RCC_Configuration();

  /* GPIO Configuration */
  GPIO_Configuration();

  NVIC_Configuration();

/*USART Configuration */
    COM_Init();

  /* TIM1 Peripheral Configuration --------------------------------------------*/
  /* Time Base configuration */
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = 36000;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /* Channel 3 Configuration in PWM mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 18000;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

  TIM_OC1Init(TIM1, &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
  TIM_ARRPreloadConfig(TIM1, ENABLE);

  //TIM2产生5ms中断计时。
  TIM_DeInit(TIM2);

  TIM_TimeBaseStructure.TIM_Period = 7199;
  TIM_TimeBaseStructure.TIM_Prescaler = 24;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);


  TIM_CCPreloadControl(TIM1, ENABLE);

  TIM_ClearFlag(TIM1, TIM_FLAG_Update);
  TIM_ClearFlag(TIM2, TIM_FLAG_Update);

   TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
   TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);


  /* TIM1 counter enable */
  TIM_Cmd(TIM1, ENABLE);
  TIM_Cmd(TIM2, ENABLE);


  /* Main Output Enable */
  TIM_CtrlPWMOutputs(TIM1, ENABLE);

  while (1)
  {}
}

方式2:输入捕获计数。TIM1 Chanel1 接至 TIM2 Channel2, TIM2 Channel2 在输入捕获中断中计数
在TIM2_IRQHandler()中加入下面代码
  if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)
  {    TIM_ClearITPendingBit(TIM2, TIM_IT_CC2 );
          pulseNum++;
  }


方式3:外部时钟模式2.TIM1 Channel1作为TIM3的外部时钟。
    TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
    TIM_TimeBaseStructure.TIM_Prescaler = 0x00;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_ETRClockMode2Config(TIM3, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);
    TIM_SetCounter(TIM3, 0);
/****************************** stm32f10x_it.c **********************************/
void TIM2_IRQHandler(void){
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
  {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update );

        pulseNum  = TIM_GetCounter(TIM3);
        TIM_SetCounter(TIM3, 0);

        printf("\nnStep : %d,pulseNum : %d\n", nStep, pulseNum);

        TIM1->CCR1 =  ARR_Buffer[nStep] / 2;
        TIM1->ARR =   ARR_Buffer[nStep];
        TIM_GenerateEvent(TIM1, TIM_EventSource_Update);

        nStep++;
        if(nStep >9)
           nStep = 0;

  }



沙发
siatliuliu|  楼主 | 2011-8-3 10:36 | 只看该作者
请达人指点,不知道问题出在何处

使用特权

评论回复
板凳
香水城| | 2011-8-3 11:20 | 只看该作者
1)需要确认晶振的频率是否准确
2)需要确认示波器的计量是否准确
3)要对照示波器上脉冲数目是否与程序中计数一致

使用特权

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

本版积分规则

0

主题

3

帖子

0

粉丝