HAL库STM32常用外设教程(六)——定时器 输入捕获

07-17 1502阅读

文章目录

  • 前言
  • 一、输入捕获原理及相关驱动
    • 1.1 输入捕获原理
    • 1.2 输入捕获相关的HAL驱动
    • 二、 输入捕获检测方波占空比
      • 2.1 原理
      • 2.2 STM32CubeMx设置
      • 2.3 程序设计
      • 2.4 示例结果
      • 三、 输入捕获检测PWM频率和占空比
        • 3.1 原理
        • 3.2 STM32CubeMx设置
        • 3.3 程序设计
        • 3.3 示例结果
        • 四、用定时器ETR方式计算PWM脉冲数
          • 4.1 ETR计算脉冲数原理
          • 4.2 STM32CubeMx设置
          • 4.3 程序设计
          • 4.4 示例结果
          • 4.5 问题反思
          • 五、总结

            前言

            1、STM32F407ZGT6

            2、STM32CubeMx软件

            3、keil5

            内容简述:

            通篇文章将涉及以下内容,如有错误,欢迎指出:

            定时器有关输入捕获的HAL库驱动程序

            (1)CubeMx配置

            (2)TIM驱动程序

            (3)输入捕获检测方波占空比

            (4) 输入捕获检测PWM频率和占空比

            (5)用定时器ETR方式计算PWM脉冲数


            • 有关于定时器 输出PWM功能不了解的可以看这篇文章 :HAL库STM32常用外设教程(一)—— 定时器 输出PWM
            • 有关于定时器 定时功能+基础定时器特性不了解的可以看这篇文章 :HAL库STM32常用外设教程(四)—— 定时器 基本定时
            • 有关于定时器输出比较+通用定时器特性不了解的可以看这篇文章 :HAL库STM32常用外设教程(五)—— 定时器 输出比较

              一、输入捕获原理及相关驱动

              1.1 输入捕获原理

                输入捕获(intput capture)就是检测输入通道输入方波信号的跳变沿,并将发生跳变沿时的计数器的值锁存到CCR。使用输入捕获功能可以检测方波信号周期,从而计算方波信号的频率,也可以检测方波的占空比。其基本原理可以看成下面的几个步骤:

              1、输入捕获通道配置:首先,需要选择一个特定的计时器作为输入捕获的计时源,并将其中的一个或多个通道配置为输入捕获模式。

              2、捕获触发条件设置:根据需要,在输入捕获通道上设置触发条件,例如上升沿、下降沿或两者都有的边缘触发。

              3、 外部信号检测:当外部信号满足触发条件(如上升沿)时,输入捕获通道会记录当前计时器的计数值并生成相应的中断或标志。

              4、 捕获值获取:在中断服务程序或适当的时间点,可以读取输入捕获通道的捕获寄存器,获取记录的捕获值。

              5、计算参数:通过对捕获值进行处理和计算,可以得到所需的参数,如脉冲宽度、频率、周期等。

              下面将通过用输入捕获功能计算按键按下时高电平的占空比、输入捕获计算PWM的周期和频率两个例子讲解定时器输入捕获的用法。

              1.2 输入捕获相关的HAL驱动

                输入捕获相关的HAL函数如表2.1 所示。这里仅列出了相关函数名,简要说明其功能相关函数在stm32f4xx_hal_tim.h中。

                               表2.1输入捕获相关HAL库函数

              函数名功能描述
              HAL_TIM_IC_Init()输入捕获初始化,需先执行HAL_TIM_Base_Init()进行定时器初始化
              HAL_TIM_IC_ConfigChannel()输入通道配置
              HAL_TIM_IC_Start()启动输入捕获,需要先执行HAL_TIM_Base_start()启动定时器
              HAL_TIM_IC_Stop()停止输入捕获
              HAL_TIM_IC_Start_IT()以中断方式启动输入捕获,需要先执行HAL_TIM_Base_start_IT()启动定时器
              HAL_TIM_IC_Stop_IT()停止输入捕获
              HAL_TIM_IC_GetState()返回定时器状态,与HAL_TIM_Base_GetState()功能相同
              __HAL_TIM_SET_CAPTUREPOLARITY()设置捕获输入极性,上跳沿、下降沿或双边捕获
              __HAL_TIM_SET_COMPARE()设置比较寄存器CCR的值
              __HAL_TIM_GET_COMPARE()读取比较寄存器CCR的值
              HAL_TIM_IC_CaptureCallback()产生捕获事件时的回调函数

              二、 输入捕获检测方波占空比

              2.1 原理

                如图2.1所示,如果两个上跳沿的捕获发生在同一个计数周期内,两个计数值分别为CCR1和CCR2,则方波的周期为CCR2-CCR1个计数周期,根据定时器的周期就可以计算出方波周期和频率。如果方波周期超过定时器的计数周期,或两次输入捕获发生在相邻的两个定时周期内,如图2.2中CCR2和CCR3,则只需将计数器的计数周期和UEV事件发生次数考虑进去即可,根据CCR2和CCR3计算的脉冲周期应该是 ARR - CCR1 + CCR2。

                输入捕获还可以对输入设置滤波,滤波系数0 ~ 15,用于输入抖动时的处理。输入捕获还可以设置与分频系数 N,数值N的取值为1、2、4或8,表示发生了N个时间才执行一次的捕获

              HAL库STM32常用外设教程(六)——定时器 输入捕获

                                 图2.1 捕获PWM高电平示意图(1)HAL库STM32常用外设教程(六)——定时器 输入捕获

                                 图2.2 捕获PWM高电平示意图(2)

                本次示例通过按键去提供一次高电平,测试按键按下时的高电平时间,所以需要将TIM输入捕获的引脚接到按键的引脚上,可以在CubeMx里面将按键引脚配置成定时器输入捕获模式(如图2.3)

              通过观察开发板原理图,如图2.3 到 图2.5所示,可以发现KEY_UP按键的引脚可以实现配成TIM2_CH1的输入捕获通道。

              HAL库STM32常用外设教程(六)——定时器 输入捕获

                                 图2.3 CubeMx里按键引脚配置

              HAL库STM32常用外设教程(六)——定时器 输入捕获

                                 图2.4 按键原理图(1)

              HAL库STM32常用外设教程(六)——定时器 输入捕获                   图2.5 按键原理图(2)

              2.2 STM32CubeMx设置

              1、TIM配置

                如图所示,按照图2.6 中的步骤将TIM2的通道1配置输入捕获模式,还需要使能TIM2中断(在中断里面计数高电平脉冲)。

              HAL库STM32常用外设教程(六)——定时器 输入捕获                     图2.6 CubeMx里TIIM2输入捕获设置

              HAL库STM32常用外设教程(六)——定时器 输入捕获

                                   图2.7 使能TIM2中断(1)

              HAL库STM32常用外设教程(六)——定时器 输入捕获

                                   图2.8 使能TIM2中断(2)

                因为需要通过串口将高电平时间计算出来,所以实验也需要配置好串口,本次用到的是串口1

              HAL库STM32常用外设教程(六)——定时器 输入捕获

                                   图2.9 使能TIM2中断(2)

              配置完成后生成工程。

              2.3 程序设计

                STM32CubeMx配置结束后,生成工程。先进行初步分析STM32CubeMx生成的工程,以便更好的理解STM32CubeMx里面的配置。

              HAL库STM32常用外设教程(六)——定时器 输入捕获

                                   图2.10 Counter Settings

              如图所示,逐行解释上图片中标记的代码

              • htim2.Instance = TIM2;

                  将定时器设置为TIM2。

              • htim2.Init.Prescaler = 84-1;

                   设置预分频器的值为83(实际值减去1)。预分频器用于将输入时钟频率分频,从而得到更低的计数频率。在这里,输入时钟频率将被除以84,获得的计数频率为84Mhz /(84-1 +1) = 1MHz。

              • htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

                   将计数模式设置为向上计数模式。在向上计数模式下,计数器从0递增到自动重载值。

              • htim2.Init.Period = 0xFFFFFFFF;

                  设置自动重载寄存器的值为0xFFFFFFFF(32位最大值)。这意味着计数器将从0递增到0xFFFFFFFF,然后重新从0开始循环。

              • htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

                  设置时钟分频系数为不分频(TIM_CLOCKDIVISION_DIV1)。时钟分频用于进一步分频计数器的时钟频率。

              • htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;

                   启用自动重载预装载功能。当该功能启用时,新的自动重载值在下一个更新事件时生效,以避免在计数器工作时意外更改自动重载值。

                HAL库STM32常用外设教程(六)——定时器 输入捕获

                                     图2.10 Counter Settings设置

                • sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

                     这段代码的作用是将定时器的时钟源设置为内部时钟。sClockSourceConfig是一个结构体,其中的ClockSource成员用于配置定时器的时钟源。通过将ClockSource成员设置为TIM_CLOCKSOURCE_INTERNAL,代码指定定时器使用内部时钟作为计数时钟源。

                  HAL库STM32常用外设教程(六)——定时器 输入捕获

                                 图2.11 TRGO Parameters和Input Capture Channel设置

                  • sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

                       配置定时器的主输出触发源为 TIM_TRGO_RESET,表示在每次定时器重置(复位)时触发主输出触发事件。具体说,当定时器的计数值达到最大值并发生溢出时,定时器将自动复位到初始值。此时,如果配置了主输出触发源为 TIM_TRGO_RESET,就会产生一个触发事件,可以用来同步其他外设或执行相关的操作

                  • sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

                       禁用主从模式,即该定时器不会作为其他定时器的主定时器。

                  • sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

                      设置输入捕获通道的触发极性为上升沿触发。

                  • sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

                      配置输入捕获通道的输入源选择为直接触发模式。捕获选择器设置为 TIM_ICSELECTION_DIRECTTI 时,定时器会直接读取输入端的电平变化,并进行相应的计数和捕获操作。这通常适用于需要测量输入信号的上升沿和下降沿的情况。

                      当将输入捕获选择器设置为 TIM_ICSELECTION_INDIRECTTI 时,定时器会先通过一个互补触发器(Complementary Trigger)来产生一个间接触发信号。然后,根据该触发信号的边沿变化来触发输入捕获操作。这种设置通常适用于需要测量输入信号的互补边沿(例如正边沿和负边沿)或需要使用输入信号的互补版本进行计数的情况。

                  • sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;

                      设置输入捕获通道的输入分频器预分频系数为1,TIM_ICPSC_DIV1指定输入信号的频率不进行预分频,直接用于输入捕获。

                  • sConfigIC.ICFilter = 0;

                      将输入捕获通道的滤波器配置为无滤波器。ICFilter参数表示滤波器的设置值,0表示禁用滤波器,即不对输入信号应用任何滤波。通过将ICFilter设置为0,可以确保输入捕获模式下的输入信号不受滤波器的影响,即直接获取输入信号的原始状态。这适用于需要实时响应输入信号变化或对输入信号精确测量的情况。

                      了解了上面的 tim.c 里面的基础配置后,开始在生成的工程上编写用户代码 实现输入捕获功能。

                    (1)首先,需要对实现“串口重定向”,printf可以将指定字符打印到电脑的显示器上,但是要想使用printf在单片机中通过串口打印出来,就需要重定向到串口配置上。

                    注:如果用到的是串口2,将“串口重定向中的”USART1换成USART2即可。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                    /* 串口重定向 */
                    int fputc(int ch,FILE *f)
                    {
                    	while(!(USART1->SR &(1
                    		idle	= 0,  /* 空闲 */
                    		runing, 	  /* 运行*/
                    		end			  /* 结束*/
                    }IC_STATE;
                    IC_STATE ic_state;	  /* 定义结构体变量 */
                    
                    	if(htim == &htim2){								    /* 判断是否为定时器TIM2 */
                    		 if(ic_state == runing){					    /* 判断是否为是 正在运行状态 */
                    				tim_over ++;					        /* 定时器溢出值计数 */
                    		 }
                    	}
                    }
                    	
                    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
                    {
                    	if(htim == &htim2){							         /* 判断是否为定时器TIM2 */
                    		 if(ic_state == idle){							 /* 判断状态是不是 空闲 */
                    				ic_state = runing;						 /* 将状态设置为 正在运行 */
                    				tim_value = 0;							 /* 计数值清零 */
                    				__HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING); /* 将TIM2的通道1捕获极性设置为下降沿捕获 */
                    			 __HAL_TIM_SET_COUNTER(&htim2,0);		     /* 将TIM2的计数值设置为0 */
                    		 }else{								             /* 此时不是空闲状态 */
                    				HAL_TIM_IC_Stop_IT(&htim2,TIM_CHANNEL_1);/* 停止定时器2输入捕获功能 */
                    				ic_state = end;						     /* 将状态设置为 结束 */
                    			  tim_value = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1);	 /* 获取此时计数值 */
                    		 	 __HAL_TIM_SET_CAPTUREPOLARITY(&htim2, TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING);/* 将TIM2的通道1捕获极性设置为上升沿捕获 */
                    		 }
                    	}
                    }
                    																											 /* 判断是否结束 */
                    			duty_cycle=(float)(Period_cnt1 * 65536 + ccr1_cnt + 1) * 100 /(Period_cnt2 * 65536 + ccr2_cnt + 1);  /* 计算占空比 */
                      		frequency=1000000 / (float)(Period_cnt2 * 65536 + ccr2_cnt + 1); /* 计算频率 */
                    			printf("\r\n 频率 = %.2f Hz,占空比 = %.2f %%",frequency,duty_cycle);
                    			end_flag = 0;																										 /* 将捕获结束标志置0(准备下一次捕获) */
                    		}
                        /* 定时器计数溢出回调函数 */
                    		Period_cnt ++;								            /* 定时器计数溢出时间次数 */
                    }
                    void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){	    /* 定时器输入捕获回调函数 */
                    		if(htim-Channel == HAL_TIM_ACTIVE_CHANNEL_1){		    /* 判断是不是定时器TIM1 */
                    			if(end_flag == 0){							        /* 判断结束标志是不是0,在打印期间不进行捕获,防止打印时相关数值改变 */
                    				switch(ic_flag){							    /* 判断此时处于捕获的第几个阶段 */
                    					case 0:									    /* 阶段一:第一次捕获到上升沿 */
                    					{
                    						__HAL_TIM_SET_COUNTER(&htim3,0);	    /* 将定时器3计数设置为0 */
                    						ccr1_cnt = 0;							/* 将相关参数清0 */
                    						ccr2_cnt =0;
                    						Period_cnt = 0;
                    						Period_cnt1 = 0;
                    						Period_cnt2 = 0;
                    						__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_FALLING);/* 设置成下降沿捕获 */
                    						ic_flag = 1;							/* 捕获设置为等待第二个阶段 */
                    						break;
                    					}
                    						case 1:									/* 阶段二:第一次捕获到下降沿 */
                    					{
                    						ccr1_cnt = __HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1);/* 获取存放在CCR寄存器的值(捕获值CCR1) */
                    						Period_cnt1 = 	Period_cnt;				/* 获取计时器溢出次数1 */
                    						__HAL_TIM_SET_CAPTUREPOLARITY(&htim3,TIM_CHANNEL_1,TIM_INPUTCHANNELPOLARITY_RISING); /* 设置成上升沿捕获 */
                    						ic_flag = 2;							/* 捕获设置等待为第三个阶段 */
                    						break;
                    					}
                    					case 2:										/* 阶段三:第二次捕获到上升沿 */
                    					{
                    						ccr2_cnt = __HAL_TIM_GET_COMPARE(&htim3,TIM_CHANNEL_1);/* 取存放在CCR寄存器的值(捕获值CCR2) */
                    						Period_cnt2 = Period_cnt;				/* 获取计时器溢出次数2 */
                    						ic_flag = 0;							/* 捕获设置等待为第一个阶段 */
                    						end_flag = 1;							/* 完成一次捕获,将标志置1 */
                    						break;
                    					}			
                    				}
                    			}
                    		}
                    }
                    

                    3.3 示例结果

                      接上串口后观察打印结果,如图3.7和图3.8 所示,其显示的PWM频率域PWM占空比和图2.13中示波器测出来的相同。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                     图3.6 接线

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                       图3.7 串口结果显示

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                       图3.8 示波器显示

                    四、用定时器ETR方式计算PWM脉冲数

                    4.1 ETR计算脉冲数原理

                       通过示例2能够计算PWM的占空比和频率,如果单纯的计算PWM数,就不得不提到定时器的另一个模式:ETR(External Trigger)模式。在这种模式下,定时器的计数器会在PWM信号发生时启动计数。计数器会开始累积时钟脉冲的数量,这个数量与PWM信号的脉冲数成正比。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.1 定时器ETR模式框图

                    4.2 STM32CubeMx设置

                    (1)因为此处需要产生一个PWM,此处用TIM2产生一个频率为1K的PWM方波,如何产生PWM请参考这篇文章:HAL库STM32常用外设教程(一)—— 定时器 输出PWM ,TIM2的配置如图4.2所示。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.2 定时器TIM2 STM32CubeMx配置

                    (2)TIM3设置成ETR模式,如图4.3所示。然后使能TIM3中断,如图4.4所示

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.3 定时器TIM3 STM32CubeMx配置

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.4 使能定时器TIM3 中断

                    (2)通过TIM6设置成1s的计时,如图4.6所示,之所以设置成1s进行计时是因为PWM频率的定义为:

                      在单位时间内,PWM信号中的脉冲从起始到结束再到下一个脉冲的周期性重复次数。PWM频率通常以赫兹(Hz)为单位。

                      通俗来讲,1s内产生 x 个脉冲,其频率就为 x 赫兹。

                    但是有一点需要注意,ETR模式是用来测量脉冲个数的,本次示例通过定时1s去测量ETR的数值(脉冲的个数)来计算脉冲的频率,此方法是不严谨的,因为脉冲的频率可能是不断变化的,举例来说:

                      在图4.5中,一定时间内ETR测到的PWM1和PWM2的脉冲个数都是3个,如果按照本次示例中的测量方法得出的结论是PWM1和PWM2的频率是一样的(一定时间内脉冲个数是一样的),所以这种方式只能计算频率不变的脉冲频率。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.5 两种PWM

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.6 定时器TIM6 STM32CubeMx配置

                      然后使能定时器6中断,如图4.7所示。需要在TIM6的溢出中断里面进行计数,在“NVIC”里再次检测中断TIM3和TIM6的中断是否开启。如图4.8所示。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.7 使能定时器TIM6 中断

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                         图4.8 STM32Cube"NVIC"设置

                    4.3 程序设计

                    (1)参考 2.3节 先进行 串口重定向,完成后再进行下面相关变量的定义。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                    uint32_t count_over = 0; 	/* 定时器计数溢出次数 */
                    uint32_t count_cnt = 0;		/* 定时器计数值 */
                    uint32_t count = 0;				/* 1s 内脉冲总数 */
                    uint8_t printf_flag = 0;
                    

                    (2)启动TIM2定时器的PWM输出,以中断方式启动TIM3定时器和TIM6定时器。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                    	HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);  /* 启动定时器TIM2的PWM输出 */
                    	HAL_TIM_Base_Start_IT(&htim3);						/* 以中断方式启动定时器TIM3 */
                    	HAL_TIM_Base_Start_IT(&htim6);						/* 以中断方式启动定时器TIM6 */
                    

                    (3)在定时器TIM3的中断服务例程里面进行溢出计数,在定时器6的中断服务例程里面通过函数 __HAL_TIM_GET_COUNTER()进行读出此时的CNT值,将打印标志置1,此时主循环检测到该标志置1后就可以进行打印,并将溢出值清0,定时器3的计数值清零,为下一秒计算脉冲频率做准备。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                    void TIM3_IRQHandler(void)
                    {
                      /* USER CODE BEGIN TIM3_IRQn 0 */
                      /* USER CODE END TIM3_IRQn 0 */
                      HAL_TIM_IRQHandler(&htim3);
                        /* USER CODE BEGIN TIM3_IRQn 1 */
                    	count_over ++; 
                      /* USER CODE END TIM3_IRQn 1 */
                    }
                    
                    void TIM6_DAC_IRQHandler(void)
                    {
                      /* USER CODE BEGIN TIM6_DAC_IRQn 0 */
                    	
                    	count_cnt =  __HAL_TIM_GET_COUNTER(&htim3);   /* 获取此时的CNT值 */
                    	printf_flag = 1;							  /* 将打印标志置1 */
                    	count_over = 0;								  /* 溢出计数清0 */
                    	__HAL_TIM_SET_COUNTER(&htim3,0);			/* 将定时器3的计数值清0 */
                    	
                      /* USER CODE END TIM6_DAC_IRQn 0 */
                      HAL_TIM_IRQHandler(&htim6);
                      /* USER CODE BEGIN TIM6_DAC_IRQn 1 */
                      /* USER CODE END TIM6_DAC_IRQn 1 */
                    }
                    

                    (4)在主循环里面通过判断 printf_flag标志将PWM频率打印出来,之所以放到主循环里面,是因为中断里面遵循“快进快出”的原则,在中断里面打印会占用过多的时间。

                    count = count_over * 65535 + count_cnt;

                      上述公式是计算的PWM的脉冲数,因为本次示例中自动重装载值(ARR)的数值设置的是65535,所以每溢出一次计数65535个,也是公式中count_over * 65535的由来。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                    		if(printf_flag){								    /* 判断中断标志是否被置1 */
                    			 count = count_over * 65535 + count_cnt;		/* 计算1s内产生的脉冲数,即脉冲频率 */
                    			 printf("频率为 %d Hz \n\r",count);
                    			 printf_flag = 0;								/* 将中断标志清0,为下一次打印做准备 */
                    		}	
                    

                    4.4 示例结果

                      通过杜邦线将PA0引脚和PD2引脚相连,就可以在串口工具里面看到输出的频率,本次示例为验证输出的是否正确,在PA0引脚上又接了一个示波器,观察输出的波形,从图4.10和4.11可以看出,产生PWM的频率是1KHz,捕获到的频率也是1KHz。

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                        图4.9 接线

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                        图4.10 串口输出频率

                    HAL库STM32常用外设教程(六)——定时器 输入捕获

                                        图4.11 示波器显示

                    4.5 问题反思

                    (1)在做该实验时,搞错了一个函数,将 __HAL_TIM_GET_COUNTER()

                    函数错用成了 __HAL_TIM_GET_COMPARE()函数,下面补充一下这两个函数的作用

                    __HAL_TIM_GET_COUNTER()函数

                    • 作用:用于获取定时器的当前计数器值。
                    • 示例:
                      uint32_t counterValue = __HAL_TIM_GET_COUNTER(&htim);
                      
                      • 这个宏返回当前定时器的计数器寄存器(CNT)的值。在定时器工作时,计数器值不断增加,通过这个宏可以读取当前的计数值,用于查看定时器整体的计数状态。

                        __HAL_TIM_GET_COUNTER()函数

                        • 作用:用于获取定时器的比较寄存器值。。
                        • 示例:
                          uint32_t compareValue = __HAL_TIM_GET_COMPARE(&htim, TIM_CHANNEL_1);
                          
                          • 这个宏返回指定通道(channel)的比较寄存器(Capture/Compare Register,通常缩写为CCR的值。比较寄存器通常用于与计数器值进行比较,从而确定何时触发中断或改变输出状态,用于查看与特定通道相关联的比较状态。这通常与定时器的PWM生成、捕获比较等操作有关。

                            (2)在进行 “ printf ” 打印时,第一次‘’将其放在了TIM6定时器的中断服务例程里面,结果发现打印出来的频率都是996Hz,然后考虑到了中断里面“快进快出”原则 ,通过置标志的方式将打印内容放在了while循环里面,打印出的结果是1000Hz。在单片机中,这一原则有助于确保中断服务程序的及时响应和高效执行,该原则一般包括两个方面:

                            ① 尽量减小中断服务程序的执行时间:

                            • 中断服务程序(ISR - Interrupt Service Routine)应该尽量简洁而高效。在中断服务程序中,应避免长时间的计算、复杂的数据处理等操作。
                            • 长时间执行的中断服务程序会导致其他中断被阻塞,这可能影响系统的实时性和响应性。
                            • 应该专注于在中断服务程序中完成必要的最小工作量,将复杂和耗时的任务移到主循环中或其他地方处理。

                              ②尽量减小中断响应时间:

                              • 中断响应时间是指从中断发生到中断服务程序开始执行的时间。较短的中断响应时间有助于提高系统的实时性。
                              • 在设计中,可以通过适当配置中断控制器、合理选择中断优先级、以及优化硬件和软件的交互,来缩短中断响应时间。
                              • 另外,及时清除中断标志位也是减小中断响应时间的一部分,确保中断服务程序能够迅速响应新的中断。

                                五、总结

                                  上述主要讲述了定时器输入捕获的原理及其三个应用示例,包括每个示例的HAL库配置、程序编写以及测试结果。在学习输入捕获时,应该多去琢磨其捕获的原理,可以通过画图去研究其过程,例如图3.1和图3.2,明白该在哪一个跳变沿进行捕获等。


                                参考书籍和文章:

                                1、《STM32Cube高效开发教程(基础篇)》王维波

                                2、《STM32F4xx中文参考手册》

                                3、《STM32F407 探索者开发指南》

                                4、【STM32】标准库与HAL库对照学习教程十–输入捕获实验

                                5、[018] [STM32] 定时器 基本定时/输出比较/输入捕获功能详解与HAL库编程

                                6、STM32频率测量

                                7、第五节:STM32输入捕获(用CubeMx学习STM32)

                                8、cube配置定时器ETR2模式测频实验

                                9、STM32的ETR引脚计数功能

                                10、基于STM32定时器ETR信号的应用示例


                                  生活总是这样,不能叫人处处都满意。但我们还要热情的活下去。人活一生,值得爱的东西很多,不要因为一个不满意,就灰心。

                                                    ——《人生》

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]