qidao123.com ToB IT社区-企服评测·应用市场

标题: STM32学习之通用定时器 [打印本页]

作者: 十念    时间: 2025-11-5 20:58
标题: STM32学习之通用定时器
1. 通用定时器概述

1.1 通用定时器与根本定时器的差别

通用定时用具有根本定时器的全部特性,在此根本上通用定时器多出来一些自身特有的功能。根本定时器只能递增计数,而通用定时器还可以递减计数,可以中央对齐计数,根本定时器只可以触发ADC,而通用定时器还可以触发DAC,根本定时器只有在更新变乱(计数器溢出)发生的时间才会产生克制/DMA哀求,通用定时器还可以在触发变乱、输入捕捉、输出比力时,也产生克制/DMA哀求。
除此以外,根本定时器是没有外部通道的,而通用定时器会有四个独立通道,可用于:输入捕捉、输出比力、输出PWM、单脉冲模式,可以使用外部信号控订定时器来实现多个定时器互连的同步电路,用一个定时器的溢出来驱动另一个定时器的计数器举行计数,也就是定时器的级联,同时也支持编码器和霍尔传感器电路等。
1.2 通用定时器的核心功能

通用定时器的本质也是通过计数器来举行定时计数,和根本定时器最大的差别是有了输入输出通道,以是平常的来说就是通过定时器来控制通道的输入和输出,具体来说告急分为以下几点:

2. 通用定时器的根本原理

2.1 时钟源与预分频器

内部时钟(APB总线时钟)
外部时钟模式(ETR引脚、外部触发输入)
预分频器(PSC)的作用与盘算(怎样设置分频值)。
2.2 计数器模式

向上计数(Upcounting)
向下计数(Downcounting)
中央对齐模式(中央对齐PWM的设置与波形分析)。
主动重载寄存器(ARR)
怎样盘算定时周期(公式:T = (ARR+1) * (PSC+1) / F_clk)。
3. 通用定时器的设置流程(以TIM3为例)

3.1 CubeMX图形化设置

时钟树设置(确认APB总线频率)。
定时器参数设置:
模式选择(PWM天生、输入捕捉等)。
预分频器(PSC)与主动重载值(ARR)。
通道设置(CH1-CH4的复勤奋能)。
3.2 代码实现(HAL库)

初始化函数分析(HAL_TIM_Base_Init())。
PWM启动代码(HAL_TIM_PWM_Start())。
克制与回调函数(如HAL_TIM_PeriodElapsedCallback())。
4. 实战案例——通用定时器的典范应用

4.1 案例1:PWM输出驱动LED呼吸灯

硬件毗连:LED接至TIMx_CHx引脚。
关键代码:动态修改占空比(__HAL_TIM_SET_COMPARE())。
效果演示:呼吸灯波形(示波器截图或逻辑分析仪数据)。
4.2 案例2:输入捕捉丈量脉冲宽度

硬件毗连:外部信号接至TIMx_CHx引脚。
代码逻辑:
上升沿/降落沿捕捉设置。
盘算脉冲宽度(使用捕捉值差值)。
调试本领:怎样克制捕捉溢出?
4.3 案例3:编码器模式读取电机转速

硬件毗连:正交编码器信号接至TIMx_CH1/CH2。
代码分析:编码器模式初始化与计数值读取。
数据处理惩罚:通过计数值盘算转速(RPM)。
1.1通用定时器先容

通用定时用具有根本定时器的全部特性,根本定时器只能递增计数,而通用定时器可以递减计数,可以中央对齐计数;也可以触发ADC和DAC,同时在更新变乱,触发变乱,输入捕捉,输出比力的时间可以产生克制和DMA哀求,而根本定时器只有更新变乱的时间可以触发克制或DMA哀求,通用定时器另有独立通道用来和外部举行信息交互,比如输入捕捉,输出比力,输出PWM和单脉冲模式,这就有个疑问了,之前根本定时器就看到设置寄存器里有单脉冲模式,但是原子的教程说这个是通用定时器特有,有空可以做个实行验证一下根本定时器有没有单脉冲模式。通用定时器可以使用外部信号控订定时器,可以实现多个定时器互连的同步电路,应该就是主从模式了。也支持编码器和霍尔传感器电路等,这些东西是用在电机控制中的。现在很多概念都不懂,随着学习的深入逐步明白吧。
1.2 通用定时器框图


