STM32学习5

TIM定时器中断

简介

TIM(Timer)定时器

定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断

16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时(72M/65536/65536=59.65)

不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能

根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型

stm32的定时器可以从宇宙诞生计数到宇宙毁灭哦!!!

定时器类型

STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4 

定时中断基本结构

预分频器时序

计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)

计数器时序

计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1  = CK_PSC / (PSC + 1) / (ARR + 1)

计数周期,即ARR的值,预分频器,即PSC的值。

计数器无预装时序

计数器有预装时序

RCC时钟树

定时器定时中断

定时器函数

#include "stm32f10x.h"                  // Device header

void timer_init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2 ,ENABLE );//开启TIM2的时钟
	/*配置时钟源*/
	TIM_InternalClockConfig(TIM2);	//选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
	/*时基单元初始化*/
	TIM_TimeBaseInitTypeDef TIM_TimebaseinitStructure;//定义结构体变量
	TIM_TimebaseinitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ;//时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
	TIM_TimebaseinitStructure.TIM_CounterMode=TIM_CounterMode_Up ;//计数器模式,选择向上计数
	TIM_TimebaseinitStructure.TIM_Period=10000-1;//计数周期,即ARR的值
	TIM_TimebaseinitStructure.TIM_Prescaler=7200-1;//预分频器,即PSC的值
	TIM_TimebaseinitStructure.TIM_RepetitionCounter=0;//重复计数器,高级定时器才会用到
	TIM_TimeBaseInit(TIM2,&TIM_TimebaseinitStructure);	//将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);	//清除定时器更新标志位
																				//TIM_TimeBaseInit函数末尾,手动产生了更新事件
																				//若不清除此标志位,则开启中断后,会立刻进入一次中断
																				//如果不介意此问题,则不清除此标志位也可
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );//开启TIM2的更新中断
	
	/*NVIC中断分组*/
	NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2 );//配置NVIC为分组2
																//即抢占优先级范围:0~3,响应优先级范围:0~3
																//此分组配置在整个工程中仅需调用一次
																//若有多个中断,可以把此代码放在main函数内,while循环之前
																//若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_Initstructure;//定义结构体变量
	NVIC_Initstructure.NVIC_IRQChannel=TIM2_IRQn ;//选择配置NVIC的TIM2线
	NVIC_Initstructure.NVIC_IRQChannelCmd=ENABLE;	//指定NVIC线路使能
	NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=2;//指定NVIC线路的抢占优先级为2
	NVIC_Initstructure.NVIC_IRQChannelSubPriority=1;	//指定NVIC线路的响应优先级为1
	NVIC_Init (&NVIC_Initstructure );//将结构体变量交给NVIC_Init,配置NVIC外设
	/*TIM使能*/
	TIM_Cmd (TIM2,ENABLE );//使能TIM2,定时器开始运行
	
}

/*void TIM2_IRQHandler (void)
{
	if(TIM_GetITStatus (TIM2 ,TIM_IT_Update)==SET)
	{
		
		
		
	}

	TIM_ClearITPendingBit (TIM2 ,TIM_IT_Update );
}*/

!!!!!!!!!!!!!!!!打100000个感叹号!!!!!!!!!!!!!!!!!!

定时器为单片机很重要很重要的一个工具,需要好好学习

注意点:

1.配置定时器需要时基单元初始化,如果是内部时钟的话可以不配。

2.配置定时器的步骤还是老样子:定义结构体变量——把所有结构体内容写出来——结构体变量交给xxx。

3.定时器相比于其他多了几个内容:开启更新中断和使定时器开始运行。

4.判断是否是TIM2的更新事件触发的中断需要单独写。可以再写定时器的模板的时候写在最底下然后注释掉,使用的时候复制到main函数中使用,否则将会用到extern。

主函数

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "key.h"
#include "OLED.h"
#include "Timer.h"
uint16_t Num;

int main(void)
{
	
	OLED_Init();	
	OLED_ShowString(1, 1, "Num:");	//1行1列显示字符串Num:
	timer_init() ;

	while(1)
	{
		OLED_ShowNum (1,5,Num,5 );
	
	}

}

