概述

STM32的输出比较功能通常是指在微控制器的PWM(脉冲宽度调制)生成能力中的一个方面。STM32微控制器拥有一个或多个定时器/计数器,这些定时器/计数器可以用来生成PWM信号。PWM信号是一种重要的控制信号,广泛应用于电机控制、亮度调节、功率控制等领域。

在STM32中,输出比较功能指的是定时器/计数器的比较寄存器(如TIMx_CCRx)与定时器的计数寄存器(如TIMx_CNT)的值进行比较的过程。当计数器的值达到比较寄存器的值时,PWM模块会根据输出比较模式改变输出引脚的电平状态。

STM32的输出比较模式通常有以下几种:

  1. 翻转(Toggle)模式:当计数器的值达到比较寄存器的值时,输出引脚的电平状态会翻转。

  2. 置位(Set)模式:当计数器的值达到比较寄存器的值时,输出引脚被设置为高电平。

  3. 复位(Reset)模式:当计数器的值达到比较寄存器的值时,输出引脚被设置为低电平。

  4. PWM模式1和PWM模式2:这两种模式用于生成标准的PWM信号。在PWM模式1下,当计数器值小于比较寄存器值时,输出为有效电平(通常是高电平),反之则为无效电平(低电平)。PWM模式2与PWM模式1相反,计数器值小于比较寄存器值时输出为无效电平。

 区别

 