通用定时器的框图比根本定时器多了很多东西,由于它包罗了根本定时器全部的功能,以是可以先从框图里找到根本定时器的布局,剩下的就是通用定时器对它的扩展,下面对框图大抵解说一下,背面会具体阐明。
①时钟源
根本定时器的时钟只能来自内部时钟,也就是APB总线上时钟颠末倍频器之后得到的时钟,而通用定时器的时钟可以有4个泉源,1:来自APB总线的时钟;2:内部触发输入的时钟,就是①中的ITR0到ITR3的部分,这个内部信号就是其他的定时器;3:外部时钟模式1,右下角的TI1F_ED,TI1FP1和TI2FP2,这个来自下面第④部分的输入滤波器和边沿检测器,最初是来自外部IO口的输入,只有外部通道TIMx_CH1和TIMx_CH2的输入信号可以作为时钟源;4:图中TIMx_ETR的那边,来自外部IO口,称为外部时钟模式2。
②控制器
TRGO触发信号可以毗连到别的定时器的ITR0到ITR3,作为别的定时器的时钟源,也就是完成定时器的级联;从模式和根本定时器没什么区别。
控制器包罗:从模式控制器、编码器接口和触发控制器(TRGO)。从模式控制器可以控制计数器复位、启动、递增/递减、计数。编码器接口针对编码器计数。触发控制器用来提供触发信号给别的外设,可以毗连到别的定时器的ITR0到ITR3,作为别的定时器的时钟源,也就是完成定时器的级联,也可以为 DAC/ADC 的触发转换提供信号。
③时基单元
这个就和根本定时器一样,参考STM32学习之根本定时器。
④输入捕捉
以TIMx_CH1为例,信号从外部输入后先颠末一个异或门(常用于电机控制范畴,这里先忽略),然后进入输入滤波器和边沿检测器,滤波器可以过滤掉一些高频噪声,然后得到两个信号,TI1FP1和TI2FP2,这两个信号可以由我们用户自己选择映射到IC1还是IC2,不能同时使用,一样寻常就是CH1映射到IC1,然后颠末一个预分频器之后产生一个捕捉变乱U,捕捉变乱就是捕捉的上升沿还是降落沿,产生捕捉变乱之后就会把计数器的值转移到捕捉比力1寄存器内里,来一次变乱记一个数,如许就可以根据设置去盘算外部信号的时间,比如周期和脉宽之类的。除了捕捉变乱U以外还可以通过设置来产生一个CC1I克制。
⑤输入比力
这部分是毗连④和⑤的桥梁,联合别的两部分看就可以了。
⑥输出比力
将计数器的值与预先存入捕捉/比力1寄存器的影子寄存器举行比力,假如二者相称,则会使输出参考信号举行改变,这个信号为固定高电平有用,同时还会产生一个比力变乱CC1I, 假如同时开启了克制的话还会开启比力克制,输出参考信号会进入输出控制来控制产生一些信号,比如PWM,然后通过TIMx_CH1输出。图片的最左边和最右边属于分时复用,同一时间根据IO扣得设置模式只能有一个起作用。
现在对上面的框图具体表明一下。
1.2.1. 通用定时器时钟源

时钟模式泉源设置方法内部时钟(CK_INT)APB总线设置 TIMx_SMCR 的 SMS=0000外部时钟模式1外部输入引脚TIx设置 TIMx_SMCR 的 SMS=1111外部时钟模式 2外部触发输入ETR设置 TIMx_SMCR 的 ECE=1内部触发输入模式内部触发输入ITRx参考《STM32F10xxx参考手册_V10(中文版).pdf》 14.3.15 末节 1.2.2. 通用定时器输入捕捉

