一、STM32定时器简介
二、STM32定时器类型
(1)基本定时器框图
(2)通用定时器框图
(3)高级定时器(与通用比较)
三、定时中断基本结构
四、预分频器时序
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
五、定时器定时中断代码
(1)恢复缺省配置
void TIM_DeInit(TIM_TypeDef* TIMx);
(2)时基单元初始化*
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
(3)把结构体变量付一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
(4)使能计数器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
(5)使能中断输出信号
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
(6)选择内部时钟
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
(7)选择ITRX其他定时器的时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
(8)选择TIx捕获通道时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);
(9)选择ETR通过外部时钟模式1的时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
(10)选择ETR通过外部时钟模式2的时钟
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx,uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
(11)改写预分频值
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
(12)改变计数器计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
(13)自动重装器预装功能配置
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
(14)给计数器写入一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
(15)给自动重装器写一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
(16)获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
(17)获取当前预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
(18)获取标志位与清楚标志位
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);
(19)代码编写
#include "stm32f10x.h" // Device header
#include "OLED.h"
uint16_t Num=0;
void TimerInit(void);
int main(void)
{
TimerInit();
OLED_Init();
while(1)
{
OLED_ShowNum(1,7,Num,5);
}
}
/***************************************************************
* @brief void TimerInit(void)
* @param void
* @note 初始化中断引脚
* @Sample TimerInit();
**************************************************************/
void TimerInit(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
TIM_InternalClockConfig(TIM2);//选用内部时钟
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式
TIM_TimeBaseInitStruct.TIM_Period=10000-1;//周期ARR自动重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler=7200-1;//PSC预分频器的值
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//重复计数器的值
//定时频率=72M/(PSC+1)*(ARR+1)
//定时时间=1/[72/(PSC+1)]*(ARR+1)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;//中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;//
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;//
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择分组2
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM2,ENABLE);//启动定时器
}
/***************************************************************
* @brief void TIM2_IRQHandler()
* @param void
* @note 定时器中断函数
* @Sample 无
**************************************************************/
void TIM2_IRQHandler()
{
if( TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//判断中断标志位是否被置一
{
Num++;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
六、定时器外部时钟代码
#include "stm32f10x.h" // Device header
#include "OLED.h"
uint16_t Num=0;
void TimerInit(void);
uint16_t TimerGetCounter(void);
int main(void)
{
TimerInit();
OLED_Init();
while(1)
{
OLED_ShowNum(1,7,Num,5);
}
}
/***************************************************************
* @brief void TimerInit(void)
* @param void
* @note 初始化中断引脚
* @Sample TimerInit();
**************************************************************/
void TimerInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0X00);//选用外部ETR模式2时钟
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式
TIM_TimeBaseInitStruct.TIM_Period=10-1;//周期ARR自动重装载值
TIM_TimeBaseInitStruct.TIM_Prescaler=1-1;//PSC预分频器的值
TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//重复计数器的值
//定时频率=72M/(PSC+1)*(ARR+1)
//定时时间=1/[72/(PSC+1)]*(ARR+1)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;//中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;//
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;//
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;//
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择分组2
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM2,ENABLE);//启动定时器
}
uint16_t TimerGetCounter(void)
{
return TIM_GetCounter(TIM2);
}
/***************************************************************
* @brief void TIM2_IRQHandler()
* @param void
* @note 定时器中断函数
* @Sample 无
**************************************************************/
void TIM2_IRQHandler()
{
if( TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)//判断中断标志位是否被置一
{
Num++;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}