区别

  • 输出波形:比较输出模式通常产生非周期性的脉冲或者控制信号,而PWM模式产生周期性的信号。
  • 用途:比较输出更多地用于事件定时和单脉冲生成,而PWM则用于模拟信号的数字控制。
  • 占空比控制:PWM模式允许通过改变CCR的值来精确控制输出信号的占空比,而比较输出模式通常不涉及占空比的控制。
  •  PWM指在一个周期中改变占空比,输出比较是在定时器到一个值时产生一个事件或电平反转

    如在1kHz中PWM不是低电平就是高电平(在的是反转时间)

    而输出比较则是值到了为低或高(看的是值)

    STM32Cude的配置讲解

    输出比较

    1. Mode(模式):

    2. Frozen(冻结)

    3. 在这种模式下,比较寄存器的值不会影响输出电平,输出保持不变。
    4. 这对于需要固定电平输出而不受定时器计数影响的场景非常有用。(可以接收一个中断但不会引脚状态)
    5. Active Level on match(匹配时激活电平)

    6. 当定时器的计数器值与比较寄存器值匹配时,输出电平将被设置为激活电平(通常是高电平)。
    7. 一旦匹配发生,输出将保持激活电平,直到定时器计数器重新开始计数。
    8. Inactive Level on match(匹配时非激活电平)

    9. 当定时器的计数器值与比较寄存器值匹配时,输出电平将被设置为非激活电平(通常是低电平)。
    10. 类似于"Active Level on match",一旦匹配发生,输出将保持非激活电平,直到定时器计数器重新开始计数。
    11. Toggle on match(匹配时翻转)

    12. 每当定时器的计数器值与比较寄存器值匹配时,输出电平会在高电平和低电平之间翻转。
    13. 这种模式适用于需要生成方波或脉冲信号的场景。
    14. Forced Active(强制激活)

    15. 在这种模式下,输出电平被强制设置为激活电平,不论定时器的计数器值和比较寄存器值是否匹配。
    16. 这适用于需要输出始终保持激活电平的场景。
    17. Forced Inactive(强制非激活)

    18. 与" Forced Active"相反,输出电平被强制设置为非激活电平,不论定时器的计数器值和比较寄存器值是否匹配。
    19. 这适用于需要输出始终保持非激活电平的场景。
    20. Pulse (16 bits value)(脉冲(16位值))

    21. 这个选项设置定时器在PWM模式下的脉冲宽度,也就是占空比。
    22. 它是一个16位的值,代表定时器计数器的一个计数周期内,输出为高电平的时间长度。
    23. 例如,如果你的定时器时钟频率是1 MHz(即时钟周期为1微秒),并且你想要一个50%的占空比,那么你需要将Pulse值设置为定时器计数周期的一半。如果你的定时器是16位的,并且你设置的自动重装载值(TIMx_ARR)是65535(即计数器从0计数到65535),那么Pulse值应该是32768(65535的一半)。
    24. Output compare preload(输出比较预加载)

    25. 这个选项决定是否在下一个定时器周期开始时预加载比较寄存器的值。(。当输出比较预加载功能被使能时,你在任何时候写入TIMx_CCRx的值都不会立即影响当前的PWM周期,而是会等到下一个PWM周期开始时才生效。这样,PWM波形的改变就会更加平滑,不会在中间突然跳变。)
    26. 如果启用(Enable),则在当前周期结束前,比较寄存器的值会被更新,但不会影响当前周期。
    27. 如果禁用(Disable),则比较寄存器的值立即生效。
    28. CH Polarity(通道极性)

    29. 这个选项设置输出比较信号的极性。
    30. "High"表示在比较匹配时,输出被置为高电平。
    31. "Low"表示在比较匹配时,输出被置为低电平。

     HAL输出比较实验

    实验效果

    每次点亮的时间会增加

    1定时器配置

    将在程序中改变Pulse(16 bits values)的值

    打开中断

    代码设置

    HAL有哪些函数

    HAL_TIM_OC_Start() - 启动定时器的输出比较。
    HAL_TIM_OC_Stop() - 停止定时器的输出比较。
    HAL_TIM_OC_Start_IT() - 启动定时器的输出比较并使能中断。
    HAL_TIM_OC_Stop_IT() - 停止定时器的输出比较并禁用中断。
    HAL_TIM_OC_IRQHandler() - 定时器输出比较中断处理函数。
    HAL_TIM_OC_GetState() - 获取定时器输出比较的状态。
    __HAL_TIM_SET_COMPARE(htim, TIM_CHANNEL_x, compareValue);改变其比较值
    1为定时器2为通道3为比较的值(0-重装的值)

    main源码

    /* USER CODE BEGIN Header */
    /**
      ******************************************************************************
      * @file           : main.c
      * @brief          : Main program body
      ******************************************************************************
      * @attention
      *
      * Copyright (c) 2024 STMicroelectronics.
      * All rights reserved.
      *
      * This software is licensed under terms that can be found in the LICENSE file
      * in the root directory of this software component.
      * If no LICENSE file comes with this software, it is provided AS-IS.
      *
      ******************************************************************************
      */
    /* USER CODE END Header */
    /* Includes ------------------------------------------------------------------*/
    #include "main.h"
    #include "tim.h"
    #include "gpio.h"
    
    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    
    /* USER CODE END Includes */
    
    /* Private typedef -----------------------------------------------------------*/
    /* USER CODE BEGIN PTD */
    
    /* USER CODE END PTD */
    
    /* Private define ------------------------------------------------------------*/
    /* USER CODE BEGIN PD */
    
    /* USER CODE END PD */
    
    /* Private macro -------------------------------------------------------------*/
    /* USER CODE BEGIN PM */
    
    /* USER CODE END PM */
    
    /* Private variables ---------------------------------------------------------*/
    
    /* USER CODE BEGIN PV */
    
    /* USER CODE END PV */
    
    /* Private function prototypes -----------------------------------------------*/
    void SystemClock_Config(void);
    /* USER CODE BEGIN PFP */
    
    /* USER CODE END PFP */
    
    /* Private user code ---------------------------------------------------------*/
    /* USER CODE BEGIN 0 */
    uint32_t compareValue =0;
    	void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim){
    			if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){//判断是否为通道2
    					if(compareValue> htim->Instance->ARR){//比较直必须小于从装置
    							compareValue=0;
    					}
    					compareValue=compareValue+100;//增加的值设置越大闪烁越慢     (其改的是一个周期内产生几个信号)
    					__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_2,compareValue);//修改比较值
    					
    			}
    	}
    /* USER CODE END 0 */
    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    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_TIM2_Init();
      /* USER CODE BEGIN 2 */
    //打开比较定时的中断
    	HAL_TIM_OC_Start_IT(&htim2,TIM_CHANNEL_2);
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    
    /**
      * @brief System Clock Configuration
      * @retval None
      */
    void SystemClock_Config(void)
    {
      RCC_OscInitTypeDef RCC_OscInitStruct = {0};
      RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    
      /** Initializes the RCC Oscillators according to the specified parameters
      * in the RCC_OscInitTypeDef structure.
      */
      RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
      RCC_OscInitStruct.HSEState = RCC_HSE_ON;
      RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
      RCC_OscInitStruct.HSIState = RCC_HSI_ON;
      RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
      RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
      RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
      if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
      {
        Error_Handler();
      }
    
      /** Initializes the CPU, AHB and APB buses clocks
      */
      RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                  |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
      RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
      RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
      RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
      RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    
      if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
      {
        Error_Handler();
      }
    }
    
    /* USER CODE BEGIN 4 */
    
    /* USER CODE END 4 */
    
    /**
      * @brief  This function is executed in case of error occurrence.
      * @retval None
      */
    void Error_Handler(void)
    {
      /* USER CODE BEGIN Error_Handler_Debug */
      /* User can add his own implementation to report the HAL error return state */
      __disable_irq();
      while (1)
      {
      }
      /* USER CODE END Error_Handler_Debug */
    }
    
    #ifdef  USE_FULL_ASSERT
    /**
      * @brief  Reports the name of the source file and the source line number
      *         where the assert_param error has occurred.
      * @param  file: pointer to the source file name
      * @param  line: assert_param error line source number
      * @retval None
      */
    void assert_failed(uint8_t *file, uint32_t line)
    {
      /* USER CODE BEGIN 6 */
      /* User can add his own implementation to report the file name and line number,
         ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
      /* USER CODE END 6 */
    }
    #endif /* USE_FULL_ASSERT */
    

    总结

    输出比较是一个周期内产生几个信号(信号分成几份)

    PWM为特殊的输出比较   是一个周期内低平和高平如何分配

    区别

  • 功能目的:输出比较通常用于产生精确的定时事件,而PWM用于模拟信号的生成和控制。
  • 信号形式:输出比较产生离散的脉冲或电平变化,PWM产生连续的脉冲信号。
  • 调节能力:PWM可以通过改变占空比来调节输出功率或电压,而输出比较通常不具备这种调节能力。
  • 使用场景:输出比较适用于需要精确时间控制的场合,PWM适用于需要连续模拟量控制的场合。
  • 作者:快秃头的码农

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32_HAL__TIM_输出比较

    发表回复