第6章高级定时器TIMXppt课件.pptx
STM32定时器的工作原理,STM32之所以能够实现定时,是单片机内部在计数脉冲(来自晶振)T = 1/F F为频率例如:我们以51单片机举例,假设单片机搭配12MHz的晶振,由于51单片机是12分频(即1个机器周期有12个时钟周期),则单片机的最小定时时间为 12MHz / 12 = 1MHzT = 1 / 1MHz = 1us,STM32定时器的工作原理,最小定时时间 T = 1 / 1MHz = 1us51单片机定时器:方式0 13位 最大定时时间间隔 213=8.192ms方式1 16位 最大定时时间间隔 216=65.536ms方式2 8位 最大定时时间间隔 28=256us,STM32定时器的工作原理,由此我们知道对于一个定时器而言要做到精确定时需要关注2个内容1.分频器(分频比)2.定时计数器的值,STM32定时器类型,按功能划分 2个高级控制定时器 TIM1 TIM8可分配6个通道的三相PWM发生器(多用于电机控制) 4个普通定时器 TIM2 TIM3 TIM4 TIM5每个定时器有4个输入捕获/输出比较/PWM/脉冲计数,STM32定时器类型, 2个基本定时器 TIM6 TIM7 主要用于产生DAC触发信号 2个看门狗定时器 独立看门狗 窗口看门狗 系统时基定时器 SysTick24位递减计数器自动重加载常用于产生延时 us级 ms级,从图中可以看出,定时器的时钟不是直接来自APB1或APB2,而是来自于输入为APB1或APB2的一个倍频器,图中的蓝色部分。下面以通用定时器2的时钟说明这个倍频器的作用:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1的频率两倍。,STM32高级定时/计数器,STM32高级定时/计数器,举个例子:当AHB=72MHz时,APB1的预分频系数必须大于2,因为APB1的最大频率只能为36MHz。如果APB1的预分频系数=2,则因为这个倍频器,TIM27仍然能够得到72MHz的时钟频率。能够使用更高的时钟频率,无疑提高了定时器的分辨率,这也正是设计这个倍频器的初衷。,基本定时器寄存器示意图,STM32定时器的时钟,CK_CNT 表示定时器工作频率TIMx_PSC 表示分频系数则定时器的工作频率计算公式为CK_CNT=定时器时钟/ (TIMx_PSC +1)由此我们可得到STM32单片机1个时钟周期为: T=1/ CK_CNT,例如普通定时器模块的时钟为72MHz,分频比位7199,那么我们想要得到一个1秒钟的定时,定时计数器的值需要设定为TIMx_ARR = 10 000因为72 000 000 / 7200 = 10KHz时钟周期T=1/10KHz=100us100us 10 000 = 1S结论 :分频比7199 定时计数器的值 10 000定时时间T公式为:T=(TIMx_PSC +1)(TIM_Period)/TIMxCLK,举例:基本定时器编程步骤,定时器相关的库函数主要集中在固件库文件stm32f10 x_tim.h和stm32f10 x_tim.c文件中。1)TIMx时钟使能。2)初始化定时器参数,设置自动重装值,分频系数,计数方式等。 在库函数中,定时器的初始化参数是通过初始化函数TIM_TimeBaseInit实现的:voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);3)允许中断发生。 在库函数里面定时器中断使能是通过TIM_ITConfig函数来实现的: voidTIM_ITConfig(TIM_TypeDef*TIMx,uint16_tTIM_IT,FunctionalStateNewState);,基本功能:定时器7定时时间为0.5秒,定时时间到达后,翻转LED灯的状态,达到LED灯闪烁的效果,闪烁周期1秒,举例:基本定时器编程步骤,4)TIMx中断优先级设置。在定时器中断使能之后,因为要产生中断,必不可少的要设置NVIC相关寄存器,设置中断优先级。5)允许TIMx工作,也就是使能TIMx。在固件库里面使能定时器的函数是通过TIM_Cmd函数来实现的:6)编写中断服务函数。在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,,举例:基本定时器,基本功能:定时器7定时时间为0.5秒,定时时间到达后,翻转LED灯的状态,达到LED灯闪烁的效果,闪烁周期1秒编程步骤:1、开时钟void RCC_Configuration(void) SystemInit(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);,举例:基本定时器,2)配置GPIO口:void GPIO_Configuration(void) GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; /LED1 V6 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, ,举例:基本定时器,3)配置中断分组(NVIC),并使能中断void NVIC_Configuration(void) NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);NVIC_InitStructure.NVIC_IRQChannel =TIM7_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; /抢占优先级 0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;/子优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/使能 NVIC_Init(,举例:基本定时器,4) 配置TIMER;利用TIM_DeInit()函数将Timer设置为默认缺省值;TIM_InternalClockConfig()选择TIMx来设置内部时钟源;TIM_Perscaler来设置预分频系数;TIM_ClockDivision来设置时钟分割;TIM_CounterMode来设置计数器模式; TIM_Period来设置自动装入的值 TIM_ARRPerloadConfig()来设置是否使用预装载缓冲器 TIM_ITConfig()来开启TIMx的中断,举例:基本定时器,3)-(6)步骤中的参数由TIM_TimerBaseInitTypeDef结构体给出。步骤(3)中的预分频系数用来确定TIMx所使用的时钟频率,具体计算方法为:CK_INT/(TIM_Perscaler+1)。CK_INT是内部时钟源的频率,是根据2.1中所描述的APB1的倍频器送出的时钟,TIM_Perscaler是用户设定的预分频系数,其值范围是从065535。定时器频率=(1+TIM_Prescaler )/72M)*(1+TIM_Period ),举例:基本定时器,例:如果想要设置定时器频率为1秒,可以设置TIM_Prescaler=35999,TIM_Period=1999 /2Khz的频率,计数到2000或TIM_Prescaler=7199,TIM_Period=9999 /10KHz的频率,计数到10000但是在作为PWM输出时会有细度不同的问题,后者的细度更高些,更倾向于第二种配置。,举例:基本定时器,void TIM_Configuration(void)TIM_DeInit(TIM7);TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Prescaler = 36000-1; / 分频36000 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /计数方向向上计数 TIM_TimeBaseStructure.TIM_Period = 1000;/自动重装载寄存器的值 TIM_TimeBaseStructure.TIM_ClockDivision = 0 x0;/时钟分频 TIM_TimeBaseInit(TIM7,举例:基本定时器,5)中断服务子程序Void TIM7_IRQHandler(void)if (TIM_GetITStatus(TIM7,TIM_IT_Update)=SET) GPIO_WriteBit(GPIOB, GPIO_Pin_5, (BitAction)(1-GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_5) );/ TIM_ClearITPendingBit (TIM7,TIM_FLAG_Update);,不是说使用了IO的复用功能就一定要启动RCC_APB2Periph_AFIO的Clock的,(参考手册8.4)只有使用了AFIO的事件控制寄存器、AFIO的重映射功能以及外部中断(EXTI)控制寄存器才需要开启AFIO的时钟,STM32参考手册从来没说过使用IO的复用功能就一定要开启AFIO时钟,这是个误区。例如下面的,最常用的USART1,如果你的板子上,默认用的就是PA9和PA10这两个IO作为USART1的TX和TX,那么也就是没有重映射,No Remap,这种情况下根本不需要开启AFIO时钟,只要开启USART1的外设时钟就行了,第6章高级定时器TIM1.TIM8,定时器的应用:定时操作,完成与时间相关的任务。另一种情况是计数操作。,6.1 定时和计数功能的实现方式,6.1.1、完全硬件实现 完全硬件电路实现,没有软件参与,可靠性高,但是通用性和灵活性差,一但设计好很难修改,如果需要修改,心须改变硬件的元器件戓线路,每次应用心须重新设计。6.1.2、纯软件方式,6.1.3 可编程定时/计数器,可编程定时/计数器时钟源来自内部系统时钟时,则定时/计数值就可以完成精密的定时,如果时钟源来自外部信号时,可编程定时/计数器就可以完成信号计数。 为了扩大定时/计数的范围,可编程定时/计数器经常附加设计了预分频计数器,对时钟进行分频操作。 可编程定时/计数器的启动、停止、定时间隔、预分频设置,工作模式等控制操作均可以通过软件实现。 通过这种方法实现的定时/计数具有不占用CPU时间,定时准确,定时/计数器可编程,可以重复利用,实现成本低,通用性强,实现灵活等优点,是目前使用最多的一种定时/计数方式,6.2 STM32高级定时/计数器,TIM1和TIM8称为高级控制定时器,功能最强:TIM2TIM5称为通用定时器:TIM6和TIM7称为基本定时器:更详细内容见223页表6-1,STM32高级定时/计数器,STM32系列的CPU,有多达8个定时器,其中TIM1和TIM8是能够产生三对PWM互补输出的高级定时器,常用于三相电机的驱动,它们的时钟由APB2的输出产生。其它6个为普通和基本定时器,时钟由APB1的输出产生。 这些定时器使STM32具有定时、信号的频率测量、信号的PWM测量、PWM输出、三相6步电机控制及编码器接口等功能,都是专门为工控领域量身订做的。,6.2.1高级定时器的主要特性,TIM1和TIM8定时器的功能包括: 16位向上、向下、向上/下自动装载计数器 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为165535之间的任意数值 多达4个独立通道: 输入捕获 输出比较 PWM生成(边缘或中间对齐模式) 单脉冲模式输出,6.2.1高级定时器的主要特性, 死区时间可编程的互补输出 使用外部信号控制定时器和定时器互联的同步电路 允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器 刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态,6.2.1高级定时器的主要特性, 如下事件发生时产生中断/DMA: 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发) 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数) 输入捕获 输出比较 刹车信号输入 支持针对定位的增量(正交)编码器和霍尔传感器电路 触发输入作为外部时钟或者按周期的电流管理,6.2.2 高级定时器概述,高级定时器结构框图见224页图6-2高级定时器可以划分为5个模块1 、时钟源选择2 、时基单元3 、输入捕获4 、比较输出5 、捕获比较寄存器,TIM用到的寄存器,6.4 高级定时器原理及应用,1 、时钟源内部系统时钟 内部系统时钟CK_INT来源于内部总线时钟,即APB2时钟。外部时钟模式1 外部时钟模式1触发输入信号可以选择共8种,触发输入的8种信号外部时钟模式1触发输入信号:内部触发0(ITR0) ;内部触发1(ITR1) ;内部触发2(ITR2) ;内部触发3(ITR3) ;通道1边沿检测器(TI1F_ED) ;定时器外部输入1(TI1FP1) ;定时器外部输入2(TI2FP2) ;外部触发输入(ETRF) ;,外部时钟模式1结构图,外部时钟模式2计数器能够在外部触发管脚ETR上信号的每一个上升沿或下降沿计数。,外部时钟模式2结构图,编码器输入方式两个输入TI1和TI2通常被用来作为增量编码器的接口。注意:编码器模式和外部时钟模式2不兼容,因此不能同时操作。,编码器,图1为编码器的示意图,中间是一个带光栅的码盘,光通过光栅,接收管接收到高电平,没通过,接收到低电平。电机旋转一圈,码盘上有多少光栅,接受管就会接收多少个高电平。,编码器,增量式旋转编码器通过内部两个光敏接受管转化其角度码盘的时序和相位关系,得到其角度码盘角度位移量增加(正方向)或减少(负方向)。下图为编码器的原理图:图2 增量式旋转编码器A,B两点对应两个光敏接受管,A,B两点间距为 S2 ,码盘的光栅间距分别为S0和S1。S0+S1的距离是S2的四倍。这样保证了A,B波形相位相差90度。旋转的反向不同,锯齿波A,B先到达高电平的顺序就会不同,如上图左侧所示,顺序的不同,就可以得到旋转的方向,编码器输入方式STM32的每个TIMER都有正交编码器输入接口,TI1,TI2经过输入滤波,边沿检测产生TI1FP1,TI2FP2接到编码器模块,通过配置编码器的工作模式,即可以对编码器进行正向/反向计数,编码器输入方式两个输入TI1和TI2通常被用来作为增量编码器的接口。注意:编码器模式和外部时钟模式2不兼容,因此不能同时操作。,2 、时基单元 可编程高级定时器的核心部分是由一个16位计数器和与其相关的几寄存器构成。 计数器可以向上计数、向下计数或者双向计数。 预分频器可以将输入时钟频率按1-65536之间的任意值分频,由于这个控制寄存器带有缓冲器,因此它能够在运行时被改变。新的预分频系数在下一次更新事件到来时被采用。,定时器时基单元示意图,补充,1.影子寄存器预装载寄存器的概念应该是相对于影子寄存器来说的。影子寄存器是即时其作用的,而预装载寄存器的值只有传递到影子寄存器才能起作用,你可以把它理解为一个缓存。设计预装载寄存器和影子寄存器的好处是,所有真正需要起作用的寄存器(影子寄存器)可以在同一个时间(发生更新事件时)被更新为所对应的预装载寄存器的内容,这样可以保证多个通道的操作能够准确地同步。如果没有影子寄存器,软件更新预装载寄存器时,则同时更新了真正操作的寄存器,因为软件不可能在一个相同的时刻同时更新多个寄存器,结果造成多个通道的时序不能同步,如果再加上例如中断等其它因素,多个通道的时序关系有可能会混乱,造成是不可预知的结果。,预分频器描述 预分频器可以将计数器的时钟频率按1到65536之间的任意值分频。它是基于一个(在TIMx_PSC寄存器中的)16位寄存器控制的16位计数器。 因为这个控制寄存器带有缓冲器,它能够在运行时被改变。新的预分频器的参数在下一次更新事件到来时被采用。 寄存器带有输出缓存器,所以可以中途改变它的值,预分频当器的参数从1变到2,预分频当器的参数从1变到4,计数器模式 向上计数模式:计数器从0计数到自动加载值,计数器溢出,然后重新从0开始计数。如果使用了重复计数器功能,在向上计数次数达到了设置的重复计数寄存器设置的次数时,才产生更新事件,否则每次计数器上溢时将产生更新亊件。,向上计数模式(N=36),向下计数模式在向下模式中,计数器从自动加载值开始向下计数到0 ,然后从自动加载值重新开始计数,如果使用了重复计数器,当向下计数次数达到了重复计数寄存器中设定的次数后,将产生更新亊件(UEV) ,否则每次计数器下溢时才产生更新亊件。,向下计数模式(N=36),中央对齐模式(向上/向下计数)在中央对齐模式中,计数器从0计数到自动加载值,产生一个计数器上溢事件,然后向下计数到1并且产生一个计数器溢事件,然后再从0开始重新计数。根据设置中断标志位的不同,又分为中央对齐模式1、2、3,具体参考教材p225,向上/向下计数模式,6.4.2 重复计数器,“时基单元”解释了计数器上溢/下溢时更新事件(UEV)是如何产生的,然而事实上它只能在重复计数达到0的时候产生。这个特性对产生PWM信号非常有用。 只有 高级定时器具有重复计数功能。 这意味着在每N次计数上溢或下溢时,数据从预装载寄存器传输到影子寄存器, N是TIMx_RCR重复计数寄存器中的值。,重复计数器在下述任一条件成立时递减: 向上计数模式下每次计数器溢出时, 向下计数模式下每次计数器下溢时, 中央对齐模式下每次上溢和每次下溢时。虽然这样限制了PWM的最大循环周期为128,但它能够在每个PWM周期2次更新占空比。在中央对齐模式下,因为波形是对称的,如果每个PWM周期中仅刷新一次比较寄存器,则最大的分辨率为2xTck。 重复计数器是自动加载的,重复速率是由TIMx_RCR寄存器的值定义,不同模式下更新速率的例子,例子:通过配置定时器相关寄存器的配置,实现定时器3每1s中断一次,通用定时器定时功能编程步骤,1)TIM3时钟使能。TIM3是挂载在APB1之下,所以我们通过APB1总线下的使能使能函数来使能TIM3。调用的函数是:RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);/时钟使能2)初始化定时器参数,设置自动重装值,分频系数,计数方式等。在库函数中,定时器的初始化参数是通过初始化函数TIM_TimeBaseInit实现的:voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);第一个参数是确定是哪个定时器,这个比较容易理解。第二个参数是定时器初始化参数结构体指针,结构体类型为TIM_TimeBaseInitTypeDef。针对TIM3初始化范例代码格式:TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period=5000; /设置自动重载计数周期值TIM_TimeBaseStructure.TIM_Prescaler=7199;/设置分频系数TIM_TimeBaseStructure.TIM_ClockDivision=0;/设置时钟分频因子TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;/设置计数方式TIM_TimeBaseInit(TIM3,通用定时器定时功能编程步骤,3)设置TIM3_DIER允许更新中断。在库函数里面定时器中断使能是通过TIM_ITConfig函数来实现的:voidTIM_ITConfig(TIM_TypeDef*TIMx,uint16_tTIM_IT,FunctionalStateNewState);第一个参数是选择定时器号,这个容易理解,取值为TIM1TIM18。第二个参数非常关键,是用来指明我们使能的定时器中断的类型,定时器中断的类型有很多种,包括更新中断TIM_IT_Update,触发中断TIM_IT_Trigger,以及输入捕获中断等等。第三个参数就很简单了,就是失能还是使能。例如我们要使能TIM3的更新中断,格式为:TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);,通用定时器定时功能编程步骤,4)TIM3中断优先级设置。在定时器中断使能之后,因为要产生中断,必不可少的要设置NVIC相关寄存器,设置中断优先级。5)允许TIM3工作,也就是使能TIM3。在配置完后要开启定时器,通过TIM3_CR1的CEN位来设置。在固件库里面使能定时器的函数是通过TIM_Cmd函数来实现的:voidTIM_Cmd(TIM_TypeDef*TIMx,FunctionalStateNewState)这个函数非常简单,比如我们要使能定时器3,方法为:TIM_Cmd(TIM3,ENABLE);/使能TIMx外设,通用定时器定时功能编程步骤,6)编写中断服务函数。在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,所以在状态寄存器SR的最低位。在处理完中断之后应该向TIM3_SR的最低位写0,来清除该中断标志。在固件库函数里面,用来读取中断状态寄存器的值判断中断类型的函数是:ITStatusTIM_GetITStatus(TIM_TypeDef*TIMx,uint16_t)该函数的作用是,判断定时器TIMx的中断类型TIM_IT是否发生中断。比如,我们要判断定时器3是否发生更新(溢出)中断,方法为:if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)固件库中清除中断标志位的函数是:voidTIM_ClearITPendingBit(TIM_TypeDef*TIMx,uint16_tTIM_IT)该函数的作用是,清除定时器TIMx的中断TIM_IT标志位。使用起来非常简单,比如我们在TIM3的溢出中断发生后,我们要清除中断标志位,方法是:TIM_ClearITPendingBit(TIM3,TIM_IT_Update);,作业,根据上述定时器编程流程,实现定时器3定时时间为0.5秒,定时时间到达后,翻转LED灯的状态,达到LED灯闪烁的效果,闪烁周期1秒,6.4.4 输入捕获,输入捕获功能概述输入捕获功能是用来检测外部事件或输入信号的。输入捕获功能可以用来测量周期信号的周期,频率和占空比等参数;也适于测量非周期输入信号的脉冲宽度、到达时刻或消失时刻等参数。,6.4.4 输入捕获,输入捕获模式可以用来测量脉冲宽度或者测量频率。STM32的定时器,除了TIM6和TIM7,其他定时器都有输入捕获功能。STM32的输入捕获,简单的说就是通过检测TIMx_CHx上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(TIMx_CNT)存放到对应的通道的捕获/比较寄存器(TIMx_CCRx)里面,完成一次捕获。同时还可以配置捕获时是否触发中断/DMA等。,捕获通道1的功能框图,输入捕获编程流程,基本功能:通用定时器作为输入捕获的使用。我们将用TIM3的通道2(PA7)来做输入捕获,捕获PA7上两次上升沿,计算信号频率输入捕获流程详见课本P251,输入捕获编程流程,输入捕获的配置步骤:1)开启TIM3时钟和GPIOA时钟,配置PA7为下拉输入。要使用TIM3,我们必须先开启TIM3的时钟。这里我们还要配置PA7为下拉输入,因为我们要捕获TIM3_CH2上面的高电平脉宽,而TIM3_CH2是连接在PA7上面的。RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);/使能TIM3时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);/使能GPIOA时钟,输入捕获编程流程,2)初始化TIM3,设置TIM3的ARR和PSC。在开启了TIM3的时钟之后,我们要设置ARR和PSC两个寄存器的值来设置输入捕获的自动重装载值和计数频率。这在库函数中是通过TIM_TimeBaseInit函数实现的TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Period=arr;/设定计数器自动重装值TIM_TimeBaseStructure.TIM_Prescaler=psc;/设置预分频值TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;/ TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;/TIM 向上计数模式TIM_TimeBaseInit(TIM3,输入捕获编程流程,3)设置TIM3的输入比较参数,开启输入捕获输入比较参数的设置包括映射关系,滤波,分频以及捕获方式等。这里我们需要设置通道2为输入模式,且IC2映射到TI2(通道2)上面,并且不使用滤波(提高响应速度)器,上升沿捕获。库函数是通过TIM_ICInit函数来初始化输入比较参数的:voidTIM_ICInit(TIM_TypeDef*TIMx,TIM_ICInitTypeDef*TIM_ICInitStruct);同样,我们来看看参数设置结构体TIM_ICInitTypeDef的定义:typedefstructuint16_t TIM_Channel;/设置通道uint16_t TIM_ICPolarity;/设 置 输 入 信 号 的 有效 捕获 极性uint16_t TIM_ICSelection;/设置映射关系uint16_t TIM_ICPrescaler;/设置 输入捕获分频系数uint16_t TIM_ICFilter;/设置滤波器长度TIM_ICInitTypeDef;,输入捕获编程流程,配置代码是:TIM_ICInitTypeDef TIM_ICInitStructure;TIM3_ICInitStructure.TIM_Channel=TIM_Channel_2;/选择输入端 IC2 映射到 TI2 上TIM3_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;/上升沿捕获TIM3_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;/映射到 TI2 上TIM3_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;/配置输入分频,不分频TIM3_ICInitStructure.TIM_ICFilter=0 x00;/IC1F=0000 配置输入滤波器 不滤波TIM_ICInit(TIM3,输入捕获编程流程,4)使能捕获和更新中断(设置TIM3的DIER寄存器)因为我们要捕获的是高电平信号的脉宽,所以,第一次捕获是上升沿,第二次捕获时下降沿,必须在捕获上升沿之后,设置捕获边沿为下降沿,同时,如果脉宽比较长,那么定时器就会溢出,对溢出必须做处理,否则结果就不准了。这两件事,我们都在中断里面做,所以必须开启捕获中断和更新中断。这里我们使用定时器的开中断函数TIM_ITConfig即可使能捕获和更新中断:TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);/允许更新中断和捕获中断,输入捕获编程流程,5)设置中断分组,编写中断服务函数设置中断分组主要是通过函数NVIC_Init()来完成。分组完成后,我们还需要在中断函数里面完成数据处理和捕获设置等关键操作,从而实现高电平脉宽统计。在中断服务函数里面,跟以前的外部中断和定时器中断实验中一样,我们在中断开始的时候要进行中断类型判断,在中断结束的时候要清除中断标志位。使用到的函数分别为TIM_GetITStatus()函数和TIM_ClearITPendingBit()函数。if(TIM_GetITStatus(TIM3,TIM_IT_Update)!=RESET)/判断是否为更新中断if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)/判断是否发生捕获事件TIM_ClearITPendingBit(TIM3,TIM_IT_CC1|TIM_IT_Update);/清除中断和捕获标志位,输入捕获编程流程,6)使能定时器(设置TIM3的CR1寄存器)最后,必须打开定时器的计数器开关,启动TIM5的计数器,开始输入捕获。TIM_Cmd(TIM5,ENABLE);/使能定时器5,作业,根据输入捕获的编程流程,完成上述编程,实现其功能,PWM输入捕获模式,PWM输入捕获模式是输入捕获模式的特例,自己理解如下1. 每个定时器有四个输入捕获通道IC1、IC2、IC3、IC4。且IC1 IC2一组,IC3 IC4一组。并且可是设置管脚和寄存器的对应关系。2. 同一个TIx输入映射了两个ICx信号。3. 这两个ICx信号分别在相反的极性边沿有效。4. 两个边沿信号中的一个被选为触发信号,并且从模式控制器被设置成复位模式。5. 当触发信号来临时,被设置成触发输入信号的捕获寄存器,捕获“一个PWM周期(即连续的两个上升沿或下降沿)”,它等于包含TIM时钟周期的个数(即捕获寄存器中捕获的为TIM的计数个数n)。6. 同样另一个捕获通道捕获触发信号和下一个相反极性的边沿信号的计数个数m,即(即高电平的周期或低电平的周期)7. 由此可以计算出PWM的时钟周期和占空比了 frequency=f(TIM时钟频率)/n。 duty cycle=(高电平计数个数/n), 若m为高电平计数个数,则duty cycle=m/n 若m为低电平计数个数,则duty cycle=(n-m)/n注:因为计数器为16位,所以一个周期最多技术65535个,所以测得的 最小频率= TIM时钟频率/65535。,6.4.5 输出比较模式,脉冲宽度调制(PWM),是英文“PulseWidthModulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。STM32的定时器除了TIM6和7。其他的定时器都可以用来产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出,这样,STM32最多可以同时产生30路PWM输出!首先要提到的是,PWM相关的函数设置在库函数文件stm32f10 x_tim.h和stm32f10 x_tim.c文件中。,6.4.5 输出比较模式,通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCR被用作比较功能,下面把它简称为比较寄存器。这里直接举例说明定时器的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),6.4.5 输出比较模式,输出比较模式的配置步骤: 选择计数器时钟(内部,外部,预分频器)。 将相应的数据写入TIMx_ARR和TIMx_CCRx寄存器中如果要产生一个中断请求,设置CCxIE位。 选择输出模式,例如: 要求计数器与CCRx匹配时翻转OCx的输出引脚,设置OCxM=011 置OCxPE = 0禁用预装载寄存器 置CCxP = 0选择极性为高电平有效 置CCxE = 1使能输出 设置TIMx_CR1寄存器的CEN位启动计数器,输出比较模式结构图,然后来理解输出比较的几个模式(PWM模式是输出比较模式的特例),TIM输出比较的三种模式,1、输出比较模式000:冻结。输出比较寄存器TIMx_CCR1与计数器TIMx_CNT间的比较对OC1REF不起作用;也就是Timing模式。是在比较成功后不在对应输出管脚上产生输出001:匹配时设置通道1为有效电平。当计数器TIMx_CNT的值与捕获/比较寄存器1(TIMx_CCR1)相同时,强制OC1REF为高。这个也就是ACTIVE模式010:匹配时设置通道1为无效电平。当计数器TIMx_CNT的值与捕获/比较寄存器1(TIMx_CCR1)相同时,强制OC1REF为低。这个也就是INACTIVE模式011:翻转。当TIMx_CCR1=TIMx_CNT时,翻转OC1REF的电平。也就是toggle模式是在比较成功后翻转对应输出管脚上的电平,TIM输出比较的三种模式,2、强制输出模式1)100强制为无效电平2)101强制为有效电平强制有效电平、强制无效电平在固件库中也有对应的设置:TIM_ForcedAction_Active和TIM_ForcedAction_InActive,对应的函数是:void TIM_ForcedOCxConfig(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction),但在之前也需要配置TIM_OCInitTypeDef结构体来使能相应的通道,并设置对应端口的极性;,TIM输出比较的三种模式,3、PWM输出模式 1)PWM模式1 2)PWM模式2PWM1和PWM2在固件库中有对应的模式设置:TIM_OCMode_PWM1(脉冲宽度调制模式1)、TIM_OCMode_PWM2(脉冲宽度调制2),其中PWM1和PWM2的区别就是他们的输出是恰好相反的,就像配置TIM1的通道1、2、3为互补输出的关系一样吧,通过调用函数void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);初始化TIM_OCInitTypeDef结构体实现配置,最后一定要记得调用函数设置BDTR的MOE位,使能输出:void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);,PWM输出模式编程流程,首先要提到的是,PWM相关的函数设置在库函数文件stm32f10 x_tim.h和