输入捕捉是用来收罗外部信号的上升沿和降落沿的,一个常见的应用就是电机转动的时间收罗霍尔数,是一系列的脉冲信号,本质上就是一个pwm波,霍尔数就是指此中的上升沿和降落沿的数量,一种方法就是采取输入捕捉,然后在上升沿和降落沿的时间触发克制,在克制函数内对计数变量加1就行了。STM32的输入捕捉告急用到上面通用定时器框图的④和⑤部分,TIMx_CH1~TIMx_CH4 表现定时器的 4 个通道,这 4 个通道都是独立工作的。通过IO端口复勤奋能将IO口与这些计数器通道相连。设置好 IO 端口的复勤奋能后,将必要丈量的信号输入到相应的IO 端口,输入捕捉部分就可以对输入的信号的上升沿,降落沿大概双边沿举行捕捉了,常见的丈量有:丈量输入信号的脉冲宽度、丈量 PWM 输入信号的频率和占空比等。本质上是通过计数器收罗时间的,以是喊空比和频率都是后期算出来的,原始的读出来的数据一样寻常都是脉宽和周期,然后根据这俩去盘算其他的信息。
在丈量脉宽的时间一样寻常要先设置输入捕捉的边沿检测极性,如:我们设置上升沿检测,那么当检测到上升沿时,定时器会把计数器 CNT的值锁存到相应的捕捉/比力寄存器 TIMx_CCRy 里, y=1~4。然后我们再设置边沿检测为降落沿检测,当检测到降落沿时,定时器会把计数器 CNT 的值再次锁存到相应的捕捉/比力寄存器TIMx_CCRy 里。末了,我们将前后两次锁存的 CNT 的值相减,就可以算出高电平脉冲期间内
计数器的计数个数,再根据定时器的计数频率就可以盘算出这个高电平脉冲的连续时间。假如要丈量的高电平脉宽时间长度凌驾定时器的溢出时间周期,就会发生溢出,这时间还必要做定时器溢出的额外处理惩罚。以通道1来简朴先容一下:

外部信号TI1通过IO口进入TIMx_CH1后,先颠末一个滤波器,滤波器的设置由TIMx_CCMR1决定,接着颠末边沿检测器,由 CC1P 位来设置检测的边沿,可以上升沿大概降落沿检测。 CC1NP是设置互补通道的边沿检测的,只有在高级定时器才有,通用定时器没有。然后颠末输入捕捉映射选择器,由 CC1S[1:0]位来选择把 IC1 映射到TI1FP1、TI2FP1还是 TRC。这里我们的待丈量信号从通道1进来,以是选择IC1 映射到TI1FP1。紧接着颠末输入捕捉 1 预分频器,由 ICPS[1:0]位来设置预分频系数,范围: 1、 2、 4、 8。末了把CC1E位置1,使能输入捕捉, IC1PS 就是分频后的捕捉信号。这个信号将会到达通用定时器框图的第⑤部分,下图是第⑤部分的放大版。

上图的灰色阴影部分是输出比力功能部分,和输入捕捉无关。左边没有阴影部分是输入捕捉功能部分。起首看到捕捉/比力预装载寄存器,还是以通道1为例,它就是CCR1寄存器,通道 2、通道 3、通道 4 就是CCR2、CCR3、CCR4。在最开始通用定时器框图中可以看到 CCR1~4 是有影子寄存器的,以是这里就可以看到上图中有捕捉/比力影子寄存器,影子寄存器都是不可直接访问的。上图左下角TIMx_EGR寄存器的CC1G位可以产生软件捕捉变乱,和根本定时器的更新变乱一样,就是软件触发一个更新变乱来将预装载寄存器的值通报到对应的影子寄存器中,那么硬件捕捉变乱怎样产生的?这里我们还是以通道 1 输入为例,CC1S[1:0] = 01,即IC1映射到TI1上;CC1E位置1,使能输入捕捉;比如不滤波、不分频, ICF[3:0] = 00, ICPS[1:0] = 00;比如检测上升沿, CC1P 位置 0;接着就是等候丈量信号的上升沿到来。当上升沿到来时, IC1PS 信号就会触发输入捕捉变乱发生,计数器的值就会被锁存到捕捉/比力影子寄存器里。当 CCR1 寄存器没有被举行读利用的时间,捕捉/比力影子寄存器里的值就会锁存到 CCR1 寄存器中,那么步调员就可以读取 CCR1 寄存器,得到计数器的计数值。检测降落沿同理。
1.2.3. 通用定时器输出比力

