定时器功能:定时 定时比较(PWM波) 输入捕获 互补输出(电机)
定时器分类:基本定时器 通用定时器 高级定时器
定时器资源:429有2个高级定时器 10个通用定时器 2个基本定时器
计数器分辨率:计数最大值 2^16/32
基本定时器
计数器16位,只能向上计数 只有TIM6 TIM7
没有外部GPIO,是内部资源,只能用来定时
时钟来自PCLK1 可以实现1~65535 分频
定时时间计算
PSC = 9000-1,定时频率 = 90M/(PSC+1) = 10000HZ
ARR = 4999 从0计数到4999 共计数5000次
T = 5000/10000 = 0.5s
TIM结构体
uint16_t | TIM_ClockDivision 外部输入时钟分频因子,基本定时器没有 |
uint16_t | TIM_CounterMode 计数模式:向上计数/向下计数 |
uint32_t | TIM_Period 自动装载值 |
uint16_t | TIM_Prescaler 分频因子 |
uint8_t | TIM_RepetitionCounter 重复计数器,基本定时器没有 |
基本定时器只需要配置
TIM_Prescaler TIM_CounterMode(默认向上计数) TIM_Period
.c文件
static void TIMx_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
// 设置中断组为0
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
// 设置中断来源
NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQn;
// 设置抢占优先级
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// 设置子优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void TIM_Mode_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
// 开启TIMx_CLK,x[6,7]
RCC_APB1PeriphClockCmd(BASIC_TIM_CLK, ENABLE);
/* 累计 TIM_Period个后产生一个更新或者中断*/
//当定时器从0计数到4999,即为5000次,为一个定时周期
TIM_TimeBaseStructure.TIM_Period = 5000-1;
//定时器时钟源TIMxCLK = 2 * PCLK1
// PCLK1 = HCLK / 4
// => TIMxCLK=HCLK/2=SystemCoreClock/2=90MHz
// 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=10000Hz
TIM_TimeBaseStructure.TIM_Prescaler = 9000-1;
// 初始化定时器TIMx, x[2,3,4,5]
TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
// 清除定时器更新中断标志位
TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
// 开启定时器更新中断
TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
// 使能定时器
TIM_Cmd(BASIC_TIM, ENABLE);
}
/**
* @brief 初始化基本定时器定时,1ms产生一次中断
* @param 无
* @retval 无
*/
void TIMx_Configuration(void)
{
TIMx_NVIC_Configuration();
TIM_Mode_Config();
}
.h文件
#ifndef __BASIC_TIM_H
#define __BASIC_TIM_H
#include "stm32f4xx.h"
#define BASIC_TIM TIM6
#define BASIC_TIM_CLK RCC_APB1Periph_TIM6
#define BASIC_TIM_IRQn TIM6_DAC_IRQn
#define BASIC_TIM_IRQHandler TIM6_DAC_IRQHandler
void TIMx_Configuration(void);
#endif /* __BASIC_TIM_H */
.it中断服务函数
注意:如果不清除标志位则会一直调用中断服务函数,无限循环
TIM_ClearITPendingBit(BASIC_TIM , TIM_IT_Update);
void BASIC_TIM_IRQHandler (void)
{
if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET )
{
LED1_TOGGLE;
TIM_ClearITPendingBit(BASIC_TIM , TIM_IT_Update);
}
}