stm32之TIM-基本定时器应用实例(详细)

  • 开发环境:Window 7
  • 开发工具:Keil uVision4
  • 硬件:STM32F103VCT6

定时器最基本的功能就是定时处理事情。比如定时发送USART数据、定时采集AD数据、定时检测IO口电位、还可以通过IO口输出波形等。可以实现非常丰富的功能。

STM32系列的定时器分为基本定时器、通用定时器、高级控制定时器。后者包括前者的全部功能。所以先掌握基本定时器可以更好理解后面功能繁多的定时器。

通常地,STM32高级定时器TIM1、TIM8,通用定时器TIM2、TIM3、TIM4、TIM5,基本定时器TIM6、TIM7。

有用过STM32的话都知道,STM32所有的外设初始化都是使用标准库里的初始化结构体和初始化函数,下面先说一下IM_TimeBaseInitTypeDef structure 结构体成员的含义。

TIM_TimeBaseInitTypeDef 定义于文件“stm32f10x_tim.h”:

typedef struct 
{ 
u16 TIM_Period; 
u16 TIM_Prescaler; 
u8 TIM_ClockDivision; 
u16 TIM_CounterMode; 
u8 TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
  1. TIM_Period:定时器周期,当计数寄存器的值递增到等于该值时,将相关事件标志位置位。范围0~65535。
  2. TIM_Prescaler:定时器预分频设置。时钟源经该预分频器才是定时器时钟。范围0~65535。
  3. TIM_ClockDivision:时钟分频。基本定时器没有这个功能,无需设置。
  4. TIM_CounterMode:定时器计数方式设置。基本定时器只能向上计数,无需设置。
  5. TIM_RepetitionCounter :重复计数器,基本定时器没有这个功能,无需设置。

虽然定时器初始化结构体有5个成员,但是对于基本定时器只需设置其中两个就可以了。下面是一个定时0.5s翻转IO口电平的例子。

循环定时时间的计算:基本定时器只有内部时钟72MHz,定时器的实际时钟=内部时钟/(定时器预分频+1),那么TIM_Prescaler设置为7200-1,内部时钟源经过定时器预分频后即可得到10kHz(72MHz/((7200-1)+1))的频率。然后TIM_Period设置为5000-1,(这里因为计数是从0开始的,所以要减1),即可以得到定时为0.5s(5000*(1/10kHz))的定时器。代码如下:

创建一个TIME_base.h

#ifndef __TIMER_BASE_H
#define __TIMER_BASE_H
#include "stm32f10x.h"
    void TIME_NVIC_Configuration(void);
    void TIME_Configuration(void);
    void GPIO_Config(void);
#endif

创建一个TIME_base.c

#include "TIME_base.h"
void TIME_NVIC_Configuration(void)//如果系统会产生多种中断,那么就存在中断响应的优先级
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);           //设置优先级分组
    NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;           //指定IRQ通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //指定先占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //从优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;          //定义的IRQ是被使能还是失能
    NVIC_Init(&NVIC_InitStructure);  
}

void TIME_Configuration(void)//配置TIM6
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); 
    TIM_TimeBaseStructure.TIM_Period = 5000; //设置了在下一个更新事件装入活动的自动重装载寄存器周期的值 范围是0x0000-0xFFFF
    TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); //设置了用来作为 TIMx 时钟频率除数的预分频值
    TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); 
    TIM_ITConfig(TIM6,TIM_IT_Update|TIM_IT_Trigger,ENABLE);//使能或者失能 TIM 的中断,详见附录图1
    TIM_Cmd(TIM6, ENABLE);  
}

void GPIO_Config(void)//配置一个IO口:
{		
    /*定义一个GPIO_InitTypeDef类型的结构体*/
     GPIO_InitTypeDef GPIO_InitStructure;
    /*开启GPIOB的外设时钟*/
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    /*选择要控制的GPIOB引脚*/	   
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	
    /*设置引脚模式为通用推挽输出*/
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   
    /*设置引脚速率为50MHz */   
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
    /*调用库函数,初始化GPIOB*/
     GPIO_Init(GPIOB, &GPIO_InitStructure);
    /*PB.0 输出高*/
     GPIO_SetBits(GPIOB,GPIO_Pin_0);   
}

附录图1:

stm32之TIM-基本定时器应用实例(详细)_第1张图片

在stm32f10x_it.c添加定时器触发的中断处理函数:

void TIM6_IRQHandler(void)   
{
    if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)  //获取中断状态
    {
        TIM_ClearITPendingBit(TIM6, TIM_IT_Update  );  //清除中断标志
        //在这里做中断需要处理的事情,尽可能精简,避免过长时间停留在中断里面
        GPIO_WriteBit(GPIOB, GPIO_Pin_0, (BitAction)(1-(GPIO_ReadOutputDataBit(GPIOB,  GPIO_Pin_0))));
    }

}

创建一个main.c

#include "TIME_base.h"
int main(void)
{	  
    /* IO端口配置 */ 
    GPIO_Config();	
    /* TIM6 定时配置 */
    TIME_NVIC_Configuration();
    TIME_Configuration();
    while(1){
    }
}

将上面的TIM6全部换成TIM7也是可以的。

然后就可以把编译好的程序下载到开发板了,可以在PB.0引脚处接一个led,那么led就会每0.5s闪烁一次。

水平有限,仅供参考,错误以及不足之处还望多多指教。

你可能感兴趣的:(STM32应用实例)