输出比力是用来向外部发出信号的,一样寻常是周期性的发出高低电平,一个常见的应用就是发出PWM波来控制MOS管来进一步控制电机的转速和车灯的亮度等。STM32的输出比力告急用到通用定时器框图的⑤和⑥部分,和输入捕捉一样,TIMx_CH1~TIMx_CH4 表现定时器的4个通道,这 4 个通道都是独立工作的。通过IO端口复勤奋能将IO口与这些计数器通道相连。下图是通用定时器框图的第⑤部分的放大版:

灰色阴影部分是输入捕捉功能部分,前面已经说过了。右 边没有阴影部分就是输出比力功能部分。下面以通道 1 输出比力功能为例来看定时器怎样实现输出功能的。起首向CCR1 寄存器内写入比力值。这个比力值必要转移到对应的捕捉/比力影子寄存器后才会真正见效。当compare_transfer 旁边与门的三个条件都满足的时间才会举行数据转移:1. CCR1 不在写入利用期间、 2. CC1S[1:0] = 0 设置为输出、 3. OC1PE位置0(大概OC1PE 位置1,而且必要发生更新变乱,这个更新变乱可以软件产生大概硬件产生)。当 CCR1 寄存器的值转移到其影子寄存器后,新的值就会和计数器的值举行比力,它们的比力效果将会通过第⑥部分影响定时器的输出。下面看第⑥部分:

可以看到输出模式控制器,由OC1M[2:0]位设置输出比力模式,该位的形貌必要看参考手册。oc1ref 是输出参考信号,高电平有用,为高电平常称之为有用电平,为低电平常称之为无效电平。它的高低电平受到三个方面的影响:1. OC1M[3:0]位设置的输出比力模式,2. 第⑤部分比力器的比力效果,3. OC1CE位设置的ETRF信号,ETRF信号就是通用定时器框图第⑤部分最下面和第①部分上面的谁人信号。 ETRF 信号可以将 Oc1ref 电平欺压清零,该信号来自 IO 外部。
一样寻常来说,当计数器的值和捕捉/比力寄存器的值相称时,输出参考信号 oc1ref 的极性就会根据我们选择的输出比力模式而改变。假如开启了比力克制,还会触发比力克制。CC1P 位用于选择通道输出极性,设置高电平就输出高电平,设置低电平就取反后输出。CC1E 位置 1 使能通道输出。OC1 信号就会从 TIMx_CH1 输出到 IO 端口,再到 IO 外部。
1.3. 通用定时器寄存器学习

1.3.1. 控制寄存器 1(TIMx_CR1)

寄存器低十位有用。

1.3.2. 控制寄存器2(TIMx_CR2)

寄存器7:3位有用。

1.3.3. 从模式控制寄存器(TIMx_SMCR)

这个寄存器除了第3位生存,别的全部位都故意义。

1.3.4. DMA/克制使能寄存器(TIMx_DIER)

这个寄存器的各个位的作用是用来使能和克制一些克制和DMA哀求的,没什么好说的。
1.3.5. 状态寄存器(TIMx_SR)

这个寄存器工是个位有用,记载捕捉比力的一些标记位。

1.3.6. 变乱产生寄存器(TIMx_EGR)

这个寄存器6个位有用。

1.3.7. 捕捉/比力模式寄存器1(TIMx_CCMR1)

这个寄存器的16位均有用,高八位和低八位功能雷同,只是针对差别的器通道:
输出比力模式:

1.3.8. 捕捉/比力模式寄存器2(TIMx_CCMR2)

寄义雷同,针对通道3和4。
1.3.9. 捕捉/比力使能寄存器(TIMx_CCER)

这个寄存器设置四个定时器通道的输出极性和使能:

1.3.10. 计数器(TIMx_CNT)

16位寄存器,CNT[15:0]:储存计数器的值。
1.3.11. 预分频器(TIMx_PSC)

16位寄存器,PSC[15:0]:储存预分频器的值。
1.3.12. 主动重装载寄存器(TIMx_ARR)

16位寄存器,ARR[15:0]:包罗了将要传送至实际工作的主动重装载寄存器的数值。
1.3.13. 捕捉/比力寄存器 1(TIMx_CCR1)

