在所有的定时器中,TIM1和TIM8的功能最多。通用和基本定时器在结构上都有一定的简化。所以本章就以高级定时器为例讲解:
定时器在检测、控制领域有广泛应用,可作为应用系统运行的控制节拍,实现信号检测、控制、输入信号周期测量或电机驱动等功能。在很多的应用场合,都会用到定时器,因此定时器系统是现在微控制器中的一个不可缺少的组成部分。
定时器有很多用途,包括基本定时功能、生成输出波形(输出比较、PWM和带死区插入的互补PWM)和测量输入信号的脉冲宽度(输入捕抓)等.
STM32F429共有14个定时器,包括2个高级定时器(TIM1、TIM8),10个通用定时器(TIM2-5、TIM9~14,以及2个基本定时器分别是TIM6和TIM7)。这里面2和5是32位定时器,,其他的都是16位的。具体可看下图:
定时器计数需要计数器时钟,可由下列时钟源提供:
① 内部时钟(CK_INT)源模式。
② 外部时钟源模式1:外部输入引脚。
③ 外部时钟源模式2:外部触发输入ETR。
④ 编码器模式。
具体如下图结构:
将TI1FP1和TI2FP2信号的电平状态的变化作为定时器时钟源。这一模式主要用于测量光电正交编码器输出脉冲数,以及测量电机转速和方向。
STM32F429微控制器的高级定时器和通用定时器中有输入捕抓通道和输出比较通道。
1 ) 、频率测量、PWM信号周期、占空比测量,以及霍尔传感器输出信号测量等。
2 ) 、测量光电正交编码器输出信号,实现电机转速的测量。
实现PWM信号输出、6步PWM信号生成,用于电机控制。
在使用输入捕抓通道1,当检测到TI1引脚上输入的信号出现上升沿时,将计数器的值捕抓到TIMx_CCR1中。具体操作步骤如下:
1.选择输入捕抓模式,IC1映射到TI1上
2.设定输入信号边沿检测的滤波功能(防抖动)
3.选择边沿触发方式
4.对输入预分频器进行编程
5.使能输入捕抓功能
6.设置捕抓中断和DMA请求
当连续两次捕抓同一输出信号的连续两个边沿跳变,两次得到的计数寄存器值分别为C1和C2(假设C1和C2计数期间没有溢出事件),那么这一输入信号的周期:
((C2-C1)/CK_CNT)/输入捕抓通道预分频系数。
在编码器模式下,计数器会根据增量编码器的速度和方向自动进行修改,因此计数器内容始终表示编码器的位置。计数方向对应于定时器所连传感器的轴旋转方向。
不同编码器模式下的计数方式如下图:
①使能定时器时钟。
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();
①使能定时器时钟和GPIO时钟
②初始化定时器输入捕抓通道引脚
③初始化定时器测量时钟
④设置输入捕抓通道
⑤选择定时器复位触发源
⑥开启定时器中断
⑦使能定时器
⑧编写中断服务函数
①使能定时器时钟
②初始化定时器比较输出通道引脚
③定义PWM波的周期
④设置比较输出通道
⑤使能定时器
⑥开启定时器中断
①使能定时器时钟
②初始化定时器编码器接口输入通道引脚
③定义编码器接口的计数值溢出值
④设置定时器编码器接口模式
⑤开启定时器中断
⑥使能定时器
⑦编写测量速度应用程序
#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**********************/