stm32入门教程--TIM定时器

TIM(Timer)定时器

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

STM32 有16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz基数时钟下可以实现最大的59.65s的定时。不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。

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

三种定时器高级向下兼容,高级定时器包含通用定时器的所有功能,通用定时器包含基本定时器的所有功能。

以STM32F103C8T6为例,其定时器资源为:TIM1、TIM2、TIM3、TIM4,也就是一个高级定时器和三个通用定时器,没有基本定时器。

定时器电路分析

基本定时器

基本定时器中有三个最重要的寄存器,分别是预分频器、计数器、自动重装寄存器,他们构成了最基本的计数计时器电路,所以这一块电路叫做时基单元,预分频器之前,连接的就是基准计数时钟的输入,最终到了控制器,控制器的输入端直接与内部时钟相连,内部时钟的来源是RRC_TIMxCLK,这里的频率值一般都是系统的主频72MHz。

预分频器如果为0,就是不分频,或者1分频,此时输出频率=输入频率=72MHz;

如果预分频器写1,就是2分频,此时输出频率=输入频率/2=36MHz;

如果预分频器写2,就是3分频,此时输出频率=输入频率/3=24,以此类推

即,实际分频系数=预分频器的值+1

图中预分频器为16位的,所以最大值可以写65535,也就是65536分频

计数器也为16为,每计数一次自增一次,直到65535清零,计数的同时不断与自动重装寄存器进行比较他们的值相等时,会产生一个更新中断和更新事件,CPU相应更新中断,就完成了定时中断的任务了。

通用定时器

通用定时器最核心的还是时基单元,每部分功能和流程也可时基单元是一样的,但高级定时器和通用定时器就不止向上自增这一种计数模式,还支持向下计数模式和中央对齐模式。向下计数模式是从重装值开始向下自减,减到0之后,回到重装值同时申请中断然后继续下一轮,依次循环 。中央对齐模式就是从0开始向上自增到重装值时再向下自减,减到0,再申请中断。不过我们比较常用的还是向上计数的模式

定时器中断

在OLED上显示了一个数字Num,并且每秒自动加1,这就是用了定时中断的功能,定时器使用内部时钟定了一个1秒的时间,每隔1秒申请下中断,然后在中断函数里执行Num++,最后在OLED显示Num。

接线图

示例代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;			//定义在定时器中断里自增的变量

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	Timer_Init();		//定时中断初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Num:");			//1行1列显示字符串Num:
	
	while (1)
	{
		OLED_ShowNum(1, 5, Num, 5);			//不断刷新显示Num变量
	}
}

/**
  * 函    数:TIM2中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)		//判断是否是TIM2的更新事件触发的中断
	{
		Num ++;												//Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);			//清除TIM2更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}
}

定时器外部时钟

使用外部时钟来驱动定时器,在定时器指定的外部引脚上,输入一个方波信号来提供定时器计数的时钟。(该实验用对射红外传感器模拟外部时钟,用挡光片,依次遮挡、移开、遮挡、移开,提供一个方波对应OLED显示出计数器的值,每遮挡、移开一次,计数器加1,计数器计到9后自动清0,同时申请中断,同时Num++)

使用定时器的外部时钟,可以提供一个更加精准的时钟来计时,或者也可以把外部时钟当作一个计数器,用来统计引脚上的电平翻转的次数

接线图

示例代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;			//定义在定时器中断里自增的变量

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	Timer_Init();		//定时中断初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Num:");			//1行1列显示字符串Num:
	OLED_ShowString(2, 1, "CNT:");			//2行1列显示字符串CNT:
	
	while (1)
	{
		OLED_ShowNum(1, 5, Num, 5);			//不断刷新显示Num变量
		OLED_ShowNum(2, 5, Timer_GetCounter(), 5);		//不断刷新显示CNT的值
	}
}

/**
  * 函    数:TIM2中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)		//判断是否是TIM2的更新事件触发的中断
	{
		Num ++;												//Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);			//清除TIM2更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是lamune

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值