stm32学习日记3(TIM上)

本文主要为TIM定时器的笔记。

TIM简介

TIM(Timer)定时器:定时器可以对输入的时钟进行计数,在计数值达到设定值时触发中断,这是定时器最基本的功能,可以将定时器看作一个计数器

在STM32中,定时器的基准时钟一般是主频72MHz,对72MHz计72个数,1MHz就是1us的时间,计72000个数,1KHz就是1ms的时间。

STM32定时器拥有16位的计数器(CNT)、16位的预分频器(PSC)和16位的自动重装寄存器(ARR),这三部分统称为时基单元,在72MHz计数时钟下可以实现最大59.65s的定时。

计数器:执行计数定时的寄存器,每累积一个时钟,计数器加1。

预分频器:对计数器的时钟进行分频,使得计数更加灵活。

自动重装寄存器:设置计数的目标值,申请中断需要时钟的计数达到多少。

计数器可以级联:一个计数器的输出当作另一个计数器的输入,两个计数器的级联模式下,最大定时时间为59.65*65536*65536。

定时器的功能:定时中断,内外时钟源选择,输入捕获,输出比较,编码器接口,主从触发模式等。

定时器的个数和分类

在stm32中,最多有8个定时器

但在STM32F103C8T6中只有TIM1,TIM2,TIM3,TIM4一个高级定时器和三个通用定时器。

基本定时器:时钟源只有内部时钟,系统频率72MHz

通用定时器:时钟源可以选择内部时钟和外部时钟(1.TIMx_ETR、2.TRGI)

基本定时器定时中断的流程

基本定时器框图

PSC预分频器对输入的基准频率提前进行分频的操作,对72MHz的计数时钟进行预分频,当预分频器写0时表示不分频或是1分频,输出频率=输入频率=72MHz;预分频器写1表示2分频,输出频率=输入频率/2=36MHz,预分频器为16位,所以其最大值为65535,最大分频为65535。

计数器对预分频后的计数时钟进行计数,计数时钟每有一个上升沿计数器的值就+1,计数器16位,它的值也是从0-65535,如果超过65535,计数器就会回到0重新开始。

自动重装寄存器存储计数器目标值,当计数器的值等于自动重装的值时,表示计时时间到了,产生中断信号并清零计数器。

大致如上图所示,像这种计数值等于自动重装值产生的中断叫做“更新中断”,更新中断产生后,产生更新事件触发内部其他电路的工作,中断信号会通往NVIC,再通过配置NVIC的定时器通道,就能够让CPU响应定时器的更新中断。

总结流程

1.来自RCC的时钟源TIMxCLK通过内部基准时钟(CK_INT)进入控制器,

2.然后到达预分频器对,输入的基准频率提前进行分频的操作,

3.计数器对预分频后的计数时钟进行计数,计数器计数自增,同时不断地与自动重装寄存器进行比较,

4.当计数器值和自动重装寄存器值相等时,达到计时时间,产生一个更新中断和更新事件,CPU响应更新中断,定时中断任务完成。

计数器计数模式

计数模式

计数器有三种计数模式:向上计数模式、向下计数模式、中央对齐模式。 

基本定时器仅支持向上计数模式,通用定时器和高级定时器支持上面三种模式,最常用的是向上计数模式。

通用定时器定时中断的流程

初始化定时器

1.配置RCC时钟

打开RCC时钟,同时会打开定时器的基准时钟和整个外设的工作时钟。

2.选择时基单元的时钟源

对于定时中断,选择内部时钟源。

3.配置时基单元

包括预分频器、计数模式、自动重装器,包含在结构体中。

4.配置输出中断控制

允许更新中断输出到NVIC。

5.配置NVIC

在NVIC中打开定时器中断的通道,分配合适的中断优先级,中断信号通过NVIC进入CPU,CPU收到中断信号,跳转到中断函数中执行中断程序。

6.运行控制

编写中断函数,使能定时器,当定时器使能后,计数器开始计数,计数器更新触发中断,每隔一段时间自动执行一次中断函数。

定时器TIM库函数介绍

void TIM_DeInit(TIM_TypeDef* TIMx);
功能:把TIM的寄存器值恢复到复位状态(恢复出厂设置)

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
功能:初始化时基单元,
选定某个定时器,通过结构体变量的参数来配置时基单元

void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
功能:用于初始化时间基础结构体,
将时间基础结构体的各个成员变量初始化为默认值

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
功能:决定让计数器使能(ENABLE)还是失能(DISABLE)

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
功能:使能中断输出信号,打开中断输出控制

void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
功能:选择内部时钟

void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
功能:选择ITRx其他定时器的时钟,
参数选择要配置的定时器和接入哪个其他的时钟

void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);
功能:选择TIx捕获通道的时钟,
参数TIM_TIxExternalCLKSource是选择TIx具体的某个引脚,
ICPolarity, ICFilter表示输入的极性和滤波器

void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
功能:选择ETR通过外部时钟模式1输入的时钟,
ExtTRGPrescaler外部触发预分频器,对ETR的外部时钟提前做一个分频

void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
功能:选择ETR通过外部时钟模式2输入的时钟

void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
功能:配置ETR引脚的预分频器、极性、滤波器这些参数

void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
功能:写入预分频值,Prescaler就是要写入的预分频值,PSCReloadMode表示写入的模式

void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
功能:用于改变计数器的计数模式,CounterMode计数器模式

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
功能:配置自动重装器预装功能

void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
功能:给计数器写入一个值

void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
功能:给自动重装器写入一个值

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
功能:获取当前计数器的值,返回值就是当前计数器的值

uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
功能:获取当前的预分频器的值

FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
这四个用于获取标志位或清除标志位

定时器定时中断的配置代码

#include "stm32f10x.h"

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	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;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	//开启更新中断到NVIC的通路
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	TIM_ClearFlag(TIM2,TIM_IT_Update);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2,ENABLE);
	
}

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

定时器外部时钟的配置代码

在配置定时中断的基础上,配置GPIO口,设置PA0引脚为TIM2的ETR引脚,在此引脚输入一个外部时钟,使用外部时钟来进行定时中断。

#include "stm32f10x.h"

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	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);
	

//通过ETR引脚的外部时钟2配置
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10-1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1-1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	//开启更新中断到NVIC的通路
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	TIM_ClearFlag(TIM2,TIM_IT_Update);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	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))
	{
		NUM++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值