STM32-定时器系列(一)基本定时器

    相信学过51单片机的小伙伴们使用过定时刷新数码管吧,那也一定想过,我们在STM32中也想要实现定时刷新数码管,这该怎么实现呢?下面小编就带大家走进STM32的定时器模块吧!

一、什么是定时器

    定时器是一种计时的工具,它具有延时、频率测量、PWM输出、电机控制及编码接口等功能。
    STM32F103微控制器内部集成了多个可编程定时器,可以分为基本定时器(TIM6和TIM7)、通用定时器(TIM2~TIM5)和高级定时器(TIM1、TIM8)3种类型。从功能上看,基本定时器的功能是通用定时器的子集,而通用定时器的功能又是高级定时器的一个子集。

二、基本定时器

1、相关概念

    在STM32F103中,基本定时器TIM6、TIM7各自都包含一个16位自动装载计数器,能够通过各自的可编程预分频器驱动,这两个定时器相互独立,不共享任何资源。

2、主要功能

  • (1)16位自动重载累加计数器
  • (2)16位可编程(可实时修改)预分频器
  • (3)触发DAC同步电路
  • (4)能够咱更新事件(计数器溢出)时产生DMA/中断请求

3、相关寄存器

■ TIM6 和TIM7 控制寄存器 1(TIMx_CR1)
■ TIM6 和TIM7 控制寄存器 2(TIMx_CR2)
■ TIM6 和TIM7 DMA/中断使能寄存器(TIMx_DIER)
■ TIM6 和TIM7 状态寄存器(TIMx_SR)
■ TIM6 和TIM7 事件产生寄存器(TIMx_EGR)
■ TIM6 和TIM7 计数器(TIMx_CNT)
■ TIM6 和TIM7 预分频器(TIMx_PSC)
■ TIM6 和TIM7 自动重装载寄存器(TIMx_ARR)

三、函数解析

1、清除中断标志位TIM_ClearFlag函数

STM32-定时器系列(一)基本定时器_第1张图片

2、定时器使能失能设置TIM_Cmd函数

STM32-定时器系列(一)基本定时器_第2张图片

3、定时器初始化TIM_TimeBaseInit函数

STM32-定时器系列(一)基本定时器_第3张图片

定时器时基单元配置信息结构体TIM_TimeBaseInitTypeDef

typedef struct
{
  uint16_t TIM_Prescaler;        
  uint16_t TIM_CounterMode;       
  uint16_t TIM_Period;           
  uint16_t TIM_ClockDivision;     
  uint8_t TIM_RepetitionCounter; //仅高级定时器TIM1和TIM8有效
} TIM_TimeBaseInitTypeDef;
  • TIM_Period:
        设置在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在 0x0000 和0xFFFF 之间。
  • TIM_Prescaler:
        设置用来作为 TIMx 时钟频率除数的预分频值。它的取值必须在 0x0000 和 0xFFFF 之间。
  • TIM_ClockDivision:
        配置时钟分割,具体值见下表:
    STM32-定时器系列(一)基本定时器_第4张图片
  • TIM_CounterMode :
        选择时钟模式,具体选项见下表:
    STM32-定时器系列(一)基本定时器_第5张图片

四、示例

    小明突发奇想,打算利用STM32F103ZET6开发板做出一个实时时钟出来,其中利用定时器计时并且利用定时器来刷新数码管。

1、基本定时器6(TIM6)配置函数

/*
	* @brif intialization of time(定时器初始化)
	* @para none
	* @reval none
*/
void time6_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	//打开Time6的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 360-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 200-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
	
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM6,TIM_FLAG_Update);
	
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM6,ENABLE);
	
	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);
}

2、基本定时器7(TIM7配置函数)

/*
	* @brif intialization of time(定时器初始化)
	* @para none
	* @reval none
*/
void time7_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	//打开Time6的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 36000-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 2000-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);
	
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM7,TIM_FLAG_Update);
	
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM7,ENABLE);
	
	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);
}


3、基本定时器6中断处理函数

void TIM6_IRQHandler(void)
{ 
	TIM_ClearFlag(TIM6,TIM_IT_Update);//清楚中断标志位
	refresh_segs();//刷新数码管
}

4、基本定时器7中断处理函数

void TIM7_IRQHandler(void)
{ 
	TIM_ClearFlag(TIM7,TIM_IT_Update);
	if(++second==60){//时钟的秒加1并且判断是否需要分钟加1
		second=0;
		if(++minute==60){//时钟的分加1并且判断是否需要时钟加1
			minute=0;
			if(++hour==24) hour=0;//时钟的时加1并且判断24小时是否过完
		}
	}	
}

5、主函数

int main(void)
{
	time6_init();
	time7_init();
	seg_GPIO_Init();
	while(1){
		segbuff[0] = hour/10;
		segbuff[1] = hour%10+12;
		segbuff[2] = minute/10;
		segbuff[3] = minute%10+12;
		segbuff[4] = second/10;
		segbuff[5] = second%10;
	}
}

五、附

1、基本定时器配置6、基本定时器7的配置

    基本定时器6与基本定时器7在同一个函数中进行配置

/*
	* @brif intialization of time(定时器初始化)
	* @para none
	* @reval none
*/
void time6_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	//打开Time6的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6,ENABLE);
	//打开Time7的APB1时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 360-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 200-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM6,&TIM_TimeBaseStructure);
	
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM6,TIM_FLAG_Update);
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM6,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM6,ENABLE);
	
	/*  定时器的初始化以及设置 */
	//设置自动装载周期的值 寄存器的值为周期的值-1
	TIM_TimeBaseStructure.TIM_Period = 36000-1;
	//设置预分频系数 预分频寄存器的值为分频系数-1
	TIM_TimeBaseStructure.TIM_Prescaler = 2000-1;
	//设置时钟分割 TDTS =  Tck_tim
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	//时钟设置为向上计数模式
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM7,&TIM_TimeBaseStructure);
		
	//清楚TIMx的中断待处理位 即TIMx的中断源
	TIM_ClearFlag(TIM7,TIM_FLAG_Update);
	/* 设置参数并打开中断*/
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);
	//设置使能或者失能外设
	TIM_Cmd(TIM7,ENABLE);
	
	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);

	/* 设置NVIC参数 即优先级、打开中断 */
	NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;//指定终端通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//配置抢占式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//配置响应式中断优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//设置成使能中断
	NVIC_Init(&NVIC_InitStructure);
}

2、基本定时器的定时时长计算

  • 定时时长T=(自动装载周期的值+1)(预分频系数+1)/72MHz;
      例如,上面用于数码管刷新基本定时器6定时的时长T=360
    200/72000000=1/1000s;用于实时时钟时间刷新的基本定时器7的定时时长T=36000*2000/72000000=1s。

3、其他相关函数

    假如大家想看相关模块的内容请点击链接前往:STM32-刷新数码管

你可能感兴趣的:(#,STM32,单片机,stm32,单片机,arm)