16位寄存器,CCR1[15:0]: 捕捉/比力1的值,当CC1通道是输出时,CCR1包罗了装入当前捕捉/比力1寄存器的值(预装载值);当CC1通道是输入时,CCR1包罗了由上一次输入捕捉1变乱(IC1)传输的计数器值。
1.3.14. 捕捉/比力寄存器 2(TIMx_CCR2)

16位寄存器,CCR2[15:0]: 捕捉/比力2的值,当CC2通道是输出时,CCR2包罗了装入当前捕捉/比力1寄存器的值(预装载值);当CC2通道是输入时,CCR2包罗了由上一次输入捕捉1变乱(IC2)传输的计数器值。
1.3.15. 捕捉/比力寄存器 3(TIMx_CCR3)

16位寄存器,CCR3[15:0]: 捕捉/比力3的值,当CC3通道是输出时,CCR3包罗了装入当前捕捉/比力1寄存器的值(预装载值);当CC3通道是输入时,CCR3包罗了由上一次输入捕捉1变乱(IC3)传输的计数器值。
1.3.16. 捕捉/比力寄存器 4(TIMx_CCR4)

16位寄存器,CCR4[15:0]: 捕捉/比力4的值,当CC4通道是输出时,CCR4包罗了装入当前捕捉/比力1寄存器的值(预装载值);当CC4通道是输入时,CCR4包罗了由上一次输入捕捉1变乱(IC4)传输的计数器值。
1.3.17. DMA控制寄存器(TIMx_DCR)

位12:8,DBL[4:0]: DMA连续传送长度 (DMA burst length);
位4:0,DBA[4:0]: DMA基所在 (DMA base address)。
现在还用不到。
1.3.18. 连续模式的DMA所在(TIMx_DMAR)

位15:0,DMAB[15:0]: DMA连续传送寄存器 (DMA register for burst accesses),现在还用不到。
1.4. PWM输出实行

pwm输出实行的目标是通过使用定时器来出书pwm波控制LED0来实现一个呼吸灯。通过上面知识的学习可以知道定时器输出pwm波的原理很简朴,由于定时器计数的频率是确定的,以是通过预先设置好捕捉比力寄存器的值和主动重装载寄存器的值就可以调治pwm的高脉宽和周期了,这俩参数确定了以后pwm波的全部的信息就都确定了。
1.4.1. 原理图阅读


这里只需用用到LED0,LED0的一端接入VCC,另一端接入MCU的PB5,以是必要检察PB5可以映射哪些功能,打开数据手册找到PB5的引脚界说如下:

可以看到PB5可以重映射到TIM3_CH2,以是必要将PB5映射到TIM3_CH2。
1.4.2. 定时器的初始化

  1. void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc)
  2. {
  3.     uint8_t chy = GTIM_TIMX_PWM_CHY;
  4.     GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE();    /* TIMX 通道 IO口时钟使能 */
  5.     GTIM_TIMX_PWM_CHY_CLK_ENABLE();         /* TIMX 时钟使能 */
  6.     sys_gpio_set(GTIM_TIMX_PWM_CHY_GPIO_PORT, GTIM_TIMX_PWM_CHY_GPIO_PIN,
  7.                  SYS_GPIO_MODE_AF, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PU);    /* TIMX PWM CHY 引脚模式设置 */
  8.     sys_gpio_remap_set(10, 2, 2);         /* IO口重映射 */
  9.     GTIM_TIMX_PWM->ARR = arr;       /* 设定计数器自动重装值 */
  10.     GTIM_TIMX_PWM->PSC = psc;       /* 设置预分频器  */
  11.     GTIM_TIMX_PWM->BDTR |= 1 << 15; /* 使能MOE位(仅TIM1/8 有此寄存器,必须设置MOE才能输出PWM), 其他通用定时器, 这个
  12.                                      * 寄存器是无效的, 所以设置/不设置并不影响结果, 为了兼容这里统一改成设置MOE位
  13.                                      */
  14.     if (chy <= 2)
  15.     {
  16.         GTIM_TIMX_PWM->CCMR1 |= 6 << (4 + 8 * (chy - 1));   /* CH1/2 PWM模式1 */
  17.         GTIM_TIMX_PWM->CCMR1 |= 1 << (3 + 8 * (chy - 1));   /* CH1/2 预装载使能 */
  18.     }
  19.     else if (chy <= 4)
  20.     {
  21.         GTIM_TIMX_PWM->CCMR2 |= 6 << (4 + 8 * (chy - 3));   /* CH3/4 PWM模式1 */
  22.         GTIM_TIMX_PWM->CCMR2 |= 1 << (3 + 8 * (chy - 3));   /* CH3/4 预装载使能 */
  23.     }
  24.     GTIM_TIMX_PWM->CCER |= 1 << (4 * (chy - 1));        /* OCy 输出使能 */
  25.     GTIM_TIMX_PWM->CCER |= 1 << (1 + 4 * (chy - 1));    /* OCy 低电平有效 */
  26.     GTIM_TIMX_PWM->CR1 |= 1 << 7;   /* ARPE使能 */
  27.     GTIM_TIMX_PWM->CR1 |= 1 << 0;   /* 使能定时器TIMX */
  28. }