void TIM2_IRQHandler (void)
{
	if(TIM_GetITStatus (TIM2 ,TIM_IT_Update)==SET)//判断是否是TIM2的更新事件触发的中断
	{
		Num++;//Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit (TIM2 ,TIM_IT_Update );//清除TIM2更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}

	
}

定时器外部中断

定时器函数

#include "stm32f10x.h"                  // Device header

void timer_init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2 ,ENABLE );//开启TIM2的时钟
	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA ,ENABLE );
	GPIO_InitTypeDef GPIO_Initstructure;
	GPIO_Initstructure.GPIO_Mode=GPIO_Mode_IPU ;
	GPIO_Initstructure.GPIO_Pin=GPIO_Pin_0 ;
	GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz ;
	GPIO_Init (GPIOA ,&GPIO_Initstructure );
	/*配置时钟源*/
	TIM_ETRClockMode2Config (TIM2,TIM_ExtTRGPSC_OFF ,TIM_ExtTRGPolarity_NonInverted,0x0F);	
																//选择外部时钟模式2,时钟从TIM_ETR引脚输入
																//注意TIM2的ETR引脚固定为PA0,无法随意更改
																//最后一个滤波器参数加到最大0x0F,可滤除时钟信号抖动
	/*时基单元初始化*/
	TIM_TimeBaseInitTypeDef TIM_TimebaseinitStructure;//定义结构体变量
	TIM_TimebaseinitStructure.TIM_ClockDivision=TIM_CKD_DIV1 ;//时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
	TIM_TimebaseinitStructure.TIM_CounterMode=TIM_CounterMode_Up ;//计数器模式,选择向上计数
	TIM_TimebaseinitStructure.TIM_Period=10-1;//计数周期,即ARR的值
	TIM_TimebaseinitStructure.TIM_Prescaler=1-1;//预分频器,即PSC的值
	TIM_TimebaseinitStructure.TIM_RepetitionCounter=0;//重复计数器,高级定时器才会用到
	TIM_TimeBaseInit(TIM2,&TIM_TimebaseinitStructure);	//将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);	//清除定时器更新标志位
																				//TIM_TimeBaseInit函数末尾,手动产生了更新事件
																				//若不清除此标志位,则开启中断后,会立刻进入一次中断
																				//如果不介意此问题,则不清除此标志位也可
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );//开启TIM2的更新中断
	
	/*NVIC中断分组*/
	NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2 );//配置NVIC为分组2
																//即抢占优先级范围:0~3,响应优先级范围:0~3
																//此分组配置在整个工程中仅需调用一次
																//若有多个中断,可以把此代码放在main函数内,while循环之前
																//若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_Initstructure;//定义结构体变量
	NVIC_Initstructure.NVIC_IRQChannel=TIM2_IRQn ;//选择配置NVIC的TIM2线
	NVIC_Initstructure.NVIC_IRQChannelCmd=ENABLE;	//指定NVIC线路使能
	NVIC_Initstructure.NVIC_IRQChannelPreemptionPriority=2;//指定NVIC线路的抢占优先级为2
	NVIC_Initstructure.NVIC_IRQChannelSubPriority=1;	//指定NVIC线路的响应优先级为1
	NVIC_Init (&NVIC_Initstructure );//将结构体变量交给NVIC_Init,配置NVIC外设
	/*TIM使能*/
	TIM_Cmd (TIM2,ENABLE );//使能TIM2,定时器开始运行
	
}
uint16_t timer_gercounter(void)
{
	
	return TIM_GetCounter (TIM2 );
	
}

/*void TIM2_IRQHandler (void)
{
	if(TIM_GetITStatus (TIM2 ,TIM_IT_Update)==SET)
	{
		
		
		
	}

	TIM_ClearITPendingBit (TIM2 ,TIM_IT_Update );
}*/







注意!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

1.外部中断和定时器中断并没有多大的区别,只是多用了gpio

2.外部中断只能使用PA0接口

3.选择外部时钟模式2,时钟只能从TIM_ETR引脚输入

4.需要加一个滤波来消除抖动

主函数

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "key.h"
#include "OLED.h"
#include "Timer.h"
uint16_t Num;

int main(void)
{
	
	OLED_Init();	
	OLED_ShowString(1, 1, "Num:");	//1行1列显示字符串Num:
	OLED_ShowString(2, 1, "CNT:");
	timer_init() ;

	while(1)
	{
		OLED_ShowNum (1,5,Num,5 );
		OLED_ShowNum (2,5,timer_gercounter (),5 );
	}

}

void TIM2_IRQHandler (void)
{
	if(TIM_GetITStatus (TIM2 ,TIM_IT_Update)==SET)//判断是否是TIM2的更新事件触发的中断
	{
		Num++;//Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit (TIM2 ,TIM_IT_Update );//清除TIM2更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}

	
}

总结

1.定时器再stm32的学习中尤其重要,需要好好的揣摩

2.定时器的功能可以实现很多有意思的想法,以后有时间可以试一下

  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值