Table of Contents
TIM笔记
TIM简介
•TIM(Timer)定时器
•定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
•16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时
•不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
•根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
定时器类型
不同型号拥有的定时器数量不同,详情参考手册
正点原子精英版V2有八个定时器(TIM1~TIM8)
定时器框图
简单了解即可
通用定时器框图
定时中断基本结构
打通步骤
一、RCC开启时钟
此举能同时打开定时器基准时钟和整个外设的工作时钟
RCC_APBxPeriphClockCmd(RCC_APBxPeriph_TIMx, ENABLE);
二、选择时基单元的时钟源
定时中断--选择内部时钟源(上电后默认使用内部时钟,所以该步骤可省略)
TIM_InternalClockConfig(TIM2); // 选择内部时钟
三、配置时基单元
配置预分频器、自动重装器、计数模式
公式
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)
= CK_PSC / (PSC + 1) / (ARR + 1)
经典三步
即定义结构体,结构体变量赋值,结构体初始化
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIVx; // x分频(x为1,2或4)
TIM_TimeBaseInitStruct.TIM_CounterMode = ; // 计数器模式
TIM_TimeBaseInitStruct.TIM_Period = ; // 这玩意是ARR(范围0~65535)
TIM_TimeBaseInitStruct.TIM_Prescaler = ; // 这玩意是PSC (范围0~65535)
// ARR取10000-1,PSC取7200-1的情况下为1s
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = ; // 重复计时器(高级定时器才有)
TIM_TimeBaseInit(TIMx,&TIM_TimeBaseInitStruct);
四、配置输出中断控制
允许更新中断输出到NVIC
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);
五、配置NVIC
经典三步+一个优先级分组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_x); // 优先级分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = ; // 定时器在NVIC里的通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 开启/关闭
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ; // 响应优先级
NVIC_Init(&NVIC_InitStructure);
六、运行控制
启动定时器
TIM_Cmd(TIMx, ENABLE);
编写中断函数
void TIM2_IRQHandler(void) // 名字固定(以TIM2为例)(在启动文件里找)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) // 获取中断标志位(以更新中断标志位为例)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 清除标志位
}
}
部分API
最终实验
定时器定时中断计数
实验现象详情看江协科技stm32-6-2
TIM模块
#include "stm32f10x.h" // Device header
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);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
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)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/
主函数模块
#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);
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num ++; // 计数
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
Comments NOTHING