嵌入式学习日志————TIM定时中断之定时器定时中断
前言
本篇学习日志是今天学习的内容(第二次学),有任何问题,欢迎指正!
正文
一、理论知识
1.TIM简介
2.定时器类型
1)计数模式
向上计数模式(最常用),向下计数模式,中心对齐模式。通用计时器和高级定时器支持三种模式,基本定时器只支持向上计数模式。
2)基本定时器
注意:基本定时器只能连接内部时钟,所以进入时基单元的频率为72 MHz。
预分频器_PSC(16位):写入0时,输出频率 = 输入频率;写入1,输出频率 = 输入频率/2;写入n时,输出频率 = 输入频率/(n+1)。
计数器_CNT(16位):对预分频后的计数时钟进行计数。计数时钟每来一个上升沿,计数器值加一。
自动重装寄存器_ARR(16位):存的是我们写入的计数目标。当计数值等于自动重装值,代表计时时间到了,该寄存器就会产生一个中断信号(更新中断),同时清零计数器。
主模式触发DAC:让内部硬件在不受程序都控制下实现自动运行。看上图。只需要把更新事件通过主模式映射到TRGO,TRGO就会直接触发DAC
3)通用定时器
→定时器级联的功能
这里的ITR0~ITR3分别来自其他四个定时器的TRGO
具体链接方式如下↓
时钟输入的几个路径↓
编码器接口:读取正交编码器的输出波形
输出比较电路:可以用于输出PWM波形,驱动电机↓
输入捕获电路:可以用于测量输入方波的频率↓
捕获/比较寄存器:输入捕获电路和输出比较电路共用↓
4)高级定时器
重复计数器:可以实现没个几个计数周期才发生一次更新事件和更新中断
DTG(死区生成电路):在开关切换的瞬间,产生一定时长的死区,防止直通现象。
互补输出:右边的输出引脚由原来的一个变为了两个互补的输出,可以输出一堆互补的PWM波——为了驱动三相无刷电机。
刹车输入功能:给电机驱动提供安全保障。如果BKIN产生刹车信号,或者内部时钟失效,产生故障,控制电路就会自动切断电机的输出,防止意外发生
3.定时中断基本结构
1)预分频器时序
预分频缓冲器:在计数中途改变了预分频值,计数频率仍然会保持原来的频率,直到本轮计数完成,产生更新时间以后,在下一轮计数时,改变后的分频值才会起作用。
2)计数器时序
4.时钟树
CSS(时钟安全系统Clock Security System):负责切换时钟,可以监测外部时钟运行状态,一旦外部时钟失效,他就会自动把外部时钟切换回内部时钟,保证系统时钟的运行,防止程序卡死造成事故
二、实验
1.库函数
1)恢复初始配置
void TIM_DeInit(TIM_TypeDef* TIMx)
2)时基单元初始化(选择定时器,结构体(包含了配置时基单元的一些参数))
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
3)把结构体变量赋一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
4)使能计数器(选择定时器,使能/失能)——对应基本结构图中的运行控制
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
5)使能中断输出信号(选择定时器,选择配置哪个终端输出,使能/失能)——对应结构图中的中断输出控制
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
6)选择内部时钟
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
7)选择TIRx其他定时器的时钟(选择要配置的定时器,选择要接入哪个其他的定时器)
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
8)选择TIx捕获通道的时钟(选择定时器,选择TIx具体的某个引脚,输入的极性,输入的滤波器)
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx,uint16_tTIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);
9)选择ETR通过外部时钟模式1输入的时钟(定时器,外部触发预分频器,极性,滤波器)
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
极性:反向——低电平和下降沿有效;不反向——高电平和上升沿有效。
10)选择ETR通过外部时钟模式2输入的时钟(定时器,外部触发预分频器,极性,滤波器)
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
11)单独用于配置ETR引脚的预分频器、极性、滤波器等参数的
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
12)单独写入预分频值(定时器,写入的预分频值,写入的模式)
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
13)改变计数器的计数模式(定时器,新的计数器模式)
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
14)自动重装器预装功能配置(定时器,使能/失能)
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
15)给计数器写入一个值
void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
16)给自动重装器写一个值,手动给一个自动重装值
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);
17)获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
18)获取当前预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
2.接线图
3.代码
(1)main.c
#include "stm32f10x.h" // Device header
#include "delay.h"
#include "OLED.h"
#include "Timer.h"uint16_t Num;int main( void)
{OLED_Init();Tmier_Init(); OLED_ShowString(1,1,"Num:");while(1){OLED_ShowNum(1,5,Num,5);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);}
}
2.Timer.h
#ifndef __TIMER_H
#define __TIMER_Hvoid Tmier_Init(void);#endif
2.Timer.c
#include "stm32f10x.h"void Tmier_Init(void)
{RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//选择内部时钟TIM_InternalClockConfig(TIM2);//初始化时基单元TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; //不在时基单元TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period = 10000-1; //ARR-自动重装器TIM_TimeBaseInitStruct.TIM_Prescaler = 720-1; //PSC-预分频器TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//清除更新中断标志位TIM_ClearFlag(TIM2,TIM_FLAG_Update);//使能中断TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//配置NVICNVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);//启动定时器TIM_Cmd(TIM2,ENABLE);}
还会持续更新哒~