STM32基础教程(CubeMX)—— 定时器

定时器

定时器原理

原理

  本质上就是一个记录脉冲数量的计数器,当记的数达到上限时会发生“溢出”,计时器清零同时产生一个信号,这个信号可以代表很多事件,定时器中断就是其一。
  定时器的功能有输出比+和输入捕获两种,输出比较就是定时和PWM功能等,输入捕获用于测量。

分频器(PSC)的原理

  如果只是使用时钟信号作为基本的脉冲进行计数,虽然精度相当高,但是计数的最大时间受到了很大的限制,因此引入了分频的概念。分频,本质上就是在时钟和定时器中间再加上一个定时器,这个定时器就叫做分频器,定时器实际上记录的脉冲是分频器传递出来的脉冲。

自动重载寄存器(ARR)

  如果只是使用定时器与分频器,那么为了获得非最大时间的定时,就需要在定时器开始计时的时候设置一个初始时间,ARR解决了这个问题,它相当于降低了计时器的最大时间,让计时器到指定的时间就发生溢出。

定时器PWM原理
  • PWM(脉宽调制)的原理:通过调节矩形脉冲的占空比,达到控制输出量大小(等效大小)的目的。如果占空比一直不变,常用来做亮度调整、电机速度调整等。如果占空比随时改变,常用来模拟正弦量等连续信号(逆变)。
  • 定时器PWM的原理
  1. 原理有输入捕获和输出比较两个部分。为了通过定时器实现PWM功能,指定了一个GPIO引脚为捕获/比较引脚,同时添加一个捕获/比较寄存器(CCR)。
  2. 输出比较原理:给捕获/比较寄存器一个值,这个值介于零与ARR之间。计数分频后的脉冲,当计数达到CCR的值时,捕获比较引脚的电平状态进行翻转,同时产生一个捕获比较事件(Capture Compare),脉冲计数继续进行。当脉冲计数达到ARR的值时,定时器清零,因定时器的值再次小于CCR所以捕获比较引脚状态再次翻转,同时产生一个更新事件(Updata)。
  3. 输入捕获原理:输入捕获有两种方法,T法与M法,都是用来测量外部输入的脉冲的频率的。

CubeMX的操作

定时功能的设置(对应Updata事件)
  1. 在"Pinout & Configuration"界面下,左侧选择下拉菜单"Timers",下拉菜单中“TIM1”到“TIM8”都是定时器,选择一个定时器,中间的界面里出现对应的窗口。
  2. 第三个选项“Clock Source”选择“Internal Clock”内部时钟。内部时钟的频率在"Clock Configuration"界面下,“HCLK(MHz)”后面的“APB1”和“APB2”后面的“APB1/2 timer clocks”中设置,至于哪个定时器属于哪个APB,需要查询数据手册。
  3. 在Mode窗口下面的Configuration窗口里,第一个菜单,第一个下拉菜单里第一项PSC,这里设置PSC的值。注意, = 1 + P S C 分频值=1+PSC ,分频后的等效频率就相当于原始频率乘以分频值分之一,这里PSC的值与分频值之所以不一样,是因为PSC在最后一个脉冲到来后才会进位。
  4. 第三个选项设置ARR的值,从ARR的名字,或者点击右上角的“i”按钮后在点击ARR那一行,可以看到ARR的位数,也就相当于是定时器的位数。设置PSC和ARR的时候要综合考虑将来要设置的定时时间。同样的,要计数5000次的话,ARR应该设置4999。

举例:假设我选择定时器2(TIM2),内部时钟。考虑到我要定时500ms,那么就需要选择7199PSC,即等效时钟为10kHz,一次脉冲相当于0.1+ms。因此,我需要计数5000次,那么ARR就需要设置为4999。这样一来,ARR的值没有超过限制,PSC的值也没有超过限制(位数的限制),次设置就是合理的。而如果PSC设置为71,等效频率1MHz,那么即使ARR调到最大,计时也只有一百多ms而已。

定时器中断的设置
  1. 设定好定时器的定时功能后,它在每次定时到了归零的时候,都会产生一个Updata事件,这个时候如果开启定时器全局中断,就可以在中断服务函数里面寻找处理Updata事件的中断回调函数进行中断的处理。
  2. NVIC Settings菜单下勾选定时器全局中断。这里其实也可以在左侧的NVIC菜单中设置,设置方式与打开外部中断的方式一致,顺便还可以设置优先级。
定时器触发外部设备(Trigger Out事件)
  1. 在Mode窗口下面的Configuration窗口里,第一个菜单,第二个下拉菜单"Trigger Output (TRGO) Parameters"就是该事件的设置菜单。
  2. 第一个选项“Master/Slave Mode(MSM bit)”是让定时器既做主机触发别人,又做从机被别人触发,一般不选。
  3. 第二个选项就是选择由说明事件触发Trigger Out事件,Trigger Out事件就是定时器向外发送的一个信号,可以用来触发别的外设。
输入捕获的设置
  1. 在定时器的配置界面中,随便选择一个通道,设置为"Input Capture direct mode",即设置为输入捕获模式。
  2. 此时下方"Parameter Settings"窗口中出现输入捕获下拉菜单"Input Capture Channel",第一个选项"Polarity Selection"设置的是捕获目标,默认是上升沿捕获。
  3. 第三个选项是分频"Prescaler Division Ratio"选项,一般选择不分频。
  4. 第四个选项是数字滤波器滤波次数的选择,就是连续捕获多少次才认为真的出现了目标电平,一般设为8。
  5. 对应的输入捕获引脚设置为下拉电阻(根据你要捕获的信号来设置),保证没有目标信号时输入电平的稳定。
  6. 打开定时器的全局中断,将来需要在中断里面对捕获到的值进行处理。