复制代码

1.4.3. 主步调解读

  1.     while (1)
  2.     {
  3.         delay_ms(10);
  4.         if (dir) {
  5.             ledrpwmval++;
  6.         } else {
  7.             ledrpwmval--;
  8.         }
  9.         if (ledrpwmval > 300)dir = 0;
  10.         if (ledrpwmval == 0)dir = 1;
  11.         GTIM_TIMX_PWM_CHY_CCRX = ledrpwmval;
  12.     }
复制代码
定时器初始化竣事以后就可以编写主步调了,在主步调内里先延时10ms,延时的意义是防止闪灼频率过快,肉眼观察不到,然后通过变量dir来调解占空比是增长还是淘汰,对应灯亮度的增长和淘汰,通过变量ledrpwmval来调解具体占空比的值,计数值300对应占空比300/500=60%,这时间对占空比的厘革方向取反,也就是说占空比从0厘革到60%以后紧接着从60%再厘革到0。
可以通过把300改成499来调治灯的最大亮度,同时把第5行到第8行改成下面如许,让灯的呼吸灯效果更加显着。
  1.         if (dir) {
  2.             ledrpwmval += 5;
  3.         } else {
  4.             ledrpwmval -= 5;
  5.         }
复制代码
1.5. 输入捕捉实行

输入捕捉实行是对一个管脚举行高电平连续时间举行盘算
1.5.1. 原理图阅读


这个实行用到的是开关KEY_UP这一起,开关未打开时,PA0收罗到低电平,开关打开时,PA0收罗到连续的高电平,然后将这个高电平的连续时间收罗后通过串口发出来。

