新闻中心

EEPW首页>嵌入式系统>设计应用> STM32 学习笔记_TIME定时器详解1

STM32 学习笔记_TIME定时器详解1

作者: 时间:2016-11-26 来源:网络 收藏


基本的基时单元就是上面提及的这几个,下面看看3.0库是如何实习的基本使用。

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


TIM_DeInit(TIM2); //重新将Timer设置为缺省值

TIM_InternalClockConfig(TIM2); //采用内部时钟给TIM2提供时钟源
TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1; //预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置计数器模式为向上计数模式
TIM_TimeBaseStructure.TIM_Period = 2000 - 1; //设置计数溢出大小,每计2000个数就产生一个更新事件
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //将配置应用到TIM2中
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除溢出中断标志

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); //开启TIM2的中断
以上是一个最基本的定时器配置的代码,载自网上被转载无数次的地方……
中断函数自己按照需求写,这里不多说。
在库中的初始化函数和初始化数据类型有3类,TIM_TimeBaseInitTypeDef、TIM_OCInitTypeDef、TIM_ICInitTypeDef
与基时参数相关的数据类型是TIM_TimeBaseInitTypeDef

typedef struct
{
uint16_t TIM_Prescaler;

uint16_t TIM_CounterMode;

uint16_t TIM_Period;

uint16_t TIM_ClockDivision;

uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;
以上是从库stm32f10x_tim.h中截取的代码,整体的数据结构可以中这段注释中得知,不懂E文的要么翻字典要么翻库函数中文翻译
版本(当然这个是2.0的库,有部分会和3.0后的版本很不相同),这部分的数据类型还是很一样的,不多说。
接着就是TIM_TimeBaseInit()这个函数了,在stm32f10x_tim.c的224行中

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
uint16_t tmpcr1 = 0;


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))
{

tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
}

if((TIMx != TIM6) && (TIMx != TIM7))
{

tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
}

TIMx->CR1 = tmpcr1;


TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;


TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;

if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))
{

TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;
}


TIMx->EGR = TIM_PSCReloadMode_Immediate;
}
可以看3.0后的函数里把所有的TIMx都加入一个函数里面做判断了,不需要和2.0的区分TIM1和TIM 两类函数,比较其基本操作都一样无非就是多了一个两个寄存器而已。
程序中可以看到这一段:

if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||
(TIMx == TIM4) || (TIMx == TIM5))
{

tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
}
if((TIMx != TIM6) && (TIMx != TIM7))
{

tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
}
TIMx->CR1 = tmpcr1;
高级定时器和通用定时器拥有向上计数、向下技术、向上/向下模式,三种,而基本计时器只有向上计数一种,因此TIM6和TIM7木有的设置计数模式,tmpcr1首先装入了控制寄存器CR1d 值,然后把其中DIR(位4)和CMS(位6:5)清除,然后或运算上载入数据结构中的值,这里代码再跳转到stm32f10x_tim.h中第362行
#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) 定义的是TIM_CounterMode的几种情况,即控制计数器向上
技术或向下计数,或是向上向下交替计数,当设置的是交替计数的情况DIR位为只读。
TIM_ClockDivision为时钟分配因子,其中有 0、2x、4x ,在AHB低时钟时为提高定时精度而实用的倍频器,位于CR1寄存器中的位9:8。这段程序便配置好了CR1寄存器,然后再看下面的程序。载入了PSC寄存器和ARR寄存器值,如果是高级定时器还有RCR寄存器值,在这一步便基本配置得差不多了,但还是发现函数最后还有一句 TIMx->EGR = TIM_PSCReloadMode_Immediate; 这里在事件寄存器中做了一次软件的事件更新触发使得其UG位置1。
#define TIM_PSCReloadMode_Immediate ((uint16_t)0x0001)

上一页 1 2 下一页

评论


技术专区

关闭