datasheet

单片机入门学习十三 STM32单片机学习十 通用定时器

2019-07-12来源: eefocus关键字:单片机  STM32  通用定时器

本篇重点记录的是STM32F1的通用定时器。 

STM32F103ZE有8个定时器,其中2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5),2个基本定时器(TIM6、TIM7)。下表是对这8个定时器的详细描述。


定时器种类 位数 计数器模式 产生DMA请求 捕获/比较通道 互补输出 特殊应用场景

高级定时器

(TIM1,TIM8) 16 向上、向下、向上/下 可以 4 有 带死区控制盒紧急刹车,

可应用于PWM电机控制

通用定时器

(TIM2~TIM5) 16 向上、向下、向上/下 可以 4 无 通用。定时计数,PWM输出,

输入捕获,输出比较

基本定时器

(TIM6,TIM7) 16 向上、向下、向上/下 可以 0 无 主要应用于驱动DAC

上表中可看出STM32F103ZE定时器都是16位的,捕获/比较通道有4个,计数模式包括3种(向上计数、向下计数、中央对齐(向上/向下)计数)。


在此对计数模式做一个解释 

①向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。 

②向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。 

③中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。 


计数

1、通用计时器概述

通用计数器TIMx(TIM2~TIM5)定时器的特点包括:


位于低速的APB1总线上(APB1)

16 位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT)。

16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数 为 1~65535 之间的任意数值。

4 个独立通道(TIMx_CH1~4),这些通道可以用来作为: 

① 输入捕获 

② 输出比较 

③ PWM 生成(边缘或中间对齐模式) 

④ 单脉冲模式输出

可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。

产生中断/DMA(6个独立的IRQ/DMA请求生成器),该中断产生的事件如下: 

① 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) 

② 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) 

③ 输入捕获 

④ 输出比较 

⑤ 支持针对定位的增量(正交)编码器和霍尔传感器电路 

⑥ 触发输入作为外部时钟或者按周期的电流管理

STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。

使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。

通用计时器框图如下: 


通用计时器

从图中我们可以看到通用计时器由时钟、时基单元、输入电路、输出电路构成,下面将会对这四块分别做介绍。


2、通用计数器 时钟的选择


通用计数器

上图总结为计数器的时钟有8种选择:


内部RCC提供的时钟:TIMxCLK(CK_INT) 

CK_INT(内部时钟)值的计算: 

从下图可知如果是APB1的分频系数是1,则通用定时器的时钟=APB1的时钟;否则(APB1的分频系数不是1)通用寄存器的时钟=APB1时钟*2; 

 CK_INT 

如:默认使用SystemInit函数的情况下,SYSCLK=72M,AHB时钟=72M,APB1时钟=36M,

APB1的分频系数=AHB时钟/APB1时钟=2

所以通用定时器时钟CK_INT=2*36M=72M。


内部触发器输入口1~4(ITR1、ITR2、ITR3、ITR4),用一个定时器作为另一定时器的分频


外部捕捉比较引脚,引脚1(TI1FP1或TI1F_ED)、引脚2(TI2FP2)

外部引脚:ETR(使能/禁止位、可编程设定极性、4位外部触发过滤器、外部触发分频器[分频器关闭、二分频、四分频、八分频])

计数器时钟可以由下列时钟源提供(该内容意思同上): 

内部时钟(CK_INT) 

外部时钟模式1:外部输入脚(TIx) 

外部时钟模式2:外部触发输入(ETR) 

内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。


3、时基单元


时基单元

从上图中我们可看到定时器的构成:


1)计数寄存器(TIMx_CNT)

该寄存器计数模式为3种,向上计数、向下计数和对齐计数 

计数寄存器


2)预分频器寄存器(TIMx_PSC)

可将时钟频率按1到65536之间的任意值进行分频,可在运行时改变其设置值 

预分频寄存器


3)自动装载寄存器(TIMx_ARR)

如果TIMx_CR1寄存器中的ARPE位为0,ARR寄存器的内容将直接写入影子寄存器;如果ARPE为1,ARR寄存器的内容将再每次的更新事件UEV发生时,传送到影子寄存器; 

如果TIMx_CR1中的UDIS位为0,当计数器产生溢出条件时,产生更新事件; 

自动重装载寄存器


