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);
	}	
}
posted on 2025-01-21 22:45  轩~邈  阅读(111)  评论(0)    收藏  举报