STM32之定时器1——定时器基本知识,定时器中断与外部时钟

目录

TIM(Timer)定时器

定时器类型

高级定时器

通用定时器

基本定时器

定时器基本参数

时钟源

计数器模式

时基单元

计算公式

理论知识(不看也行)

定时器基本函数解析

 定时中断

外部时钟(中断可不用)


TIM(Timer)定时器

定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断 16位计数器、预分频器(16位)、自动重装寄存器(16位)的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时    

最大定时=1/(72Mhz/65536(16位)/65536)(中断频率) 可通过级联方式增加定时时长

(一个定时器的输出,当作另一个计时器的输入最大可达35万亿年的计时)

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

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

定时器类型

高级定时器

通用定时器

基本定时器

定时器基本参数

时钟源

计数器模式

通用计时器支持

TIM_CounterMode_Up  向上计时,从0到重装值

TIM_CounterMode_Down  向下计时,从重装值到0

TIM_CounterMode_CenterAligned 中央对齐,从0到重装,再从重装到0,如此反复

时基单元

PSC预分频器:计数的频率,(72Mhz/PSC)多久计一个数(0~65535)

ARR自动重装器:一共计多少个数(到达后归0重装)(0~65535)

CNT计数器:当前的计数值

TIM_RepetitionCounter=0;//(高级定时器)重复计数器的值

计算公式

1s=1000ms=1000000us

1Hz=1s

1khz=1000Hz=1ms

1Mhz=1000000Hz=1us

CK_PSC(72Mhz)/ (PSC + 1) / (ARR + 1)=CK_CNT_OV 

72000000/7200/10000=1s

在72Mhz/7200=10k 0.1ms计一个数,共计10000个数,0.1*10000=1000ms=1s

理论知识(不看也行)

RCC时钟树

定时器基本函数解析

1.定时器初始化

2.时基单元初始化

3.时基单元赋个默认值

4.定时器使能

5.定时器中断输出控制配置

6~11 外部时钟选择

6.内部时钟

7.ITRx其他定时器的时钟  

8.选择TIx捕获通道的时钟

9.ETR通过外部时钟1输入的时钟                                        

10.ETR通过外部时钟2输入的时钟  

11.配置ETR引脚的预分频器、极性、滤波器

12.写预分频值

13.改变计时器的计时模式 

14.配置有无预装时序

 15.手动设置计数值

 16.给自动重装器写一个值 

17.获取当前计数器的值

18.获取当前预分频的值

19~22  获取,清除中断标志位(带IT为在中断中使用)

 定时中断

初始化代码如下 timer.c

#include "stm32f10x.h"                  // Device header
void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//RCC时钟定时器使能开启
	
	TIM_InternalClockConfig(TIM2);//指定内部时钟
	
	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自动重装器(计多少个数)的值0~65535
	TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;
//时基单元PSC预分屏器(计数频率)的值0~65535
	//计数器溢出频率CK_CNT_OV = CK_PSC(72Mhz)/ (PSC + 1) / (ARR + 1)
	//这里是在10k的频率(72Mhz/7200)下计10000个数 1s=1hz
	//这里没有时基单元CNT计数器,需要的可以使用SetCounter和GetCounter来操作
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//(高级定时器)重复计数器的值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	//这里的作用很细节,在TIM_TimeBaseInit中的最后一句
	//TIMx->EGR = TIM_PSCReloadMode_Immediate;(生成一个更新事件,重新装载预分频器和重复计数器 
    //的值,立刻)
	//这样会让更新事件和更新中断同时发生,从而一上电中断标志位就成了SET,就立刻进入了中断
	//因此要养成初始化清除标志位的好习惯
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//中断控制:更新中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructrue;
	NVIC_InitStructrue.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStructrue.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructrue.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructrue.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructrue);
	
	TIM_Cmd(TIM2,ENABLE);
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
		
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
	
}

注意:

TIM_ClearFlag(TIM2,TIM_FLAG_Update);
    这里的作用很细节,在TIM_TimeBaseInit中的最后一句
    TIMx->EGR = TIM_PSCReloadMode_Immediate;(生成一个更新事件,重新装载预分频器和重复计数器的值,立刻)
    这样会让更新事件和更新中断同时发生,从而一上电中断标志位就成了SET,就立刻进入了中断
    因此要养成初始化清除标志位的好习惯

外部时钟(中断可不用)

初始化代码如下 timer.c

TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_Inverted,0x0F);
    //ETR外部时钟2指定计时器,预分频器(有预分频器则多少次CNT才加1),极性,滤波器

极性:

TIM_ExtTRGPolarity_Inverted下降沿计数一次

TIM_ExtTRGPolarity_NonInverted上升沿计数一次

ExtTRGFilter:

外部滤波:在固定频率F下采样,连续N个采样点都为相同的电平,那么代表信号稳定,则输出采样值。 若不同就有抖动,保持上一个采样值,或者输出低电平,频率越低采样数越高,效果越好,但是信号延迟会变大

#include "stm32f10x.h"                  // Device header
void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//RCC时钟定时器使能开启
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitTypeDef GPIO_InitStructrue;
	GPIO_InitStructrue.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructrue.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStructrue.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructrue);
	
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_Inverted,0x0F);
	//ETR外部时钟2指定计时器,预分频器(有预分频器则多少次CNT才加1),极性,滤波器
	//TIM_InternalClockConfig(TIM2);//指定内部时钟
	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自动重装器(计多少个数)的值0~65535
	TIM_TimeBaseInitStructure.TIM_Prescaler=1-1;//时基单元PSC预分屏器(计数频率)的值0~65535
	//计数器溢出频率CK_CNT_OV = CK_PSC(72Mhz)/ (PSC + 1) / (ARR + 1)
	//这里是在10k的频率(72Mhz/7200)下计10000个数 1s=1hz 1000hz=1ms 10000hz=1us
	//这里没有时基单元CNT计数器,需要的可以使用SetCounter和GetCounter来操作
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//(高级定时器)重复计数器的值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	//这里的作用很细节,在TIM_TimeBaseInit中的最后一句
	//TIMx->EGR = TIM_PSCReloadMode_Immediate;(生成一个更新事件,重新装载预分频器和重复计数器的值,立刻)
	//这样会让更新事件和更新中断同时发生,从而一上电中断标志位就成了SET,就立刻进入了中断
	//因此要养成初始化清除标志位的好习惯
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//中断控制:更新中断
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructrue;
	NVIC_InitStructrue.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStructrue.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructrue.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructrue.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStructrue);
	
	TIM_Cmd(TIM2,ENABLE);
}

uint16_t Timer_GetCounter(void)
{
	return TIM_GetCounter(TIM2);
}
//void TIM2_IRQHandler(void)
//{
//	if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
//	{
//		
//		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
//	}
//	
//}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值