4)控制寄存器1(TIMx_CR1)

控制寄存器1


5)DMA中断使能寄存器(TIMx_DIER)

DMA中断使能寄存器


6)定时器中断实现步骤

时基单元为我们提供了定时的功能,我们利用该功能实现如下示例程序的编写: 

通过定时器中断配置,实现每500ms中断一次,通过定时中断实现LED灯闪烁。 

① 使能定时器时钟。 

RCC_APB1PeriphClockCmd(); 

② 初始化定时器,配置ARR,PSC(即配置自动装载寄存器TIMx_ARR和预分频寄存器值TIMx_PSC) 

TIM_TimeBaseInit(TIM_TypeDef* TIMx, IM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);


ARR、PSC如何确定 

1)我们知道计数器ARR溢出后会产生更新中断,我们以中心对齐模式的时序图来说明,如下图: 

中心对称

上图中CK_INT前面已说过,其频率由APB1来决定,若使用默认时钟SystemInit初始化的话,CK_INT=72MHz。 

CK_CNT如何确定,我们看下图 

 CK_CNT 

CK_INT=APB1或APB1∗2CK_INT=APB1或APB1∗2 

Fck_psc=CK_INTFck_psc=CK_INT 

CK_CNT=Fck_pscPSC[15:0]+1CK_CNT=Fck_pscPSC[15:0]+1 该公式计算出的即为CK_CNT的频率 

   

那么一个时钟周期的时间 

T=1CK_CNT=PSC[15:0]+1Fck_psc

T=1CK_CNT=PSC[15:0]+1Fck_psc


由于计数器溢出会产生一次中断,故 

Tout(溢出时间)=(ARR+1)∗T=(ARR+1)∗(PSC[15:0]+1)Fck_psc

Tout(溢出时间)=(ARR+1)∗T=(ARR+1)∗(PSC[15:0]+1)Fck_psc


上述公式为何计数器ARR和时钟分频PSC都要加1,因为这两个值是配置在寄存器中的,其实从0开始计数,故要加1。

根据上面导出的Tout的公式,结合本小节开头的需求,中断时间设置为500ms,我们可使用默认的系统频率,则Fck_psc=CK_INT=72MHz,则 

500(ms)=(ARR+1)∗T=(ARR+1)∗(PSC[15:0]+1)72000

500(ms)=(ARR+1)∗T=(ARR+1)∗(PSC[15:0]+1)72000


设PSC=7199,则ARR=4999,该需求的ARR,PSC我们将会以此值去配置。

③ 开启定时器中断,配置NVIC。 

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); 

NVIC_Init(); 

④ 使能定时器。 

TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState); 

⑤ 编写中断服务函数。 

TIMx_IRQHandler();


7)程序编写

//通用定时器3中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器3!

void TIM3_Int_Init(u16 arr,u16 psc)

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    NVIC_InitTypeDef NVIC_InitStructure;


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


    //定时器TIM3初始化

    TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值   

    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

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


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


    //中断优先级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_Cmd(TIM3, ENABLE);  //使能TIMx                     

}

//定时器3中断服务程序

void TIM3_IRQHandler(void)   //TIM3中断

{

    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否

    {

    TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx更新中断标志 

    LED1=!LED1;

    }

}

//LED1闪烁的周期为500ms,LED0闪烁的周期为200ms,看到的现象为LED1闪烁慢,LED0闪烁快

int main(void)

