[Tool usage] STM32CubeMX-basic timer configuration

I. Overview

    Whether you are a novice or a master, based on the development of STM32 single-chip microcomputer, using STM32CubeMX can greatly improve the development efficiency, and its interface development also greatly reduces the development threshold for novices on STM32 single-chip microcomputer.
    This article mainly describes the configuration and related knowledge of the timer of the STM32 chip.

2. Software description

    STM32CubeMX is an official ST MCU/MPU cross-platform graphical tool for ST. It supports development under Linux, MacOS, and Window systems. Its underlying interface is the HAL library. In addition, students who are accustomed to register development, LL libraries can also be used. In addition to integrating the hardware abstraction layer of MCU/MPU, STM32CubeMX also integrates middleware such as RTOS, file system, USB, network, display, embedded AI, etc., so that developers can easily complete the underlying driver of MCU/MPU Configuration, leaving more energy to develop upper-layer functional logic, can further improve the efficiency of embedded development.
    Demo version 6.7.0

3. Introduction to Timer

    The timer, as the name suggests, is the function of timing. The timer is the most basic peripheral in the microcontroller except GPIO. In ST, timers are divided into several types, basic timers, general-purpose timers, advanced timers and low-power timers. This article focuses on the configuration of basic timers, and other types of timers are described in detail in other chapters.
    The basic timer is to provide only the most basic timing function. Below we will explain the principle of the timer from the block diagram of the ST basic timer.
insert image description here
    Taking timing 1s as an example, if the current input clock frequency is 1MHz, how can we get the interval of 1s? As we all know, 1MHz itself means a frequency of 1,000,000 times per second, so it is easy to think that if the timer counts a number every clock cycle, it will take 1s to count 1,000,000 times. So the first parameter appears - Auto Reload Value . The function of this parameter is: when the count reaches the auto reload value, an overflow interrupt flag can be triggered, and the user can get the overflow interrupt flag Get 1s time.
    However, the reality is not so ideal. The auto-reload value is only 16 bits, and the count value of the timer is only 16 bits. That is to say, the maximum count can only reach 65535, and it cannot reach 1000000 at all. What should I do? Think about it, since the counting cannot reach such a large number, is it possible to make the counting not so fast, for example, let the timer count at a frequency of 1kHz, then only need to count 1000 times to get 1s time. But the input of the timer is 1MHz, how can I make it slower? At this time another parameter comes in handy - the prescaler value (Prescaler Value) . If 1MHz is divided by 2, it is 500kHz, and if it is divided by 1000, it is 1kHz.

4. Timer configuration

    After reading the principle, here we will look at the specific function implementation. Take the above 1s clock as an example, how to set it in CubeMX.

  • basic configuration

    First look at the configuration interface, because here we only need a function of timing notification, and do not need to use an external port, so we can directly select "TIM6" in the tab "Timers" (TIM6 is the basic timer), tick Select "Activated" to enable the timer.
insert image description here
    Next, look at some basic configuration information.
insert image description here
One Pulse Mode: After this mode is turned on, as long as the overflow flag is triggered once, the counting enable will be automatically turned off. If you want to trigger it again, you need to manually turn on the counting enable. So if you want to implement periodic trigger events, you don't need to check this option.
Prescaler: One of the novice killers, although the prescaler is written here, but the actual setting value is the prescaler -1, that is, when the frequency is divided by 10, it needs to be set to 9.
Counter Mode: The counting mode, also called the counting direction, determines whether the timer counts up or down. If it is only used for timing, incrementing or decrementing has no effect.
Counter Period (Counter Period): When the count value reaches the count period value, an overflow flag will be triggered. Novice killer 2, because the count starts from 0, so if you want to achieve 10 counts, you only need to set 9 is enough.
Auto-reload (auto-reload preload): If auto-reload is selected, after an overflow flag is triggered, the timer will automatically clear the count to 0 and start counting again.
Trigger event selection (Trigger Event Selection): You can choose to trigger the output through the UG flag, count enable, and overflow flag, which is generally not used.

    In order to achieve 1s timing, we must first know the clock frequency of the current timer. Check the clock tree first. TIM6 is hung on the APB clock bus. Here we set it according to the highest frequency of the single chip microcomputer, which is 48MHz.
insert image description here
    For the convenience of calculation, here we can fill in 47999 for the prescaler coefficient, which is 48000 frequency division. The counting cycle can be filled with 999, that is, counting 1000 times. In addition, enable automatic reloading, so that a 1s cycle count can be obtained.
insert image description here
    In order to let us know immediately when the counting period is up to perform some operations, we also need to open the interrupt service function here. In the "NVIC Setting" tab, check the "TIM6" interrupt enable.
insert image description here
    After completing the above configuration and selecting the library to use, the project code can be generated.

  • LL library code implementation

    Add the following code to the generated project to flip a bool variable when an interrupt is triggered.

/***************************main.c******************************/
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_TIM6_Init();
  /* USER CODE BEGIN 2 */
  
  /* 使能更新中断 */
  LL_TIM_EnableIT_UPDATE(TIM6);
  /* 使能计数 */
  LL_TIM_EnableCounter(TIM6);
  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

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

/***************************stm32f0xx_it.c******************************/
void TIM6_DAC_IRQHandler(void)
{
    
    
  /* USER CODE BEGIN TIM6_DAC_IRQn 0 */
  /* 进中断后判断如果使能了更新中断,且更新中断标志为1,则翻转数据,并清除标志 */
  if (   (LL_TIM_IsActiveFlag_UPDATE(TIM6))
      && (LL_TIM_IsEnabledIT_UPDATE(TIM6))
	   )
  {
    
    
      LL_TIM_ClearFlag_UPDATE(TIM6);
      TestTimer = (++TestTimer) % 2;
  }
  /* USER CODE END TIM6_DAC_IRQn 0 */

  /* USER CODE BEGIN TIM6_DAC_IRQn 1 */

  /* USER CODE END TIM6_DAC_IRQn 1 */
}
/*******************************************************************/
  • HAL library code implementation
/* USER CODE BEGIN 0 */
uint8_t TestTimer = 0;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    
    
  /* Prevent unused argument(s) compilation warning */
  UNUSED(htim);
  TestTimer = (++TestTimer) % 2;
  /* NOTE : This function should not be modified, when the callback is needed,
            the HAL_TIM_PeriodElapsedCallback could be implemented in the user file
   */
}
/* 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_TIM6_Init();
  /* USER CODE BEGIN 2 */
  
  /* 使能更新中断 */
  HAL_TIM_Base_Start_IT(&htim6);
  /* 启动定时器 */
  HAL_TIM_Base_Start(&htim6);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
  • Effect demonstration

insert image description here

    Burning software for debugging, you can see that the variable flips once every 1s.

5. Matters needing attention

1. Note that when setting the prescaler coefficient and reload value, you need to subtract 1, that is, if you want to divide by 2, PSC needs to be set to 1, and if you want to count 10 resets, you need to set 9 for the reload value .
2. After configuring the generated project, it will not be counted when it is initialized. It needs to call the LL library to open it during use.

Guess you like

Origin blog.csdn.net/u012749085/article/details/131396208