目的:操作通用定时器实现基本时基
配置文件:#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"//定时器头文件
#include "misc.h"//定时器中断头文件
寄存器:参阅stm32参考手册
结构体定义:
typedef struct
{
uint16_t TIM_Prescaler; //预分频系数,对时钟源进行任意系数分频
uint16_t TIM_CounterMode; //计数模式
uint16_t TIM_Period; //计数周期
uint16_t TIM_ClockDivision; //外部时钟分频系数(这个例子里FIRE没有使用)
uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
其中参数有宏定义为
计数模式宏定义:
#define TIM_CounterMode_Up ((uint16_t)0x0000)
#define TIM_CounterMode_Down ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060)
外部分频系数宏定义:
#define TIM_CKD_DIV1 ((uint16_t)0x0000)
#define TIM_CKD_DIV2 ((uint16_t)0x0100)
#define TIM_CKD_DIV4 ((uint16_t)0x0200)
其中定时器时间的计算公式:
时间 = 1 / (预分频系数 +1/ 时钟频率)*周期,由此公式可以看出32定时器功能强大在于其预分频可以任意调节定时器时钟的频率,灵活性大大加强。
库函数:
TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct)
定时器时基初始化函数,用于将TIM_TimeBaseInitTypeDef;结构体内各项参数写入指定的寄存器,参数:定时器号,&(TIM_TimeBaseInitTypeDef;结构体定义变量名称)。
TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)清除定时器的标志位,参数:定时器号,定时器标志位。其中定时器标志位有多个,均有对应的宏定义如下:
#define TIM_FLAG_Update ((uint16_t)0x0001) 更新标志位,定时器重新计数
#define TIM_FLAG_CC1 ((uint16_t)0x0002)捕获标志位
#define TIM_FLAG_CC2 ((uint16_t)0x0004)
#define TIM_FLAG_CC3 ((uint16_t)0x0008)
#define TIM_FLAG_CC4 ((uint16_t)0x0010)
#define TIM_FLAG_COM ((uint16_t)0x0020)
#define TIM_FLAG_Trigger ((uint16_t)0x0040)
#define TIM_FLAG_Break ((uint16_t)0x0080)
#define TIM_FLAG_CC1OF ((uint16_t)0x0200)
#define TIM_FLAG_CC2OF ((uint16_t)0x0400)
#define TIM_FLAG_CC3OF ((uint16_t)0x0800)
#define TIM_FLAG_CC4OF ((uint16_t)0x1000)
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)查看中断状态,参数为定时器号,中断标志位,返回值为中断状态的值(SET or RESTET)。其中中断标志位有宏定义如下:
#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)
TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)清除定时器中断标志位
TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)定时器中断配置函数,参数:定时器号,中断标志位,使能或不使能。
TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)定时器使能函数,参数:定时器号,使能或不使能。
程序代码分析:(代码出自FIRE)
主函数中:
LED_GPIO_Config(); /* LED初始化*/
TIM2_Configuration(); /* 定时器初始化*/
TIM2_NVIC_Configuration(); /* 中断向量初始化 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);//开启定时器2时钟, 配置为72MHz
while(1) //进入大循环等待定时器中断发生
{
if ( time == 1000 ) /* 定时到1s */
{
time = 0; //计数值清零
/* LED1立刻取反 */
LED1_TOGGLE;
}
}
配置文件中:
void TIM2_NVIC_Configuration(void) //中断向量配置,由于只用到了一个,所以可以随便搞
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM2_Configuration(void) //定时器2配置
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , ENABLE);
//TIM_DeInit(TIM2);开启定时器2时钟,72MHz
TIM_TimeBaseStructure.TIM_Period=1000; //周期设为1000
TIM_TimeBaseStructure.TIM_Prescaler= 71;//预分频为71
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;//外部时钟分频,没用到
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //调用初始化函数
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清一下标志位
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能定时器中断
TIM_Cmd(TIM2, ENABLE); //使能定时器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 , DISABLE); //先关闭时钟,main函数里再打开
中断函数里:
{
if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET ) //读取中断状态
{
time++; //计数器加1
TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update); //清一下标志位
}
}