TIM(Timer) 定时器
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz(系统主频)计数时钟下可以实现最大59.65s的定时(72M/65536/65536取倒数)
不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
类型 |
编号 |
总线 |
功能 |
高级定时器 |
TIM1、TIM8 |
APB2 |
拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能 |
通用定时器 |
TIM2、TIM3、TIM4、TIM5 |
APB1 |
拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能 |
基本定时器 |
TIM6、TIM7 |
APB1 |
拥有定时中断、主模式触发DAC的功能 |
计数器寄存器(TIMx_CNT) 由预分频器的时钟输出CK_CNT驱动, 当设置了控制寄存器TIMx_CR1中的计数器使能位(CEN)时, CK_CNT才有效, 16位寄存器, 可计数范围为0~65535
预分频器(TIMx_PSC) 16位寄存器(可设置0~65535), 可以将计数器的时钟频率按1~65536之间的任意值分频。这个控制寄存器带有缓冲器, 它不能够在工作时被改变。新的预分频器参数再下一次更新事件到来时被采用
自动重装载寄存器(TIMx_ARR) 是预先装载的, 写或读自动重装载寄存器将访问预装载寄存器。根据在TIMx_CR1中的自动重装载预装载使能位(ARPE)的设置, 预装载寄存器的内容被立即或在每次更新事件(UEV)时传送到其影子寄存器。也是一个16位寄存器, 可设置范围为0~65535,当计数值等于自动重装值时, 产生中断并清零计数器
Note: 由计数器寄存器的计数范围、预分频器的分频范围和自动重装载寄存器的可设置范围, 可以计算:最大定时为59.65s
使用DAC时, 可能会用DAC输出一段波形
把定时器的更新事件映射到TRGO(Trigger Out)的位置, TRGO直接接到DAC的触发转换引脚上, 这样定时器的更新就不需要再通过中断来触发DAC转换了
好处避免了主程序处于频繁被中断的状态(该状态会影响到其他中断的运行)
STM32通用定时器主要包括1个外部触发引脚(TIMx_ETR), 4个输入/输出通道(TIMx_CH1, TIMx_CH2, TIMx_CH3, TIMx_CH4), 一个内部时钟(CK_INT), 一个触发控制器、1个时基单元(由预分频器PSC、自动重装载寄存器ARR和计数器CNT组成) ..( 预分频器 Prescaler)
定时器时钟可由下列时钟源提供:
内部时钟(CK_INT)
外部时钟模式1(外部输入引脚TIx), 图中为从TIMx_CHx往右边看, 具体位置参考引脚定义表
外部时钟模式2(外部触发输入ETR), 信号来源TIMx_ETR外部触发引脚, 具体位置参考引脚定义表
内部触发输入(ITR, 使用一个定时器作为另一个定时器的预分频器, 也叫级联的方式) 比如: 先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,再初始化TIM2, 选择ITR2(对应TIM3的TRGO), 选择时钟为内部触发输入,这样TIM3的更新事件就可以驱动TIM2的时基单元,也就实现了定时器的级联
向上计数(最常用)
向下计数
中央对齐模式(向上/向下计数)
可以实现每隔几个计数周期,才发生一次更新事件和更新中断, 相当于对输出的更新信号又做了一次分频 最大定时时间59.65*65536
死区生成电路: 产生一定时长的死区, 让桥臂的上下管全部关断, 防止直通现象。
直通现象: 电子管是利用阴极和阳极之间产生束流来实现电流控制,而所谓直通现象就是阳极与阴极直接连通了。
目的: 为了避免开关切换瞬间, 由于器件的不理想, 造成短暂的直通现象
前三路输出引脚由原来的一个, 变为了两个互补输出, 可以输出一对互补的PWM波,(目的是为了驱动三相无刷电机)
目的: 给电机驱动提供安全保障, 如果外部引脚BKIN(Break IN) 产生了刹车信号, 或者内部时钟失效, 产生了故障, 控制电路就会自动切断电机的输出, 防止意外发生
运行控制: 一些寄存器可以控制时基单元的运行
左边部分为时基单元提供时钟,也可通过配置相应寄存器选择时钟源和模式
时基单元产生的中断信号会先在状态寄存器里配置一个中断标志位, 标志位会通过中断输出控制(中断输出的允许位), 到NVIC申请中断
CK_PSC:一般为72MHz
CNT_EN:计数器使能,高电平正常允许,低电平停止
CK_CNT:计数器时钟
计数器寄存器:跟随时钟的上升沿不断自增
预分频寄存器缓冲机制:
预分频缓冲器(影子寄存器):
真正起作用的寄存器
机制过程:
假设在某时刻,把预分频寄存器由0改成1,若计数到一半,则前半部分和后半部分的计数频率就不一致了。而在STM32中,定时器比较严谨,当计数计一半时改变了分频值,这个变化不会立刻生效,而是等本次计数周期结束时,产生了更新事件,预分频寄存器的值才会被传递到缓冲寄存器里,才会生效,所以真正起作用的寄存器是影子寄存器
预分频计数器:
预分频器内部实际上也是靠计数分频,当预分频值为0时,计数器就一直为0,直接输出原频率; 当预分频值为1时,计数器就0、1、0、1这样计数,在回到0时输出一个脉冲, 这样输出频率就是输入频率的2分频
计数器计数频率: CK_CNT = CK_PSC / (PSC + 1)
计数器溢出频率: CK_CNT_OV = CK_CNT / (ARR +1) = CK_PSC / (PSC + 1) / (ARR + 1)
Note: 程序中主函数之前还会执行SystemInit函数,这个函数就是用来配置时钟树的
Attention: 主频经过2分频后到APB1为36MHz, 到TIM2~7前频率又×2,因此TIM2~7的频率还是72MHz,而APB2的频率为72MHz
// RCC开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// 选择时钟源
TIM_InternalClockConfig(TIM2); // 内部时钟
可供选择的时钟源在stm32f10x_tim.h中有定义, 感兴趣可以参考STM32技术手册
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); // 外部时钟模式1
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); // 外部时钟模式2
// 配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 内部时钟分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; // 计数模式
TIM_TimeBaseInitStructure.TIM_Period=50000-1; // 加载到自动重装寄存器的值
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1; // 预分频的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; // 重复计数器的值
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); // 调用初始化函数
TIM_ClearFlag(TIM2, TIM_FLAG_Update); // 清除标志
最后一步清除标志,解决了复位上电后Num不从0开始而从1开始的问题
原因是TIM_TimeBaseInit() 时基初始化函数在最后面, 手动触发了一次更新事件, 导致标志位也被设置, 因此上电后Num已经加了一次,在该函数外面将标志位清除即可解决问题。
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
uint16_t tmpcr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));
assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));
tmpcr1 = TIMx->CR1;
if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||
(TIMx == TIM4) || (TIMx == TIM5))
{
/* Select the Counter Mode */
tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
}
if((TIMx != TIM6) && (TIMx != TIM7))
{
/* Set the clock division */
tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
}
TIMx->CR1 = tmpcr1;
/* Set the Autoreload value */
TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;
/* Set the Prescaler value */
TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))
{
/* Set the Repetition Counter value */
TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;
}
/* Generate an update event to reload the Prescaler and the Repetition counter
values immediately */
TIMx->EGR = TIM_PSCReloadMode_Immediate; // 问题在这里
}
// 使能更新中断
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// 以下为TIM_ITConfig函数的注释
/**
* @brief Enables or disables the specified TIM interrupts.
* @param TIMx: where x can be 1 to 17 to select the TIMx peripheral.
* @param TIM_IT: specifies the TIM interrupts sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg TIM_IT_Update: TIM update Interrupt source
* @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
* @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
* @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
* @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
* @arg TIM_IT_COM: TIM Commutation Interrupt source
* @arg TIM_IT_Trigger: TIM Trigger Interrupt source
* @arg TIM_IT_Break: TIM Break Interrupt source
* @note
* - TIM6 and TIM7 can only generate an update interrupt.
* - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,
* TIM_IT_CC2 or TIM_IT_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.
* - TIM_IT_Break is used only with TIM1, TIM8 and TIM15.
* - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.
* @param NewState: new state of the TIM interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
// 配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC优先级分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; // 中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; // 响应优先级
NVIC_Init(&NVIC_InitStructure);
这里和之前一样, 就不详细解释了
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
操作的是上图的运行控制部分, 控制定时器的运行
void Timer_Init(void)
{
// RCC开启时钟
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=50000-1; // 加载到自动重装寄存器的值
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-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
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC优先级分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; // 中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; // 响应优先级
NVIC_Init(&NVIC_InitStructure);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
return;
}
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Num++;
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
这里我们将中断函数放到main.c下, 方便操作Num变量
也可在Timer.c 用extern指令引入Num变量
#include "stm32f10x.h"
#include "OLED.h"
#include "Timer.h"
// 定时器定时中断
// 2023年3月16日12:21:33
uint16_t Num;
int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1, 1, "Num:");
OLED_ShowString(2, 1, "CNT:");
while(1)
{
OLED_ShowNum(1, 5, Num, 5);
OLED_ShowNum(2, 5, TIM_GetCounter(TIM2), 5);
}
}
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Num++;
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
#include "stm32f10x.h"
// extern uint16_t Num;
void Timer_Init(void)
{
// RCC开启时钟
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=50000-1; // 加载到自动重装寄存器的值
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-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
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC优先级分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; // 中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; // 响应优先级
NVIC_Init(&NVIC_InitStructure);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
return;
}
/*
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Num++;
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/
#include "stm32f10x.h"
#include "OLED.h"
#include "Timer.h"
// 定时器外部中断
// 2023年3月16日14:26:54
uint16_t Num;
int main(void)
{
OLED_Init();
Timer_Init();
OLED_ShowString(1, 1, "Num:");
OLED_ShowString(2, 1, "CNT:");
while(1)
{
OLED_ShowNum(1, 5, Num, 5);
OLED_ShowNum(2, 5, TIM_GetCounter(TIM2), 5);
}
}
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Num++;
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
#include "stm32f10x.h"
// extern uint16_t Num;
void Timer_Init(void)
{
// RCC开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置GPIO
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);
// 选择时钟 外部时钟模式1
TIM_ETRClockMode1Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);
// 配置时基单元
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
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC优先级分组
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; // 中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // 抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1; // 响应优先级
NVIC_Init(&NVIC_InitStructure);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
return;
}
/*
void TIM2_IRQHandler(void)
{
// 判断标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update)==SET)
{
Num++;
// 清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/
注意: 这里与江科大教程中不同, 时钟源采用的是外部时钟模式1
这是因为, PA0除了支持TIM2_ETR(外部时钟模式2) 也支持 TIM2_CH1(外部时钟模式1)
函数原型 |
功能 |
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); |
根据TIM_TimeBaseInitStruct中指定的参数, 初始化TIMx的时基单位 |
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); |
把TIM_TimeBaseInitStruct中的每一个参数按缺省值填入 |
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); |
使能或失能TIMx外设 |
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); |
使能或失能指定的TIM中断 |
void TIM_InternalClockConfig(TIM_TypeDef* TIMx); |
设置TIMx内部时钟 |
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource); |
设置TIMx内部触发为外部时钟模式 |
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, uint16_t TIM_ICPolarity, uint16_t ICFilter); |
设置TIMx触发为外部时钟 |
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); |
配置TIMx外部时钟模式1 |
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); |
配置TIMx外部时钟模式2 |
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter); |
配置TIMx外部触发 |
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode); |
设置TIMx预分频 |
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode); |
设置TIMx计数器模式 |
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState); |
使能或失能TIMx在ARR上的预装载寄存器 |
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter); |
设置TIMx计数器寄存器值 |
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload); |
设置TIMx自动重装载寄存器值 |
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx); |
获取TIMx计数器的值 |
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx); |
获取TIMx预分频值 |
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); |
检查指定的TIM标志位设置与否 |
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG); |
清除TIMx的待处理标志位 |
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT); |
检查指定的TIM中断发生与否 |
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT); |
清除TIMx的中断待处理位 |
Note: ClearFlag()和ClearITPendingBit()的区别, 请参考: http://t.csdn.cn/0KYkq
http://t.csdn.cn/0KYkq
嵌入式单片机STM32原理及应用(机械工业出版社)
[6-2] 定时器定时中断&定时器外部时钟_哔哩哔哩_bilibili