TIM简介
16位计数器,预分频器,自动重装寄存器的时基单元, 65536.
类型 | 编号 | 总线 | 功能 |
---|---|---|---|
高级定时器 | TIM1,TIM8 | APB2 | 拥有所有功能,额外有重复计数器,死区生成,互补输出,刹车输入等 |
通用定时器 | TIM2,TIM3, TIM4,TIM5 | APB1 | 拥有基本功能,额外具有内外时钟源选择,输入捕获,输出比较,编码器接口,主从模式触发等功能 |
基本定时器 | TIM6,TIM7 | APB1 | 拥有定时中断,主模式触发DAC功能 |
- 预分频器
- 写0 为 1分频 为输出频率=输入频率/1 =72MHz
- 写1 为 2 分频 为输出频率=输入频率/2 =36MHz
- 预分频为16位 最大值位65535 也就是 65536 分频
通用定时器
- 外部时钟源
-
TIMx_ETR (PA0) ------ 输入 方波信号
– >| 配置 极性选择,边沿检测和预分频器 |–>输入滤波 【对外部波形进行修整】- 分两路
+【外部时钟模式2】 ETRF 进入控制器 选择作为时基单元
想在ETR外部引脚提供时钟 / 对ETR时钟进行计数,把定时器当做计数器
+ 【外部时钟模式1】TRGI(TRIGGER IN)主要作为触发输入来使用的,触发输入可以触发定时器的从模式 {* 之后在说,本节当成外部时钟讨论}, 或者 当作外部时钟 使用
1. ETR
2. ITR 【时钟信号来自其他定时器】{从触发器的 TRGO 来的}
可以 实现 定时器的级联 功能
3. TI1F_ED 连接 输入捕获单元的 CH1 {ED为边沿的意思 说明这一路时钟 上升沿和下降沿均有效
4. TI1FP1 和 TI2P2获得
时基单元: 预分频器 计数器 自动重装器
- 分两路
-
高级定时器
为了三相电机驱动
- 死区 防止 互补输出的pwm驱动桥臂时 在开关切换的瞬间,桥臂上下同时关闭,产生死去 防止造成短暂的直通现象
- 刹车输入 (为电机提供保障) 刹车信号 或者时钟失效 切断电源
基本结构
- 计数器计数频率
CK_CNT= CK_PSC(PSC+1)
CK_CNT 定时器时钟
PSC预分频 - 计数器溢出频率
CK_CNT_OV=CK_CNT/(ARR+1)
=CK_PSC/(PSC+1)/(ARR+1)
影子寄存器
在更新事件的时候 更新重装寄存器
思路
第一步:RCC开启时钟
第二步:选择时基单元的时钟源
第三步:配置时基单元:预分频器,自动重装器,计数模式,等等(一个结构体)
第四步:配置输出中断控制,允许更新中断输出到NVIC
第五步:配置NVIC在NVIC打开定时器中断的通道,并分配一个优先级。
第六步:运行控制 使能一下计数器,
最后:定时器的中断函数
常用讲解
- 恢复缺省配置
void TIM_DeInit(TIM_TypeDef* TIMx);
- 时基单元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx,/*选择某一个定时器*/ TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct/*结构体*/);
- 给结构体赋一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
- 使能计数器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
- 中断输出控制
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
步骤
- 时钟源选择:
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
uint16_t TIM_ICPolarity, uint16_t ICFilter);
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter);
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter);
- 时基单元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx,/*选择某一个定时器*/ TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct/*结构体*/);
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);//给结构体赋一个默认值
- 中断输出控制
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
- NVIC
NVIC - 运行控制
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
可以单独修改一些值
- 单独写预分频值的
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler,/*写入的预分频值*/
uint16_t TIM_PSCReloadMode/*写入的模式*/);
写入的模式:选择在更新事件生效;或者:手动写入更新事件,立即生效。
- 改变计数器的计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode/*选择新的计数器模式*/);
- 自动重装器预装功能装置
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState/* 使能还是失能*/);
- 给计数器写入一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
- 给自动重装器写入一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
- 获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
- 获取当前的预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
- 获取标志位和清除标志位
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
内部例程:
TIMER.c
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择一分频
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装器(一秒)
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//预分频器的值(1秒)
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器,高定才有
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//手动清除标志位,避免刚初始化进中断,例子:没有时 计数器显示从0001开始 ,正常:0000开始
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
// 配置中断函数,为别的文件使用
/*
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
//比如 NUM++ ,计数器加一 需要写声明 :extern --- 跨文件的变量 或 写到主函数//
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/
外部时钟
TIMER.c
#include "stm32f10x.h" // Device header
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU//上拉输入;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF/*选择不分频*/, TIM_ExtTRGPolarity_NonInverted/*外部触发的极性:2.不反向 高电平有效*/, 0x0F/*外部触发滤波器*/);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);
}
uint16_t Timer_GetCounter(void)//实时看一下计数器的值 封装函数
{
return TIM_GetCounter(TIM2);
}
/*
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/