Timer定时器对输入得到时钟进行计数,在计数达到设定值时触发中断。
时基单元 = 计数器 + 预分频器 + 自动重装寄存器
定时器功能:
(1)定时中断功能、内外时钟源选择
(2)输出比较
(3)输入捕获/主从触发模式
(4)编码器接口
定时器分类:
基本定时器 + 通用定时器 + 高级定时器
STM32F103C8T6芯片的定时器资源:TIM1, TIM2, TIM3, TIM4
基本定时器的结构图:
(1)基本定时器只能选择内部时钟:系统主频72MHz
(2)时基单元: 预分频器 + 计数器 + 自动重装寄存器
( 输出频率 = 输入频率/ (PSC + 1) , 实际分频系数等于PSC+1)
(3)更新中断:计数器的值等于自动重装寄存器值,通过NVIC触发CPU处理中断函数
(4)更新事件:计数器的值等于自动重装寄存器值,触发内部其他电路工作,但不会触发中断。 主模式:更新事件-->主模式映射到TRGO-->DAC。
通用定时器的结构图:
(1)通用定时器:内部时钟(系统主频72MHz) + 外部时钟(外部时钟模式1、外部时钟模式2)
外部时钟模式1:触发输入外部时钟(ETR引脚、ITR信号、CH1引脚边沿、CH1引脚、CH2引脚) -----> TRGI ----->从模式控制器 ----->时基单元
外部时钟模式2:TIMx_ETR引脚上的外部时钟 ----->极性选择、滤波、边沿检测和预分频 ------> 触发控制器----->时基单元
(2)计数模式:向上计数 + 向下计数 + 中央对齐计数
(3)输出比较寄存器+输出比较电路:4个通道CH1、CH2、CH3和CH4引脚,用于输出PWM波形驱动电机
(4)输入捕获寄存器+输入捕获电路:4个通道CH1、CH2、CH3和CH4引脚,用于测量输入方波的频率
高级定时器的结构图:
(1)增加重复次数计数器, 每隔几次计数周期更新一次
(2)死区生成电路 + 互补输出引脚:输出互补的PWM波,用于驱动三相无刷电机
(3)刹车输入功能:给电机驱动提供安全保障
定时中断基本结构图:
RCC内部时钟 ---> 内部时钟模式 ---> 时基单元
ETR外部时钟 ---> 外部时钟模式2 ---> 时基单元
ETR外部时钟 | ITRx其他定时器 | TIx捕获通道 ---> 外部时钟模式1 ---> 时基单元
预分频器时序图
计数器时序图
计数器溢出时,产生更新事件脉冲(UEV) + 更新中断标志位(UIF)
计数器溢出频率 CK_CNT_OV = CK_CNT / (ARR+1) = CK_PSC / (PSC + 1) / (ARR + 1)
计数器有无预装时序图
计数器有预装时序图(自动重装缓冲寄存器)
RCC时钟树(ST公司已在SystemInit函数中配置)
定时器初始化:
(1)RCC开启时钟
(2)选择时基单元的时钟源
(3)配置时基单元
(4)配置输出中断控制
(5)配置NVIC
(6)配置运行控制,使能计数器
内部定时器中断实验
定时器模块文件Timer.c
#include "stm32f10x.h" // Device header
extern uint16_t uiNum;
void Timer_Init(void)
{
/* RCC开始TIM2定时器的时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
/* RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
* RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
* RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
* RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4,
* RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP,
* RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
* RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14
*/
/* 选择时基单元的时钟 */
TIM_InternalClockConfig(TIM2);
/* 配置时基单元 */
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Prescaler = 7200-1; //预分频值
TIM_TimeBaseInitStruct.TIM_Period = 10000-1; // 自动重装值
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV2;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
/* 使能更新中断至NVIC */
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // TIM_IT_Update 表示更新中断
/* 配置NVIC */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStruct);
/* 启动定时器 */
TIM_Cmd(TIM2, ENABLE);
}
void TIM2_IRQHandler(void)
{
if( SET == TIM_GetITStatus(TIM2, TIM_IT_Update) )
{
uiNum ++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
定时器模块文件Timer.h
#ifndef __TIMER_H__
#define __TIMER_H__
extern void Timer_Init(void);
#endif
主函数文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
uint16_t uiNum = 0;
int main(void)
{
OLED_Init();
Timer_Init();
while(1)
{
OLED_ShowNum(1,1,uiNum, 4);
}
}
标签:定时器,中断,APB1Periph,NVIC,TIM,时钟,RCC
From: https://www.cnblogs.com/czy363/p/18684319