基于STM32F4xx 系列的基本定时器


一、基本定时器简介

STM32F4xx 系列的基本定时器 TIM6 和 TIM7 包含一个 16 位自动重载计数器,该计数器由可编程预分频器驱动。此类定时器不仅可用作通用定时器以生成时基, 还可以专门用于驱动数模转换器 (DAC)。实际上,此类定时器内部连接到 DAC 并能够通过其触发输出驱动 DAC。这些定时器彼此完全独立,不共享任何资源。(来自中文参考手册)
总结:
基本定时器功能:
①延时、计数
②触发DAC转换
③计数方向:递增计数

二、基本定时器数量

在这里插入图片描述
从芯片数据手册可知,STM32F407VET6有两个基本定时器,分别是TIM6 和 TIM7。注意:并不是每一款芯片都会有基本定时器,如需确定所使用的芯片是否有基本定时器的话,需要查看数据手册参数表,比如M3芯片就没有基本定时器。

三、基本定时器框图

在这里插入图片描述

3.1基本定时器频率

在这里插入图片描述

由数据手册可知,TIM6和TIM7挂靠在频率为42Mhz的APB1总线上。
注意:TIM6和TIM7并不是42Mhz频率,要确定TIM6和TIM7频率需要利用时钟树(中文参考手册 RCC章节)

在这里插入图片描述
当APBx总线分频为1时,定时器频率为APBx频率1
当APBx总线分频不为1时,定时器频率为APBx频率
2

众所周知,APBx总线频率是由AHB1总线频率分频来的,而AHB1频率:168Mhz, APB1频率:42Mhz,APB2频率:84Mhz,所以APB1和ABP2一定进行了分频。如APB1和ABP2进行了分频的话,所挂靠在这两根总线上的定时器的频率 = 挂靠总线频率 * 2。
所以,TIM6定时器频率为42 * 2 = 84Mhz

3.2 基本定时器寄存器

在这里插入图片描述
TIM6 和 TIM7 控制寄存器 1 (TIMx_CR1)
在这里插入图片描述
TIM6 和 TIM7 控制寄存器 2 (TIMx_CR2)
不需要配置
TIM6 和 TIM7 DMA/中断使能寄存器 (TIMx_DIER)
位 0 UIE:更新中断使能 (Update interrupt enable)
0:禁止更新中断。
1:使能更新中断。
TIM6 和 TIM7 状态寄存器 (TIMx_SR)
标志位
位 0 UIF:更新中断标志 (Update interrupt flag)
该位在发生更新事件时通过硬件置 1。但需要通过软件清零。
0:未发生更新。
1:更新中断挂起。该位在以下情况下更新寄存器时由硬件置 1:
— 上溢或下溢并且当 TIMx_CR1 寄存器中 UDIS = 0 时。
— 当由于 TIMx_CR1 寄存器中 URS = 0 且 UDIS = 0 而通过软件使用 TIMx_EGR 寄存器中的 UG 位重新初始化 CNT 时。
TIM6 和 TIM7 事件生成寄存器 (TIMx_EGR)
位 0 UG:更新生成 (Update generation)
该位可通过软件置 1,并由硬件自动清零。
0:不执行任何操作。
1:重新初始化定时器计数器并生成寄存器更新事件。请注意,预分频器计数器也将清零(但预分频比不受影响)

在初始化设置重装载值需要将UG位置一,加载重装载值到计数器
TIM6 和 TIM7 计数器 (TIMx_CNT)
设置初始计数值(注意:设置初始计数值只有在第一个周期有效)
TIM6 和 TIM7 预分频器 (TIMx_PSC)
设置预分频数:可设置范围 0 - 65535
TIM6 和 TIM7 自动重载寄存器 (TIMx_ARR)
设置重装载值:可设置范围0 - 65535

四、基本定时器使用

4.1实现TIM6的微秒级延时

void TIM6_Delay_ms(u16 nms)
{
	//打开TIM6时钟
	RCC->APB1ENR |= 1 << 4;
	//初始化TIM6
	TIM6->CR1 |= 1 << 7;    //使能ARR寄存器影子寄存器的缓冲模式
	TIM6->CR1 |= 1 << 3;    //使能单脉冲模式
	TIM6->CR1 &=~ (1 << 2); //更新请求源清零
	TIM6->CR1 &=~ (1 << 1); //USDI清零,使能更新
	//设置定时器时基单元
	TIM6->PSC = 8400 - 1;        //设置PSC
	TIM6->ARR = nms * 10 - 1;   //设置ARR
	TIM6->EGR |= 1 << 0;       //UG位置1,产生更新事件
	TIM6->SR &=~ (1 << 0);              //清除更新标志位
	//定时器使能
	TIM6->CR1 |= (1 << 0);    
	//等待更新标志位置1
	while(!(TIM6->SR & (1 << 0)));
}

主函数里我用了灯闪烁的例子

LED1_ON;
TIM6_Delay_ms(500);
LED1_OFF;
TIM6_Delay_ms(500);

4.2实现每500毫秒打印1,1000毫秒打印2

/*
函数功能:TIM7 1毫秒中断初始化
返回值:void
形参:u16 nms
函数说明:
*/
void TIM7_Interrupt(u16 nms)
{
	//打开TIM7时钟
	RCC->APB1ENR |= 1 << 5;
	//初始化TIM7      
	TIM7->CR1 |= 1 << 7;    //使能ARR寄存器影子寄存器的缓冲模式
	TIM7->CR1 &=~ (1 << 3) ;  //使能连续模式
	TIM7->CR1 &=~ (1 << 2); //更新请求源清零
	TIM7->CR1 &=~ (1 << 1); //USDI清零,使能更新
	
	//设置定时器时基单元
	TIM7->PSC = 8400 - 1;       //设置PSC
	TIM7->ARR = nms * 10 - 1;   //设置ARR
	TIM7->EGR |= 1 << 0;        //UG位置1,产生更新事件
	TIM7->SR &=~ (1 << 0);      //清除更新标志位
	
	//使能TIM7更新中断
	TIM7->DIER |= 1 << 0;   
	
	//配置NVIC
	u32 pri = NVIC_EncodePriority(5, 3, 3); 	
	//设置优先级
	NVIC_SetPriority(TIM7_IRQn, pri);
	//使能中断源
	NVIC_EnableIRQ(TIM7_IRQn); 
	
	//定时器使能
	TIM7->CR1 |= (1 << 0);    
}
//TIM7中断服务函数
void TIM7_IRQHandler(void)
{
	//清除标志位
	TIM7->SR &=~ (1 << 0);
	//1毫秒执行一次下面代码
	tim7_flag = 1;
}

主函数代码如下:

u16 time_cnt[5] = {0};
while(1)
{
	if(tim7_flag == 1)
	{
		tim7_flag = 0;
		time_cnt[0]++;
		time_cnt[1]++;
		
		if(time_cnt[0] == 500)
		{
			time_cnt[0] = 0;
			printf("1\r\n");
		}
		if(time_cnt[1] == 1000)
		{
			time_cnt[1] = 0;
			printf("2\r\n");
		}
	}
}
  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值