微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM32定时器详解 -----影子寄存器,预装寄存器

STM32定时器详解 -----影子寄存器,预装寄存器

时间:11-26 来源:互联网 点击:

构复杂。复杂的结构带来的是复杂的库函数。

高级定时器TIM1和TIM8一共有着80多个库函数,如果对其一一介绍,不但浪费时间,浪费精力,还有可能变成类似《固件库使用手册》一样的东西。在学习的时候,我们对事物的认知总是螺旋上升的,尤其是我们做嵌入式开发,当遇到一个新的系统或者硬件,指望着看一遍数据手册,就完全掌握其使用方法是不可能的。所以,我们先建立起一个最简单,最基础的实验,方便对新事物有着一个感性的直观的认知。有了清晰的认知,明白了基本原理后,后面的学习速度就会大大加快,也能的心应手了.看数据手册和固件库函数的时候,不要图快,不要浮躁,指望着看看相关的资料,复制下固件库例程的代码把程序搞定,这不叫“写代码”,这叫“移植”。基础打的不牢靠,对于细节问题理解的不清晰,是不可能真正的学好ARM的.如果想继续学习的话,你会发现,你“节省”的时间,在越来越深入后,就会给你带来双倍的“节省时间”长的麻烦.

----------作者的心得在"stm32f10x_tim.h"中可以看到如下定义:

typedef struct { uint16_t TIM_Prescaler; uint16_t TIM_CounterMode; uint16_t TIM_Period; uint16_t TIM_ClockDivision; uint8_t TIM_RepetitionCounter; } TIM_TimeBaseInitTypeDef;

库函数TIM_TimeBaseInit()的原型如下

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; }

正如函数名,和结构体名所描述的,这个函数的作用为,初始化TIM1的时基部分.

结合着数据手册和上面的高级定时器框图和时钟简介可知,我们使用高级定时器TIM1中断时对TIM1的时基配置顺序如下所示。

在此例中,我们可以这样定义他.

TIM_TimeBaseStructure.TIM_Prescaler=(18000-1); //时钟预分频 TIM_TimeBaseStructure.TIM_Period=(4000-1); //定时器初始值 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_div1; // 时钟分割 TIM_CKD_div1 为 0x0 TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); //初始化定时器的值

上面的初始化流程图已经说明,

定时器中断频率 = 时钟频率/(时钟预分频+1)/(计数器装载值+1)

所以我们要达到1S间隔的跑马灯,定时器的中断频率为1Hz,所以这里只要时钟分频的值与定时器的计数器的装载值之积为72MHZ且不越界即可

关于计数模式,在stm32f10x.h中有如下的定义

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top