7定时器.docx
- 文档编号:24671482
- 上传时间:2023-05-30
- 格式:DOCX
- 页数:29
- 大小:517.44KB
7定时器.docx
《7定时器.docx》由会员分享,可在线阅读,更多相关《7定时器.docx(29页珍藏版)》请在冰豆网上搜索。
7定时器
定时器(时基和PWM输出)
#.1定时器功能简介
区别于SysTick一般只用于系统时钟的计时,STM32的定时器外设功能强大得超出了想像力,《STM32参考手册》中仅对定时器的介绍就已经占了100多页。
Stm32一共有8个都为16位的定时器。
其中Tim6、Tim7是基本定时器;Tim2-Tim5是通用定时器;Tim1和Tim8是高级定时器。
这些定时器使stm32具有定时、信号的频率测量、信号的PWM测量、PWM输出、三相6步电子控制及编码器接口等功能,都是专业为工控领域量身定做的。
#.2定时器工作分析
#.2.1基本定时器
基本定时器TIM6和TIM7只具备最基本的定时功能,就是累加的时钟脉冲数超过(达到)预定值时,能触发中断或触发DMA请求。
由于在芯片内部与DAC外设相连,可通过触发输出驱动DAC,也可以作为其它通用定时器的时钟基准。
如下图
这两个基本定时器使用的时钟源都是TIMxCLK,时钟源经过PSC预分频器后输入至脉冲计数器TIMx_CNT,基本定时器只能工作在向上计数模式,在重载寄存器TIMx_ARR中保存的是定时器的溢出值。
工作时,脉冲计数器TIMx_CNT由时钟触发进行计数,当TIMx_CNT的计数值X等于重载寄存器中保存的数值N时,产生溢出事件,(实际情况是TIMx_CNT要完成0-N的全部计数,也就是说N这个数是要计完之后再触发响应中断或者DMA,这样TIMx_CNT实际完成了N+1次计数,所以在以后编程时,如果我们需要计1000次,参数应该配置成N=999,其它情况以此类推。
相关内容可参考该定时器的计数模式)可触发中断或DMA请求。
然后TIMx_CNT的值重新被置为0,重新向上计数。
TIM6和TIM7的主要特性
TIM6和TIM7定时器的主要功能包括:
●16位自动重装载累加计数器
●16位可编程(可实时修改)预分频器,用于对输入的时钟按系数为1~65536之间的任意数值分频
●触发DAC的同步电路
●在更新事件(计数器溢出)时产生中断/DMA请求
#.2.2TIM6和TIM7的功能
时基单元
这个可编程定时器的主要部分是一个带有自动重装载的16位累加计数器,计数器的时钟通过一个预分频器得到。
软件可以读写计数器、自动重装载寄存器和预分频寄存器,即使计数器运行时也可以操作。
时基单元包含:
●计数器寄存器(TIMx_CNT)
●预分频寄存器(TIMx_PSC)
●自动重装载寄存器(TIMx_ARR)
自动重装载寄存器是预加载的,每次读写自动重装载寄存器时,实际上是通过读写预加载寄存器实现。
根据TIMx_CR1寄存器中的自动重装载预加载使能位(ARPE),写入预加载寄存器的内容能够立即或在每次更新事件时,传送到它的影子寄存器。
当TIMx_CR1寄存器的UDIS位为“0”(UEV使能),则每当计数器达到溢出值时,硬件发出更新事件;软件也可以产生更新事件;关于更新事件的产生,随后会有详细的介绍。
计数器由预分频输出CK_CNT驱动,设置TIMx_CR1寄存器中的计数器使能位(CEN)使能计数器计数。
注意:
实际的设置计数器使能信号CNT_EN相对于CEN滞后一个时钟周期。
预分频器
预分频可以以系数介于1至65536之间的任意数值对计数器时钟分频。
它是通过一个16位寄存器(TIMx_PSC)的计数实现分频。
因为TIMx_PSC控制寄存器具有缓冲,可以在运行过程中改变它的数值,新的预分频数值将在下一个更新事件时起作用。
以下两图是在运行过程中改变预分频系数的例子。
计数模式
计数器从0累加计数到自动重装载数值(TIMx_ARR寄存器),然后重新从0开始计数并产生一个计数器溢出事件。
每次计数器溢出时可以产生更新事件;(通过软件或使用从模式控制器)设置TIMx_EGR寄存器的UG位也可以产生更新事件。
设置TIMx_CR1中的UDIS位(为1)可以禁止产生UEV事件,这可以避免在写入预加载寄存器时更改影子寄存器。
在清除UDIS位为“0”之前,将不再产生更新事件,但计数器和预分频器依然会在应产生更新事件时重新从0开始计数(但预分频系数不变)。
另外,如果设置了TIMx_CR1寄存器中的URS(选择更新请求),设置UG位可以产生一次更新事件UEV,但不设置UIF标志(即没有中断或DMA请求)。
当发生一次更新事件时,所有寄存器会被更新并(根据URS位)设置更新标志(TIMx_SR寄存器的UIF位):
●传送预装载值(TIMx_PSC寄存器的内容)至预分频器的缓冲区。
●自动重装载影子寄存器被更新为预装载值(TIMx_ARR)。
以下是一些在TIMx_ARR=0x36时不同时钟频率下计数器工作的图示例子。
和基本定时器相关的寄存器(共8个)
●TIM6和TIM7控制寄存器1(TIMx_CR1)
●TIM6和TIM7控制寄存器2(TIMx_CR2)
●TIM6和TIM7DMA/中断使能寄存器(TIMx_DIER)
●TIM6和TIM7状态寄存器(TIMx_SR)
●TIM6和TIM7事件产生寄存器(TIMx_EGR)
●TIM6和TIM7计数器(TIMx_CNT)
●TIM6和TIM7预分频器(TIMx_PSC)
●TIM6和TIM7自动重装载寄存器(TIMx_ARR)
其相关说明见《stm32参考手册》
定时器的时钟源
从时钟源方面来说,通用定时器比基本定时器多了一个选择,它可以用外部脉冲作为定时器的时钟源。
使用外部时钟源时,要使用寄存器进行触发边沿、滤波器带宽的配置。
如果选择内部时钟源的话则与基本定时器一样,也为TIMxCLK。
但要注意的是,所有定时器(包括基本、通用和高级)使用内部时钟源时,定时器的时钟源都被称为TIMxCLK,但TIMxCLK的时钟来源并不是完全一样的,见图(时钟树)。
Tim2-Tim7也就是基本定时器和通用定时器,TIMxCLK的时钟来源是APB1预分频的输出。
当APB1的分频系数为1时,则Tim2-Tim7的TIMxCLK直接等于该APB1预分频器的输出,而APB1的分频系数不为1时,Tim2-Tim7的TIMxCLK则为APB1预分频器输出的2倍。
如在常见的配置中,AHB=72MHZ,而APB1的预分频系数被配置为2,则PCLK1刚好达到最大值36MHZ,则Tim2-Tim7的时钟TIMxCLK=(AHB/2)*2=72MHZ。
而对于Tim1和Tim8这两个高级定时器,TIMxCLK的时钟来源则是APB2预分频器的输出,同样它也根据分频系数分为两种情况。
常见的配置中,AHB=72MHZ,APB2预分频器的分频系数被设置为1,此时PCLK2刚好达到最大值72MHZ,而TIMxCLK则直接等于APB2分频器的输出,即Tim1和Tim8的时钟TIMXCLK=AHB=72MHZ。
虽然这种配置下最终TIMxCLK的时钟频率相等,但必须清楚实质上它们的时钟来源是有区别的。
还要强调的是:
TIMxCLK是定时器内部的时钟源,但在时钟输出到脉冲计数器TIMx_CNT前,还经过一个预分频器PSC,最终用于驱动脉冲计数器TIMx_CNT的时钟频率根据预分频器PSC的配置而定。
时基初始化
首先是时基初始化,使用了一个TIM_TimeBaseInitTypeDef类型的结构体。
时基初始化,即配置基本定时器只具有的那部分功能,下面分析初始化结构体的成员:
(1).TIM_Period
定时周期,实质是存储到重载寄存器TIMx_ARR的数值,脉冲计数器从0累加到这个值上溢或从这个值自减至0下溢。
这个数值加1然后乘以时钟源周期就是实际定时周期。
本实验中向该成员赋值为999,即定时周期为(999+1)*T,T为时钟源周期。
注:
999和1000的区别一定要弄清楚。
(2).TIM_Prescaler
对定时器时钟TIMxCLK的预分频值,分频后作为脉冲计数器TIMx_CNT的驱动时钟,得到脉冲计数器的时钟频率为:
fCK_CNT=fTIMx_CLK/(N+1),其中N为即为赋给本成员的时钟分频值。
本实验给TIM_Prescaler成员赋值为71,即对TIMxCLK进行(71+1=72)分频,已知AHB时钟频率为72MHz、TIMxCLK为72MHz,所以输出到脉冲计数器TIMx_CNT的时钟频率为fCK_CNT=72MHz/(71+1)=1MHz。
(3).TIM_ClockDivision:
时钟分频因子。
怎么又出现一个配置时钟分频的呢?
要注意这个TIM_ClockDivision和上面的TIM_Prescaler是不一样的。
TIM_Prescaler预分频配置是对TIMxCLK进行分频,分频后的时钟被输出到脉冲计数器TIMx_CNT,而TIM_ClockDivision虽然也是对TIMxCLK进行分频,但它分频后的时钟频率为fDTS,是被输出到定时器的ETRP数字滤波器部分,会影响滤波器的采样频率。
TIM_ClockDivision可以被配置为1分频(fDTS=fTIMxCLK)、2分频及4分频。
ETRP数字滤波器的作用是对外部时钟TIMxETR进行滤波。
本实验中是使用内部时钟TIMxCLK作为定时器时钟源的,所以配置TIM_ClockDivision为任何数值都没有影响。
(4).TIM_CounterMode
本成员配置的为脉冲计数器TIMx_CNT的计数模式,分别为向上计数,向下计数,及中央对齐模式。
向上计数即TIMxCNT从0向上累加到TIM_Period中的值,(重载寄存器TIMx_ARR的值),产生上溢事件;向下计数则TIMxCNT从TIM_Period的值累减至0,产生下溢事件。
而中央对齐模式则为向上、向下计数的合体,TIMxCNT从0累加到TIM_Period的值减1时,产生一个上溢事件,然后向下计数到1时,产生一个计数器下溢事件,再从0开始重新计数。
本实验中.TIM_CounterMode成员被赋值为TIM_CounterMode_Up(向上计数模式)。
填充完配置参数后,调用库函数TIM_TimeBaseInit()把这些控制参数写到寄存器中,定时器的时基配置就完成了。
#.3Stm32通用定时器3精确延时代码分析
#.3.1实验描述及工程文件清单
实验描述
使用通用定时器TIM3进行精确定时,结果为经过一定定时时间,开发板上的ledx亮(灭)
硬件连接
Led0-pb6,led1-pb7,led2-pb8,led3-pb9
用到的库文件
startup/start_stm32f10x_hd.c
CMSIS/core_cm3.c
CMSIS/system_stm32f10x.c
FWlib/stm32f10x_gpio.c
FWlib/stm32f10x_rcc.c
FWlib/stm32f10x_tim.c
FWlib/misc.c
用户编写的文件
USER/main.c
USER/stm32f10x_it.c
USER/led.c
USER/bsp_TimeBase.c
#.3.2.配置工程环境
本按键实验中用到了GPIO、RCC、TIM片上外设,并且使用了中断,所以要把外设函数库文件FWlib/stm32f10x_gpio.c、FWlib/stm32f10x_rcc.c、FWlib/stm32f10x_tim.c和中断函数库文件FWlib/misc.c文件添加到工程模板之中。
实验中还使用了LED灯,为了重用代码,我们把在前面写好的led.c和led.h用户文件复制到USER目录下,并添加到工程之中。
配置工程环境最重要的一步就是别忘记在stm32f10x_conf.h文件中把使用到的外设头文件包含进来。
#.3.3main文件
顺着代码的执行流程,从main函数开始分析,这样阅读和分析别人写的代码更有条理。
***********************************
#include"stm32f10x.h"
#include"led.h"
#include"bsp_TiMbase.h"
volatileu32time=0;//ms计时变量
intmain(void)
{
/*led端口配置*/
LED_GPIO_Config();
/*TIM3定时配置*/
TIM3_Configuration();
/*定时器的中断优先级配置*/
TIM3_NVIC_Configuration();
/*TIM3重新开启时钟,开始定时,其实这条语句只要符合规则,怎么写都可以!
*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
while
(1)
{
if(time==1000)/*1000*1ms=1s时间到*/
{
time=0;
/*LED1取反*/
LED1_TOGGLE;
}
}
}
***********************************
#.3.4.TIM3初始化配置
现在我们分析一下紧接下来调用到的TIM3_Configuration()函数。
***************************************
voidTIM3_Configuration(void)
{
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
/*配置Tim3的时钟Tim3clk为72MHZ*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
//TIM_DeInit(TIM2);/*使用这个函数配置成默认值也是可以的*/
/*自动重装载寄存器TIM3_ARR的值为(N-1)=1000-1=999*/
TIM_TimeBaseStructure.TIM_Period=999;
/*累计TIM_Period个周期后产生一次更新或者中断*/
/*设置时钟预分频系数为72-1=71*/
TIM_TimeBaseStructure.TIM_Prescaler=71;
/*设置的是tim->cr1的8、9位,具体什么含义目前还不清楚,反正在这里是没有使用该参数*/
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
/*设置定时器的计数模式为向上计数模式*/
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
/*为了防止定时器一开始没有计数就产生中断,所以先清楚该中断标志位*/
TIM_ClearFlag(TIM3,TIM_FLAG_Update);
/*使能中断*/
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM3,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,DISABLE);/*为了防止出现的错误,先关闭这个时钟*/
}
***************************************
#.3.5中断优先级的配置
Tim3中断优先级的配置函数为TIM3_NVIC_Configuration(),具体代码如下
***************************************
voidTIM3_NVIC_Configuration(void)
{
NVIC_InitTypeDefNVIC_InitStructure;
/*中断优先级被配置成第0组*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
**************************************
由于这是个独立的程序,没有和其它的中断产生冲突,所以,这个中断优先级可随意设置。
#.3.6中断服务函数
在这个工程中,使用了Tim3的溢出中断,具体函数为
***********************************************
voidTIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)!
=RESET)
{
time++;
TIM_ClearITPendingBit(TIM3,TIM_FLAG_Update);
}
}
***********************************************
经过前面的设置,通用定时器Tim3每经过1ms触发一次中断,也就是在中断服务函数中每经过1ms,变量time加1,这样在main函数中的条件判断语句(time==1000)成立的条件恰好为1000*0.001=1s,也就是每经过1秒,led1状态变化一次。
#.3.6实验现象
使用通用定时器Tim3进行精确定时,每经过1秒,LEDx状态变化一次。
#.4通用定时器
#.4.1通用定时器简介
通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。
它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)。
使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。
每个定时器都是完全独立的,没有互相共享任何资源。
它们可以一起同步操作。
相比之下,通用定时器Tim2-Tim5就比基本定时器复杂得多了。
见下图
通用定时器主要特性
通用TIMx(TIM2、TIM3、TIM4和TIM5)定时器功能包括:
●16位向上、向下、向上/向下自动装载计数器
●16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值
●4个独立通道:
⏹─输入捕获
⏹─输出比较
⏹─PWM生成(边缘或中间对齐模式)
⏹─单脉冲模式输出
●使用外部信号控制定时器和定时器互连的同步电路
●如下事件发生时产生中断或DMA请求
⏹─更新:
计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
⏹─触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
⏹─输入捕获
⏹─输出比较
●支持针对定位的增量(正交)编码器和霍尔传感器电路
●触发输入作为外部时钟或者按周期的电流管理
#.4.2Tim2-Tim5的主要功能
时基单元
和基本定时器是一样的,只是这个计数器可以向上计数、向下计数或者向上向下双向计数。
预分频器
和基本定时器类似。
计数器模式
分为向上、向下和中央对齐三种模式,其中向上和向下的计数模式和基本定时器差不多。
时钟选择
通用定时/计数器时钟可由下列时钟源提供:
●内部时钟(CK_INT)
●外部时钟模式1:
外部输入脚(TIx)
●外部时钟模式2:
外部触发输入(ETR)
●内部触发输入(ITRx):
使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
内部时钟源(CK_INT)
如果禁止了从模式控制器(TIMx_SMCR寄存器的SMS=000),则CEN、DIR(TIMx_CR1寄存器)和UG位(TIMx_EGR寄存器)是事实上的控制位,并且只能被软件修改(UG位仍被自动清除)。
只要CEN位被写成“1”,预分频器的时钟就由内部时钟CK_INT提供。
外部时钟源模式1
当TIMx_SMCR寄存器的SMS=111时,此模式被选中。
计数器可以在选定输入端的每个上升沿或下降沿计数。
外部时钟源模式2
选定此模式的方法为:
令TIMx_SMCR寄存器中的ECE=1计数器能够在外部触发ETR的每一个上升沿或下降沿计数。
捕获/比较寄存器
通用定时器的基本计时功能与基本定时器的工作方式是一样的,同样把时钟源经过预分频器输出到脉冲计数器TIMx_CNT累加,溢出时就产生中断或DMA请求。
而通用定时器比基本定时器多出的强大功能,就是因为通用定时器多出了一种寄存器捕获/比较寄存器TIMx_CCR(Capture/CompareRegister),它在输入时被用于捕获(存储)输入脉冲在电平发生翻转时,脉冲计数器TIMx_CNT的当前计数值,从而实现脉冲的频率测量;在输出时被用来存储一个脉冲数值,把这个数值用于与脉冲计数器TIMx_CNT的当前计数值进行比较,根据比较结果进行不同的电平输出。
PWM输出过程分析
通用定时器可以利用GPIOx引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCRx被用作比较功能,下面把它简称为比较寄存器。
这里直接举例说明定时器的PWM输出工作过程:
若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR被配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。
而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR预先存储了的数值A进行比较,当脉冲计数器TIMx_CNT的数值X小于比较寄存器TIMx_CCR的值A时,输出高电平(或低电平,这是可以自定义的);相反地,当脉冲计数器的数值X大于或等于比较寄存器的值A时,输出低电平(或高电平)。
如此循环,得到的输出脉冲周期就为重载寄存器TIMx_ARR存储的数值(N+1)乘以触发脉冲的时钟周期,其脉冲宽度则为比较寄存器TIMx_CCR的值A乘以触发脉冲的时钟周期,即输出PWM的占空比为A/(N+1)。
PWM边沿对齐模式向上计数配置
当TIMx_CR1寄存器中的DIR位为低的时候执行向上计数。
下面是一个PWM模式1的例子。
当TIMx_CNT 如果TIMx_CCRx中的比较值大于自动重装载值(TIMx_ARR),则OCxREF保持为’1’。 如果比较值为0,则OCxREF保持为“0”。 下图为TIMx_ARR=8时边沿对齐的PWM波形实例。 边沿对齐的PWM波
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 定时器