PA0可以映射的定时器通道是TIM5_CH1,而TIM2_CH1_ETR和TIM8_ETR是外部时钟模式2的时钟输入信号,不要搞混。
1.5.2. 定时器的初始化

  1. void gtim_timx_cap_chy_init(uint16_t arr, uint16_t psc)
  2. {
  3.     uint8_t chy = GTIM_TIMX_CAP_CHY;
  4.     GTIM_TIMX_CAP_CHY_GPIO_CLK_ENABLE();   /* TIMX 通道IO口时钟使能 */
  5.     GTIM_TIMX_CAP_CHY_CLK_ENABLE();        /* TIMX 时钟使能 */
  6.     sys_gpio_set(GTIM_TIMX_CAP_CHY_GPIO_PORT, GTIM_TIMX_CAP_CHY_GPIO_PIN,
  7.                  SYS_GPIO_MODE_AF, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PU);    /* TIMX PWM CHY 复用功能 下拉 */
  8.     GTIM_TIMX_CAP->ARR = arr;       /* 设定计数器自动重装值 */
  9.     GTIM_TIMX_CAP->PSC = psc;       /* 设置预分频器  */
  10.     if (chy <= 2)
  11.     {
  12.         GTIM_TIMX_CAP->CCMR1 |= 1 << 8 * (chy - 1);        /* CCyS[1:0]   = 01 选择输入端 IC1/2映射到TI1/2上 */
  13.         GTIM_TIMX_CAP->CCMR1 |= 0 << (2 + 8 * (chy - 1));  /* ICyPSC[1:0] = 00 输入捕获不分频,全捕获 */
  14.         GTIM_TIMX_CAP->CCMR1 |= 0 << (4 + 8 * (chy - 1));  /* ICyF[3:0]   = 00 输入端滤波 不滤波 */
  15.     }
  16.     else if (chy <= 4)
  17.     {
  18.         GTIM_TIMX_CAP->CCMR2 |= 1 << 8 * (chy - 3);        /* CCyS[1:0]   = 01 选择输入端 IC3/4映射到TI3/4上 */
  19.         GTIM_TIMX_CAP->CCMR2 |= 0 << (2 + 8 * (chy - 3));  /* ICyPSC[1:0] = 00 输入捕获不分频,全捕获 */
  20.         GTIM_TIMX_CAP->CCMR2 |= 0 << (4 + 8 * (chy - 3));  /* ICyF[3:0]   = 00 输入端滤波 不滤波 */
  21.     }
  22.     GTIM_TIMX_CAP->CCER |= 1 << (4 * (chy - 1));       /* CCyE = 1 输入捕获使能 */
  23.     GTIM_TIMX_CAP->CCER |= 0 << (1 + 4 * (chy - 1));   /* CCyP = 0 捕获上升沿 ,注意:CCyNP使用默认值0 */
  24.     GTIM_TIMX_CAP->EGR  |= 1 << 0;  /* 软件控制产生更新事件,使写入PSC的值立即生效,否则将会要等到定时器溢出才会生效 */
  25.     GTIM_TIMX_CAP->DIER |= 1 << 1;  /* 允许捕获中断 */
  26.     GTIM_TIMX_CAP->DIER |= 1 << 0;  /* 允许更新中断 */
  27.     GTIM_TIMX_CAP->CR1  |= 1 << 0;  /* 使能定时器TIMX */
  28.     sys_nvic_init(1, 3, GTIM_TIMX_CAP_IRQn, 2);/* 抢占1,子优先级3,组2 */
  29. }
复制代码

1.5.3. 克制函数学习

  1. void GTIM_TIMX_CAP_IRQHandler(void)
  2. {
  3.     uint16_t tsr = GTIM_TIMX_CAP->SR;       /* 获取中断状态 */
  4.     uint8_t chy = GTIM_TIMX_CAP_CHY;        /* 需要捕获的通道 */
  5.     if ((g_timxchy_cap_sta & 0X80) == 0)    /* 还未成功捕获 */
  6.     {
  7.         if (tsr & (1 << 0)) /* 溢出中断 */
  8.         {
  9.             if (g_timxchy_cap_sta & 0X40)   /* 已经捕获到高电平了 */
  10.             {
  11.                 if ((g_timxchy_cap_sta & 0X3F) == 0X3F) /* 高电平太长了 */
  12.                 {
  13.                     GTIM_TIMX_CAP->CCER &= ~(1 << (1 + 4 * (chy - 1)));/* CCyP = 0 设置为上升沿捕获 */
  14.                     g_timxchy_cap_sta |= 0X80;  /* 标记成功捕获了一次 */
  15.                     g_timxchy_cap_val = 0XFFFF;
  16.                 }
  17.                 else    /* 还可以累加高电平长度 */
  18.                 {
  19.                     g_timxchy_cap_sta++;   
  20.                 }
  21.             }
  22.         }
  23.         if (tsr & (1 << chy))   /* 通道y 发生了捕获事件 */
  24.         {
  25.             if (g_timxchy_cap_sta & 0X40)   /* 捕获到一个下降沿 */
  26.             {
  27.                 g_timxchy_cap_sta |= 0X80;  /* 标记成功捕获到一次高电平脉宽 */
  28.                 g_timxchy_cap_val = GTIM_TIMX_CAP_CHY_CCRX; /* 获取当前的捕获值. */
  29.                 GTIM_TIMX_CAP->CCER &= ~(1 << (1 + 4 * (chy - 1)));/* CCyP = 0 设置为上升沿捕获 */
  30.             }
  31.             else    /* 还未开始,第一次捕获上升沿 */
  32.             {
  33.                 g_timxchy_cap_val = 0;
  34.                 g_timxchy_cap_sta = 0X40;   /* 标记捕获到了上升沿 */
  35.                 GTIM_TIMX_CAP->CNT = 0;     /* 计数器清空 */
  36.                 GTIM_TIMX_CAP->CCER |= 1 << (1 + 4 * (chy - 1));    /* CCyP = 1 设置为下降沿捕获 */
  37.             }
  38.         }
  39.     }
  40.     GTIM_TIMX_CAP->SR = 0;     /* 清除所有中断标志位 */
  41. }
