STM32通用定时器中断

STM32F1 的通用定时器是一个通过可编程预分频器(PSC,16位,1~65535)驱动的 16 位自动装载计数器(CNT)构成。STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。 使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。定时器相关的库函数主要集中在固件库文件 stm32f10x_tim.h 和 stm32f10x_tim.c 文件中。

(1)使能定时器时钟(以定时器3为例)
void TIM3_Int_Init(u16 arr,u16 psc)   //初始化函数保留重加载值arr和与分频系数psc两个入口参数
{

}
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

其中APB1和APB2中的定义如下:

/** @defgroup APB1_peripheral 
  * @{
  */

#define RCC_APB1Periph_TIM2              ((uint32_t)0x00000001)
#define RCC_APB1Periph_TIM3              ((uint32_t)0x00000002)
#define RCC_APB1Periph_TIM4              ((uint32_t)0x00000004)
#define RCC_APB1Periph_TIM5              ((uint32_t)0x00000008)
#define RCC_APB1Periph_TIM6              ((uint32_t)0x00000010)
#define RCC_APB1Periph_TIM7              ((uint32_t)0x00000020)
#define RCC_APB1Periph_TIM12             ((uint32_t)0x00000040)
#define RCC_APB1Periph_TIM13             ((uint32_t)0x00000080)
#define RCC_APB1Periph_TIM14             ((uint32_t)0x00000100)
#define RCC_APB1Periph_WWDG              ((uint32_t)0x00000800)
#define RCC_APB1Periph_SPI2              ((uint32_t)0x00004000)
#define RCC_APB1Periph_SPI3              ((uint32_t)0x00008000)
#define RCC_APB1Periph_USART2            ((uint32_t)0x00020000)
#define RCC_APB1Periph_USART3            ((uint32_t)0x00040000)
#define RCC_APB1Periph_UART4             ((uint32_t)0x00080000)
#define RCC_APB1Periph_UART5             ((uint32_t)0x00100000)
#define RCC_APB1Periph_I2C1              ((uint32_t)0x00200000)
#define RCC_APB1Periph_I2C2              ((uint32_t)0x00400000)
#define RCC_APB1Periph_USB               ((uint32_t)0x00800000)
#define RCC_APB1Periph_CAN1              ((uint32_t)0x02000000)
#define RCC_APB1Periph_CAN2              ((uint32_t)0x04000000)
#define RCC_APB1Periph_BKP               ((uint32_t)0x08000000)
#define RCC_APB1Periph_PWR               ((uint32_t)0x10000000)
#define RCC_APB1Periph_DAC               ((uint32_t)0x20000000)
#define RCC_APB1Periph_CEC               ((uint32_t)0x40000000)
 
#define IS_RCC_APB1_PERIPH(PERIPH) ((((PERIPH) & 0x81013600) == 0x00) && ((PERIPH) != 0x00))

/**
  * @}
  */
/** @defgroup APB2_peripheral 
  * @{
  */

#define RCC_APB2Periph_AFIO              ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA             ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB             ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC             ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD             ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE             ((uint32_t)0x00000040)
#define RCC_APB2Periph_GPIOF             ((uint32_t)0x00000080)
#define RCC_APB2Periph_GPIOG             ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC1              ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC2              ((uint32_t)0x00000400)
#define RCC_APB2Periph_TIM1              ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1              ((uint32_t)0x00001000)
#define RCC_APB2Periph_TIM8              ((uint32_t)0x00002000)
#define RCC_APB2Periph_USART1            ((uint32_t)0x00004000)
#define RCC_APB2Periph_ADC3              ((uint32_t)0x00008000)
#define RCC_APB2Periph_TIM15             ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM16             ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM17             ((uint32_t)0x00040000)
#define RCC_APB2Periph_TIM9              ((uint32_t)0x00080000)
#define RCC_APB2Periph_TIM10             ((uint32_t)0x00100000)
#define RCC_APB2Periph_TIM11             ((uint32_t)0x00200000)

#define IS_RCC_APB2_PERIPH(PERIPH) ((((PERIPH) & 0xFFC00002) == 0x00) && ((PERIPH) != 0x00))
/**
  * @}
  */ 

(2)初始化定时器,配置ARR,PSC
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值   
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim,参数有TIM_CKD_DIV1,TIM_CKD_DIV2,TIM_CKD_DIV4
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式,向下计数为TIM_CounterMode_Down

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

关于中断时间的计算:

Tout(溢出时间)=(ARR+1)(PSC+1) / fclk

其中,ARR为重装载值,PSC为预分配系数,fclk为系统时钟频率。 fclk / (PSC+1)其实得到的是分频后的频率,倒数后变成周期。
系统初始化的时候在默认的系统初始化函数 SystemInit 函数里面已经初始化 APB1 的时钟为 2 分频,所以 APB1 的时钟为 36M,而从 STM32 的内部时钟树图得知:当 APB1 的时钟分频数为 1 的时候,TIM2~7 的时钟为 APB1 的时钟,而如果 APB1 的时钟分频数不为 1,那么 TIM2~7 的时钟频率将为 APB1 时钟的两倍。

TIM_CounterMode 的作用:
http://blog.sina.com.cn/s/blog_76c545390100ovfj.html

(3)开启定时器中断,配置NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //在主函数main()中设置分组,设置NVIC中断分组2:2位抢占优先级,2位响应优先级
NVIC_InitTypeDef NVIC_InitStructure;

//中断优先级NVIC设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器

TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能指定的TIM3中断,允许更新中断

中断配置函数 TIM_ITConfig的说明:

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
//其中第二个参数很重要,定义如下
#define TIM_IT_Update                      ((uint16_t)0x0001)//最常用,更新中断,计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) 
#define TIM_IT_CC1                         ((uint16_t)0x0002)
#define TIM_IT_CC2                         ((uint16_t)0x0004)
#define TIM_IT_CC3                         ((uint16_t)0x0008)
#define TIM_IT_CC4                         ((uint16_t)0x0010)//都是捕获/比较中断,貌似都是平等的,即输入捕获,输出比较
#define TIM_IT_COM                         ((uint16_t)0x0020)
#define TIM_IT_Trigger                     ((uint16_t)0x0040)//触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
#define TIM_IT_Break                       ((uint16_t)0x0080)
(4)使能定时器
TIM_Cmd(TIM3, ENABLE);  //使能TIM3    

至此,初始化完成。

(5)编写中断服务函数
void TIM3_IRQHandler(void)   //TIM3中断
{
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
        {
        //各种中断服务函数内容
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  //清除TIM3更新中断标志 
        }
}

你可能感兴趣的:(STM32通用定时器中断)