9.1 定时器系统简介

在所有的定时器中,TIM1和TIM8的功能最多。通用和基本定时器在结构上都有一定的简化。所以本章就以高级定时器为例讲解:

9.1.1 定时器概述

定时器在检测、控制领域有广泛应用,可作为应用系统运行的控制节拍,实现信号检测、控制、输入信号周期测量或电机驱动等功能。在很多的应用场合,都会用到定时器,因此定时器系统是现在微控制器中的一个不可缺少的组成部分。定时器有很多用途,包括基本定时功能、生成输出波形(输出比较、PWM和带死区插入的互补PWM)和测量输入信号的脉冲宽度(输入捕抓)等.STM32F429共有14个定时器,包括2个高级定时器(TIM1、TIM8),10个通用定时器(TIM2-5、TIM9~14,以及2个基本定时器分别是TIM6和TIM7)。这里面2和5是32位定时器,,其他的都是16位的。具体可看下图:

stm32定时器模式有几种(9-玩转STM32之定时器系统)(1)

9.1.2 定时器结构

stm32定时器模式有几种(9-玩转STM32之定时器系统)(2)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(3)

TIM1和TIM8结构如下图:

stm32定时器模式有几种(9-玩转STM32之定时器系统)(4)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(5)

高级定时器内部结构图如下:

stm32定时器模式有几种(9-玩转STM32之定时器系统)(6)

9.1.3 时钟源

定时器计数需要计数器时钟,可由下列时钟源提供:① 内部时钟(CK_INT)源模式。② 外部时钟源模式1:外部输入引脚。③ 外部时钟源模式2:外部触发输入ETR。④ 编码器模式。具体如下图结构:

stm32定时器模式有几种(9-玩转STM32之定时器系统)(7)

定时器计数时钟源

stm32定时器模式有几种(9-玩转STM32之定时器系统)(8)

1.内部时钟源模式

stm32定时器模式有几种(9-玩转STM32之定时器系统)(9)

2.外部时钟源模式1

stm32定时器模式有几种(9-玩转STM32之定时器系统)(10)

3.外部时钟源模式2

stm32定时器模式有几种(9-玩转STM32之定时器系统)(11)

4.编码器模式

将TI1FP1和TI2FP2信号的电平状态的变化作为定时器时钟源。这一模式主要用于测量光电正交编码器输出脉冲数,以及测量电机转速和方向。

9.2 基本定时功能9.2.1 时基单元

stm32定时器模式有几种(9-玩转STM32之定时器系统)(12)

1、 定时器时基单元

stm32定时器模式有几种(9-玩转STM32之定时器系统)(13)

9.2.2 计数模式计数模式

stm32定时器模式有几种(9-玩转STM32之定时器系统)(14)

1、递增计数模式

stm32定时器模式有几种(9-玩转STM32之定时器系统)(15)

2、递减计数模式

stm32定时器模式有几种(9-玩转STM32之定时器系统)(16)

3、中央对齐计数模式(时钟分频因子=1 ARR=6)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(17)

9.3 捕抓/比较功能

STM32F429微控制器的高级定时器和通用定时器中有输入捕抓通道和输出比较通道

1、输入捕抓通道:

1 ) 、频率测量、PWM信号周期、占空比测量,以及霍尔传感器输出信号测量等。2 ) 、测量光电正交编码器输出信号,实现电机转速的测量。

2、输出比较通道:

实现PWM信号输出、6步PWM信号生成,用于电机控制。

9.3.1 输入捕抓/比较输出通道1、输入捕抓通道

stm32定时器模式有几种(9-玩转STM32之定时器系统)(18)

2、输出比较通道

stm32定时器模式有几种(9-玩转STM32之定时器系统)(19)

9.3.2 输入捕抓模式

stm32定时器模式有几种(9-玩转STM32之定时器系统)(20)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(21)

在使用输入捕抓通道1,当检测到TI1引脚上输入的信号出现上升沿时,将计数器的值捕抓到TIMx_CCR1中。具体操作步骤如下:

1.选择输入捕抓模式,IC1映射到TI1上2.设定输入信号边沿检测的滤波功能(防抖动)3.选择边沿触发方式4.对输入预分频器进行编程5.使能输入捕抓功能6.设置捕抓中断和DMA请求

当连续两次捕抓同一输出信号的连续两个边沿跳变,两次得到的计数寄存器值分别为C1和C2(假设C1和C2计数期间没有溢出事件),那么这一输入信号的周期:

((C2-C1)/CK_CNT)/输入捕抓通道预分频系数。

PWM波的周期测量:

stm32定时器模式有几种(9-玩转STM32之定时器系统)(22)

9.3.3 PWM输出模式

stm32定时器模式有几种(9-玩转STM32之定时器系统)(23)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(24)

比较模式:

stm32定时器模式有几种(9-玩转STM32之定时器系统)(25)

9.3.4 编码器接口模式

stm32定时器模式有几种(9-玩转STM32之定时器系统)(26)