{       


    delay_init();            //延时函数初始化    

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级


[1] [2]

关键字:单片机  STM32  通用定时器

编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic467515.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32之定时器(实例)
下一篇:Stm32入门——Systick定时器

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32F1系列单片机USB外设相关寄存器的定义

Keil MDK网站上下载的Keil.STM32F1xx_DFP.2.2.0.pack包中的stm32f10x.h头文件里面没有USB_TypeDef的定义,只有寄存器位的定义,是不完整的头文件。没有USB的数据结构就会给访问USB寄存器带来一定的困难。虽然可以参照STM32参考手册中的USB register map自己编写出USB_TypeDef结构体,但是这样比较麻烦。不过,STM32CubeMX工具生成的STM32F103工程中的头文件stm32f103xe.h中就有完整的USB数据结构,该头文件的版本是V4.2.0,日期为31-March-2017,作者仍然是Keil里面的MCD Application Team,这比Ke
发表于 2019-07-19

STM32开发笔记38: 单片机内部Flash的读写

单片机型号:STM32F070F6P6本文介绍应用C语言进行单片机内部Flash的读写技巧,将从查看文档开始,到最终完成完整的程序。单片机型号:STM32F070F6P6步骤如下:1、查看文档《STM32F030x4/x6/x8/xC and STM32F070x6/xB advanced ARM®-based 32-bit MCUs》确认其Flash的内部结构。2、查看文档确认STM32F070F6P6内部存储器地址分配。从下表中得到的主要信息是Main Flash memory的起始地址是0x08000000,长度是32KB,到0x08017FFF结束(结束值可不关心)。3、继续查看Main Flash memory的内部结构
发表于 2019-07-16
STM32开发笔记38: 单片机内部Flash的读写

模拟量数据的采集过程解析

单片机的ADC接口属于模数转换接口,将外部的模拟量信号转化为数字信号,单片机属于数字器件,需将模拟信号转化为数字信号才能够为单片机处理。目前市场的很多单片机都自带ADC转换接口,若无ADC转换接口,可以使用ADC数模转换芯片外扩。ADC模块是将模拟信号转化位数字信号,数字信号用0和1表示,ADC模块有参考电压,假设给的参考电压是5V,ADC是12位的(几位表示用二进制几位数存储模拟量转化后的数字量,12位的ADC则可储存数字量范围为:(二进制)000000000000~111111111111,转换为十进制数字范围为0~2^12即0~4095。也就是说把参考电压分为2^12份即4096份,最小分辨率为VREF/4096。也就是说
发表于 2019-07-13
模拟量数据的采集过程解析

单片机入门学习八 STM32单片机学习五 时钟系统

单片机学习除了了解该篇 单片机入门学习五 STM32单片机学习二 跑马灯程序衍生出的stm32编程基础 中的基础外,我们还需要有时钟的概念,本篇将记录 stm32的时钟系统。1、STM32时钟介绍 下面这幅图时stm32的时钟系统框图 1)蓝底框表示 时钟源,即: ①HSI是高速内部时钟,RC振荡器,频率为8MHz。 ②HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 ③LSI是低速内部时钟,RC振荡器,频率为40kHz。(WDG看门狗 使用该时钟源) ④LSE是低速外部时钟,接频率为32.768kHz的石英晶体。(RTC
发表于 2019-07-12
单片机入门学习八 STM32单片机学习五 时钟系统

51单片机与蓝牙模块连接

不久前开始学习使用蓝牙模块,在模块与51单片机连接的过程中出现了非常多的问题,我想应该也是很多新手和我一样会遇到这样的问题,因此特地写这篇文章,想分享下在学习过程中遇到的问题以及解决方法。此次学习用到模块是HC-06蓝牙模块,如下图:该模块某宝有售,价格约为20RMB。某宝上的HC-06有两种,分别是带引脚和不带引脚的,建议新手购买带引脚的。我从试验开始到成功,一共使用了四块蓝牙模块。第一次买的是带引脚的,但是模块本身是坏的;第二次买的是不带引脚的,但是由于自身的焊功有限,导致模块损坏,无法使用;第三次是朋友送的蓝牙4.0,由于某些原因无法使用,在此也特别感谢朋友送我蓝牙;第四次购买,就是上图所示的蓝牙,才最终完成了试验。总结
发表于 2019-07-11
51单片机与蓝牙模块连接

STM32解决:st-link连接下载程序的问题

STM32解决:Error: Flash Download failed - "Cortex-M3"本人由于使用普中科技的stm32 的开发板的 USB的下载的地方坏了,所以不得不使用arm仿真器 st-link 进行下载。鼓捣了半天下面总结一下几个问题:1、st-link的驱动下载首先你插上st-link的时候,电脑的设备管理器这个地方是有感叹号的,说明还没有装好驱动,所以我就在网上找啊找。终于根据:win8【笔者没这个系统,无法测试,请大家测试后报告】:http://pan.baidu.com/s/1sjJQxZn(转载来自:https://blog.csdn.net/imxiangzi/article
发表于 2019-07-19
STM32解决:st-link连接下载程序的问题

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved