dufaxing To be a better man

STM32定时器配置

2017-10-20


把STM32F10X的主频调为72MHz后,为了测试时钟是否配置正确,用定时器生成PWM波,测量PWM波的周期是否与配置的一致。

配置定时器的一般步骤

void TIMER_cfg()配置

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  • 1.重新将Timer设置为缺省值
    TIM_DeInit(TIM2);

  • 2.采用内部时钟给TIM2提供时钟源
    TIM_InternalClockConfig(TIM2);

  • 3.预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz
    TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;

  • 4设置时钟分割
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

  • 5.设置计数器模式为向上计数模式
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  • 6.设置计数溢出大小,每计2000个数就产生一个更新事件
    TIM_TimeBaseStructure.TIM_Period = 2000 - 1;

  • 7.将配置应用到TIM2中
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);

  • 8.清除溢出中断标志
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);

  • 9.禁止ARR预装载缓冲器
    TIM_ARRPreloadConfig(TIM2, DISABLE);

  • 10.开启TIM2的中断
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

void NVIC_cfg()配置

NVIC_InitTypeDef NVIC_InitStructure;

  • 1.选择中断分组1
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

  • 2.选择TIM2的中断通道
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel;

  • 3.抢占式中断优先级设置为0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  • 4.响应式中断优先级设置为0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  • 5.使能中断
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);

实际使用的定时器配置

在我使用的框架中实际代码如下:

VOID HwTim_100msEnable()
{
    TIM_TimeBaseInitTypeDef INIT = {0};
    RCC_ClocksTypeDef       Clock;
    USHORT                  Frequency = 0;  //hz
    TRACESTACK(HwTim_100msEnable);

    RCC_GetClocksFreq(&Clock);

    TIM_DeInit(TIM7);
    //100ms
    Frequency = 10;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
    INIT.TIM_Period = Clock.PCLK1_Frequency*2/1000/Frequency - 1;   //APB1时钟分频>1,定时器输入频率*2
    INIT.TIM_Prescaler = 1000 - 1;//设置预分频系数,计数器时钟为72MHz/1000 = 72kHz
    INIT.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
    INIT.TIM_CounterMode = TIM_CounterMode_Up;        
    TIM_TimeBaseInit(TIM7, &INIT);
    TIM_ClearFlag(TIM7,TIM_FLAG_Update);
    TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
    TIM_Cmd(TIM7, ENABLE);
    HwIrq_Enable(TIM7_IRQn,2,0x03,ENABLE);

    return;
}

其中Clock.PCLK1_Frequency为系统时钟的2分频,这种配置方法可移植性非常高,代码简洁明了。
Frequency = 10;
INIT.TIM_Period = Clock.PCLK1_Frequency*2/1000/Frequency - 1;
INIT.TIM_Prescaler = 1000 - 1;
如上三行代码配置了100ms的计数值和计数时间。 计数频率 = 系统时钟频率/分频系数 = SYSCLK/INIT.TIM_Prescaler
计数次数 = NIT.TIM_Period = Clock.PCLK1_Frequency*2/1000/Frequency - 1;
定时器计时时间 = 单位计数时间 × 计数次数

如果系统时钟为24MHz:
计数次数 = 12M*2/1000/Frequency - 1 = 2.4K
计数频率 = 24M/INIT.TIM_Prescaler = 24k
定时时间 = 计数次数/计数频率 = 0.1S.

如果系统时钟为72MHz
计数次数 = 36M*2/1000/Frequency - 1 = 7.2K
计数频率 = 72M/INIT.TIM_Prescaler = 72k
定时时间 = 计数次数/计数频率 = 0.1S.

这种配置方法及时更改了系统时钟,也不会影响到定时器的配置。

若要配置其他时钟更改计数次数和计数频率即可。

生成的波形如下图所示:



Comments

Content