在编码器模式下,计数器会根据增量编码器的速度和方向自动进行修改,因此计数器内容始终表示编码器的位置。计数方向对应于定时器所连传感器的轴旋转方向。不同编码器模式下的计数方式如下图:

stm32定时器模式有几种(9-玩转STM32之定时器系统)(27)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(28)

9.4 定时器典型应用步骤及常用库函数9.4.1 基本定时功能应用步骤

①使能定时器时钟。

RCC_APB1PeriphClockCmd();

②初始化定时器,配置ARR,PSC。

TIM_TimeBaseInit();

③开启定时器中断,选择中断请求事件并配置NVIC。

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); NVIC_Init();

④使能定时器。

TIM_Cmd();

⑤编写中断服务函数。

TIMx_IRQHandler();

9.4.2 输入捕抓模式应用步骤

①使能定时器时钟和GPIO时钟②初始化定时器输入捕抓通道引脚③初始化定时器测量时钟 ④设置输入捕抓通道 ⑤选择定时器复位触发源⑥开启定时器中断 ⑦使能定时器⑧编写中断服务函数

9.4.3 PWM输出应用步骤

①使能定时器时钟②初始化定时器比较输出通道引脚③定义PWM波的周期④设置比较输出通道⑤使能定时器⑥开启定时器中断

9.4.4 编码器接口应用步骤

①使能定时器时钟②初始化定时器编码器接口输入通道引脚③定义编码器接口的计数值溢出值④设置定时器编码器接口模式⑤开启定时器中断⑥使能定时器⑦编写测量速度应用程序

9.4.5 常用库函数

stm32定时器模式有几种(9-玩转STM32之定时器系统)(29)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(30)

9.5 应用实例9.5.1 定时器控制实现灯闪烁1.编程要点

stm32定时器模式有几种(9-玩转STM32之定时器系统)(31)

2.主程序

stm32定时器模式有几种(9-玩转STM32之定时器系统)(32)

3.定时器初始化函数

stm32定时器模式有几种(9-玩转STM32之定时器系统)(33)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(34)

4、定时器中断服务函数

stm32定时器模式有几种(9-玩转STM32之定时器系统)(35)

9.5.2 直流电机调速控制1.编程要点

stm32定时器模式有几种(9-玩转STM32之定时器系统)(36)

2.主程序

stm32定时器模式有几种(9-玩转STM32之定时器系统)(37)

3.定时器输出PWM波初始化函数

stm32定时器模式有几种(9-玩转STM32之定时器系统)(38)

stm32定时器模式有几种(9-玩转STM32之定时器系统)(39)

4.更改占空比

stm32定时器模式有几种(9-玩转STM32之定时器系统)(40)

5 代码

#include "bsp_tim_Encoder.h" void TIM_Config_Encoder(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM_ICInitStructure; NVIC_InitTypeDef NVIC_InitStructure; /*-------------------第1步--------------------*/ //使能定时器时钟和相关GPIO时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_GPIOC, ENABLE); /*-------------------第2步--------------------*/ //初始化定时器编码器接口输入通道引脚 /* 定时器复用引脚 */ GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM3); GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM3); /* 配置定时器输入脚 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOC, &GPIO_InitStructure); /*-------------------第3步--------------------*/ //定义编码器旋转一圈的计数值溢出值,用于计算圈数 TIM_TimeBaseStructure.TIM_Period = 4000-1; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 计数方式 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);// 初始化定时器 /*-------------------第4步--------------------*/ // 编码器模式设置 TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Falling, TIM_ICPolarity_Falling);//编码器模式3 TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;// TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 6;//滤波器值,去输入信号抖动 TIM_ICInit(TIM3, &TIM_ICInitStructure); /*-------------------第5步--------------------*/ //定时器中断配置 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; // 设置中断来源 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 设置抢占优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;// 设置子优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ClearFlag(TIM3, TIM_FLAG_Update); //清楚所有标志位 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许TIM3溢出中断 TIM_ITConfig(TIM3,TIM_IT_CC1,ENABLE); //允许TIM3通道1比较中断 /*-------------------第6步--------------------*/ TIM_SetCounter(TIM3, 0); TIM_Cmd(TIM3, ENABLE);//使能定时器 } /*********************************************END OF FILE**********************/ #include "bspl_tim_Basic.h" void TIM_Config_Basic(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; /*-------------------第1步--------------------*/ // 开启TIM2时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /*-------------------第2步--------------------*/ TIM_TimeBaseStructure.TIM_Period = 100-1; TIM_TimeBaseStructure.TIM_Prescaler = 9000-1; TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /*-------------------第3-1步--------------------*/ // 开启定时器更新中断 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); // 清除定时器更新中断标志位 TIM_ClearFlag(TIM2, TIM_FLAG_Update); /*-------------------第3-2步--------------------*/ // 设置中断组为0 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 设置中断来源 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // 设置抢占优先级 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 设置子优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /*-------------------第4步--------------------*/ // 使能定时器 TIM_Cmd(TIM2, ENABLE); } /*********************************************END OF FILE**********************/

,