复制代码
克制函数干的事变总结起来就是捕捉上升沿和降落沿,并记载时间,同时记载计数器溢出次数,末了盘算总的高电平连续时间。

1.6. 脉冲计数实行

克制脉冲实行的目标是使用外部信号作为计数器时钟,假计划数器工作在递增模式下,那么外部来一个脉冲则计数器加1。使用的IO口和脉宽捕捉一样,不外复用的功能差别,现在映射到外部时钟输入TIM2_CH1_ETR。
1.6.1 定时器初始化

  1. void gtim_timx_cnt_chy_init(uint16_t psc)
  2. {
  3.     uint8_t chy = GTIM_TIMX_CNT_CHY;
  4.     GTIM_TIMX_CNT_CHY_GPIO_CLK_ENABLE();   /* TIMX 通道IO口时钟使能 */
  5.     GTIM_TIMX_CNT_CHY_CLK_ENABLE();        /* TIMX 时钟使能 */
  6.     sys_gpio_set(GTIM_TIMX_CNT_CHY_GPIO_PORT, GTIM_TIMX_CNT_CHY_GPIO_PIN,
  7.                  SYS_GPIO_MODE_AF, SYS_GPIO_OTYPE_PP, SYS_GPIO_SPEED_HIGH, SYS_GPIO_PUPD_PD);    /* TIMX PWM CHY 复用功能 下拉 */
  8.     GTIM_TIMX_CNT->ARR = 65535; /* 设定计数器自动重装值为最大 */
  9.     GTIM_TIMX_CNT->PSC = psc;   /* 设置预分频器  */
  10.     GTIM_TIMX_CNT->CCMR1 |= 1 << 8 * (chy - 1);        /* CCyS[1:0]   = 01 选择输入端 IC1/2映射到TI1/2上 */
  11.     GTIM_TIMX_CNT->CCMR1 |= 0 << (2 + 8 * (chy - 1));  /* ICyPSC[1:0] = 00 输入捕获不分频,全捕获 */
  12.     GTIM_TIMX_CNT->CCMR1 |= 0 << (4 + 8 * (chy - 1));  /* ICyF[3:0]   = 00 输入端滤波 不滤波 */
  13.    
  14.     GTIM_TIMX_CNT->CCER |= 1 << (4 * (chy - 1));       /* CCyE = 1 输入捕获使能 */
  15.     GTIM_TIMX_CNT->CCER |= 0 << (1 + 4 * (chy - 1));   /* CCyP = 0 捕获上升沿,即上升沿计数 ,注意:CCyNP使用默认值0 */
  16.     GTIM_TIMX_CNT->SMCR |= (4 + chy) << 4;  /* TS[4:0] = 5/6  触发选择: 5,TI1FP1(TIMX_CH1);  6,TI2FP2(TIMX_CH2); */
  17.     GTIM_TIMX_CNT->SMCR |= 7 << 0;          /* SMS[2:0] = 7   从模式选择: 外部时钟模式1 */
  18.    
  19.     GTIM_TIMX_CNT->EGR  |= 1 << 0;  /* 软件控制产生更新事件,使写入PSC的值立即生效,否则将会要等到定时器溢出才会生效 */
  20.     GTIM_TIMX_CNT->DIER |= 1 << 0;  /* 允许更新中断 */
  21.     GTIM_TIMX_CNT->CR1  |= 1 << 0;  /* 使能定时器TIMX */
  22.     sys_nvic_init(1, 3, GTIM_TIMX_CNT_IRQn, 2);/* 抢占1,子优先级3,组2 */
  23. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com ToB IT社区-企服评测·应用市场 (https://www.qidao123.com/bbs/) Powered by Discuz! X3.5