-
TIM简介
-
时基单元介绍
-
函数介绍
-
实现代码
一.TIM简介
1.TIM(Timer)定时器:可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。
2.根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型。
- 高级定时器(TIM1,TIM8):拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能
- 通用定时器(TIM2到5):拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能
- 基本定时器(TIM6,TIM7):拥有定时中断、主模式触发DAC的功能
3.基本结构:
4.由图可知使用时只用配置好一条通路就可以使用了。
- RCC开启时钟——选择时钟源——配置时基单元——配置中断控制输出——NVIC——启动定时器
二.时基单元介绍
1.PSC:将定时器时钟源进行分频输出,降低计数器的频率。
- 计数器频率:CK_CNT = CK_PSC / ( PSC + 1 )
2.CNT:定时器溢出频率=CK_PSC / ( PSC + 1 )(ARR + 1)
三.函数介绍
- TIM_InternalClockConfig:开启需要的定时器时钟
- TIM_TimeBaseInit:时基单元初始化
- TIM_ITConfig:使能中断输出信号
- TIM_Cmd:使能计数器,用于启动定时器
四.实现代码
1.首先新建一个关于TIM定时器的.c文件用来存放代码,之后按照上方的步骤配置就可以了。
- RCC开始需要使用的时钟,这里使用的通用定时器TIM2,是APB1的外设,没用用到别的GPIO口,所以只用开启TIM2就可以了
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
- 之后开启定时器时钟,这里用的TIM2
TIM_InternalClockConfig(TIM2);
- 配置时基单元, 由于时基单元需要结构体参数,也就需要配置结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//控制时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//选择计数器模式,这里是向
上计数
/*这3是时基单元里关键寄存器的参数,主要是给PSC和ARR一个初始值
关于时间的计算用上方的公式,对72MHz进行7200分频,得到10K再计1万个数,得到1s的时间
注意ARR和PSC范围最大65535*/
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC预分频器值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级计时器用的
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//需要结构体参数,记得取地址符
- 之后配置中断控制输出
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
- 配置NVIC,NVIC的相关代码在上一节有介绍
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)
- 主函数如下,关于Delay和OLED部分在前两节有相关代码,Timer的代码上方都给了,再建一个.h文件就行了
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
uint16_t num;
int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1,1,"Num:");
while(1)
{
OLED_ShowNum(1,5,num,5);//每1s(中断进入一次)加1
// OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);//显示计数器的值
}
}
void TIM2_IRQHandler(void)
{
if( TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)//经典判断
{
num++;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//手动清除标志位
}
}
- 接线图如下,OELD的接线其实也在上一节有