使用STM32CubeMx实现定时器输入捕获测量PWM频率和占空比

首先选择外部晶振:

配置时钟频率:

选择使用的定时器:

根据内部原理图:

这里以TIM_CH1为例,当从CH1输入一个PWM波,通过输入滤波后将会产生两路信号:tim_ti1fp1 & tim_ti1fp2,分别送至tim_ic1 & tim_ic2,也就是说一个TI信号将会被映射成两路的IC信号,所以可以通过进行边沿检测来测量PWM的频率以及占空比。

具体步骤如下:

1、设置定时器Slave Mode为Reset Mode,也就是当检测到上升沿时,定时器复位;

2、PWM由CH1进入,触发源设置为TI1FP1,并设置IC1为上升沿捕获;

3、当第一次捕获到上升沿时,定时器复位,计数寄存器CNT清零;

4、当IC2捕获到下降沿时,计数器CNT的值将会被存到捕获寄存器CCR2中;

5、当IC1再次捕获到上升沿时,计数器CNT的值将会被存到捕获寄存器CCR1中,同时将定时器复位;

因此,CCR1的值就是周期,CCR2的值就是占空比。

配置如下:

通道1设置为直接模式,通道2设置为间接模式。

 最终计算得到的频率值 = 分频后得到的时钟频率 / 上升沿个数 

                                          = ( 定时器时钟频率 / 预分频系数 )/ 上升沿个数 

最终计算的到的占空比 = 下降沿个数 / 上升沿个数;

值得注意的是:要明确输入PWM波的大致范围,因为需要根据PWM波范围来确定预分频系数;比如说输入一个频率大概为50Hz,占空比为10%的PWM波,需要将预分频系数稍微设置大一些;(这是因为:定时器所能测量到的最小频率 = 定时器频率 / ( 预分频系数 * 自动重载值 ),而因为ARR(Auto-Reload-Register)是一个十六位寄存器,其最大值为65536,所以当需要测量的频率值较小时,必须要将预分频系数设为较大值)

以本次使用定时器TIM3为例,其时钟频率已配置为84MHz,再配置PSC(Prescaler)为(8400-1),因此,最终频率 = ( 84000000 / 8400 )/  PWM_RisingCount;

参数配置:

再打开定时器中断:

 配置NVIC(Nested Vector Interrupt Controller):

 代码:

1、全局变量以及主函数

/* USER CODE BEGIN 0 */
uint16_t PWM_RisingCount;
uint16_t PWM_FallingCount;
float duty;
/* USER CODE END 0 */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_1);
	HAL_TIM_IC_Start_IT(&htim3,TIM_CHANNEL_2);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      //每1秒输出一次
	  HAL_Delay(1000);
      //这里的10000就是由定时器频率84000000/预分频系数8400 得到
	  printf("PWM_Frequency = %d \r\n",(uint16_t)10000/PWM_RisingCount);
	  printf("PWM_Duty = %.2f %% \r\n",duty * 100);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 2、输入捕获中断回调函数

/* USER CODE BEGIN 4 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)    
    //注意这里为HAL_TIM_ACTIVE_CHANNEL_1而不是TIM_CHANNEL_1
	{
		PWM_RisingCount = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
		duty = (float)PWM_FallingCount / PWM_RisingCount;
	}
	if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
	{
		PWM_FallingCount = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_2);
	}
}
/* USER CODE END 4 */

最终结果如下:

(输入为另一块STM32产生的PWM波,频率为50Hz,占空比为5%,可以看到有些许误差,这是因为没有进行滤波的缘故)

物联沃分享整理
物联沃-IOTWORD物联网 » 使用STM32CubeMx实现定时器输入捕获测量PWM频率和占空比

发表评论