TIM-定时器——STM32

TIM-定时器——STM32

TIM(Timer)定时器
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时
不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

即使我在计数中途改变了预分频值,计数频率仍然会保持为原来的频率,直到本轮计数完成,在下一轮计数时,改变后的分频值才会起作用。
在这里插入图片描述
带一个黑色阴影的寄存器,都是有影子寄存器这样的的缓冲机制的。
在这里插入图片描述
引入这个影子寄存器的目的实际上是为了同步,就是让值的变化和更新事件同步发生,防止在运行途中更改造成错误,
在这里插入图片描述
中断定时器配置步骤
第一步,RCC开启时钟
第二步,选择时基单元的时钟源
第三步,配置时基单元
第四步,配置输出中断控制,允许更新中断输出到NMIC
第五步,配置NVIC,在NMIC中打开定时器中断的通道,并分配一个优先级
第六步,就是运行控制了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include "stm32f10x.h"                  // Device header

//exten声明变量,就是告诉编译器,现在有Num这个变量,e
//它在别的文件里定义了,用户跨文件使用变量
extern uint16_t Num;

void Timer_Intial(void)
{
	//第一步开启时钟,初始化RCC,选择TIM2
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//第二步选择时基单元的时钟,选择内部时钟,选择TIM2
	TIM_InternalClockConfig(TIM2);
	
	//第三步配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频系数 1分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数的模式 向上计数
	//计数器溢出频率:CK CNT_OV = CKCNT /(ARR + 1)= CK PSC /(PSC + 1)/(ARR +1)
	//配置定时为1s,则CK CNT_OV=1;CKCNT=72MHz=72000000;
	TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;//周期,ARR自动重装器的值 范围0~65536
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1;//PSC预分频器的值 范围0~65536
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; //重复计数器的值 高级计数器才有
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
	
	//第四步配置输出中断
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//更新中断
	
	//清除中断标志位,能够避免刚初始化完就进中断的问题
	TIM_ClearFlag(TIM2,TIM_IT_Update);
	
	//第五步,配置NVIC
	//注意:分组方式整个芯片只能用一种,因此,分组的代码只需要执行一次
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断分组
	//初始化NVIC
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStruct);

	//第六步,运行控制
	TIM_Cmd(TIM2,ENABLE);
}

//定时器的中断函数
void TIM2_IRQHandler(void)
{
	//首先检查一下中断标志位
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Num++;
		//清除标志位
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}


#ifndef _TIMER_H
#define _TIMER_H

void Timer_Intial(void);

#endif

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "LED.h"
#include "KEY.h"
#include "Timer.h"

uint16_t Num;

int main(void)
{

	
	while(1)
	{

	}
}

如何使用跨文件的变量,在中断函数中使用

第一种解决方案,就是使用跨文件的变量,用extern声明即可
第二种解决方案,就是将中断函数剪切到主函数,和变量在同一个文件夹下。

猜你喜欢

转载自blog.csdn.net/qq_45159887/article/details/130462229