PWM功能的设置
  1. 与定时器的设置类似,打开定时器的设置界面。在“Mode”界面中,第四个选项(Channel)开始,开启定时器的通道,将通道选择为“PWM Generation CH1”,它是输出比较模式“Ooutput Compare CH1”的一个特例。其中,“CH1”是通道1的意思,有时候只有一个通道,不一定有多个通道。“CH1N”是CH1通道的反相。
  2. PWM定时器定时功能设置:因为PWM功能需要用到定时器的定时功能才能完成输出比较,所以在初始化的时候也需要对定时功能进行设置,一般PWM的频率至少是200Hz,设置方面参考前面对定时功能的描述。
  3. ARR对PWM精确度的影响:ARR的值越大,CCR可以设置的值的范围就越大,PWM就越精确。比如,ARR设置为4999(实际是计数5000次),那么PWM的精度就是五千分之一(CCR取值0到4999)。
  4. CCR的设置:CubeMX中,在Mode窗口下面的Configuration窗口里,在你选择了PWM模式后,这个窗口中会多一个PWM模式的下拉菜单,在里面找到“Pulse”选项,它就是CCR的值。
  5. 其他设置选项:PWM的模式选项,是指选择第一个出现的是高电平该是低电平等。“CH Polarity”选项可以选择是用高电平计算的占空比还是低电平。
  6. 中断的设置:如果需要捕获比较事件或者更新事件产生中断,就需要再NVIC里面勾选响应的中断。注意,即使不申请中断,PWM也是会生成的。
  7. 指定需要的输出口:在参数都设置好了之后,还需要考虑通道的输出口是否是你需要的输出口,STM32中每个定时器的通道对应的GPIO口都是固定的,即每个定时器对应的捕获比较引脚是固定的。因此,要么选择对应的定时器,要么用线将捕获比较引脚与你想要输出的引脚连接起来。注意,连接的时候捕获比较引脚是输出模式的,所以你要用的引脚应该是输入模式的。

Keil5的操作

定时功能的使用

   以上的步骤都只是初始化定时器,实际使用时还需要在函数中启用定时器,这里为了使用定时器中断,需要进行两步,即启用定时器和启用定时器中断。这两步可以通过一个函数HAL_TIM_Base_Start_IT(&htim2)解决。(如果只计时不中断可以去掉“_IT”使用另一个开始函数,比如只让定时器定时触发其他外设,不需要中断去做什么事情)
   注意:使用上面说的这个函数启用定时器,定时器在定时结束后会进入中断服务函数,之后重置并继续计时,并不会定时一次后就停止。要想只进行一次中断,就需要在中断服务函数的最后关闭定时器中断(继续定时但是不中断)或者关闭定时器时基(不定时了)。

定时器中断服务函数

   中断服务函数也在用户应用文件夹下的“芯片型号_it.c”文件中,关键词为TIM2,具体的名字是“TIM2_IRQHandler”。
   与外部中断服务函数不同的是,每个定时器都有自己独立的中断服务函数。与外部中断类似的是,定时器的中断服务函数也处理定时器的全部事件,这里我们使用的是Updata事件,所以在函数中寻找对应的if语句,我们需要对里面的回调函数HAL_TIM_PeriodElapsedCallback();进行编辑,编辑方式同外部中断。
   这个中断服务函数中写的东西只是占位用的,方式因为一个空的函数而警告用户。所以使用时直接去掉weak,在用户的其他.c文件中编写即可。需要注意的是,判断是否真的是中断,以及清空中断标志位,在之前if语句所在的那个函数里已经完成了。

PWM功能的使用

   与定时功能一样,要使用定时器还需要在程序里面启用定时器。如果只使用PWM功能而不使用中断,就需要打开定时器的时基与PWM两个功能,如果还要使用中断,就是开启时基、PWM、中断三个功能,都可以通过一个库函数实现,注意,打开PWM的同时需要指定打开的是哪个通道。以定时器1为例,同时打开时基和PWM通道1的函数是HAL_TIM_PWM_Start(&htim1,CHANNEL_1);

程序中设置定时器的值
  • 捕获比较寄存器的值(CCR): 把定时器1通道1的CCR设置为200,_HAL_TIM_SET_COMPARE(&htim1,CHANNEL_1,200);
输入捕获功能的使用
  1. 使用函数HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);开启定时器的输入捕获模式(带中断),同定时器的其他模式一样,开启后不会自动关闭,需要进行手动关闭。
  2. 在中断的.c文件中,寻找定时器的中断服务函数,使用“Go to”功能在里面寻找捕获完成的回调函数,在里面编辑内容。
  3. 使用HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1)获取定时器3通道1捕获的值,作为该函数的返回值。注意,一般来说应该在中断中获取捕获的值,否则可能不能及时获取捕获值。
  4. 使用__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING)设置定时器3通道1的捕获上升沿,最后一个参数就是捕获类型的设置。注意,这是一个预处理指令,因此Keil5可能不会联想出它对应的参数,不过打出最后一个参数的前几行应该就能联想出其他参数。
  5. 根据实际需要进行捕获的设置。例如要用T法测量频率,就应该先捕获一个上升沿,再捕获一个上升沿,两次捕获做差并计算频率。之后就可以关闭捕获了,总共进行两次捕获。

我测试的时候曾经半天没有搞出来,捕获到的值始终是0,如果遇到此类问题可以尝试重新创建工程,我推测是工程中的其他功能影响了采样,目前没有研究出具体原因。


猜你喜欢

转载自blog.csdn.net/weixin_43718316/article/details/107988779