STM32CubeMX study notes (4)-system delayed use

1. Introduction to SysTick

SysTick —The system timer is a peripheral in the CM3 core and is embedded in the NVIC . The system timer is a 24-bit down counter. The time of each counter is 1/SYSCLK . Generally, we set the system clock SYSCLK to 72M . When the value of the reloaded value register is decremented to 0, the system timer will generate an interrupt, which will cycle back and forth.

Because SysTick is a peripheral belonging to the CM3 core, all CM3 core-based microcontrollers have this system timer, which makes the software easy to transplant in the CM3 microcontroller. The system timer is generally used in the operating system to generate a time base and maintain the heartbeat of the operating system.

2. New construction

1. Open the STM32CubeMX software and click "New Project"

2. Choose MCU and package

3. Configure the clock
RCC settings, select HSE (external high-speed clock),

select Clock Configuration for Crystal/Ceramic Resonator (crystal oscillator/ceramic resonator) , configure the system clock SYSCLK to 72MHz,
modify the value of HCLK to 72, and press Enter. Automatically modify all configurations

4. It
is a very important step to configure the debug mode , otherwise the debugger
SYS setting will not be recognized after the first programming program , select Debug as Serial Wire

5. Configure GPIO
GPIO settings, find the corresponding pin of the LED light in the figure on the right, select GPIO_Output, output low level lights up, you can add a custom label

6. The generated code
input path item names and item

selection of an application development environment IDE MDK-ARM V5

each peripheral generates a separate ’.c/.h’file
not hook: All initialization code is generated in main.c
checked: initialization code generated in the associated peripheral file. For example, the GPIO initialization code is generated in gpio.c.
Click GENERATE CODE to generate code

Three, ordinary delay

3.1 Modify the main function to realize the water lamp

Add function pin output is inverted while () loop HAL_GPIO_TogglePin()and delay function HAL_Delay().

/**
  * @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();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);

    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

3.2 Comparison of HAL library and standard library code

STM32CubeMX uses the code generated by the HAL library:

/**
  * @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();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
    /* USER CODE END WHILE */
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);

    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    HAL_Delay(500);
    HAL_GPIO_TogglePin(LED_B_GPIO_Port,LED_B_Pin);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

HAL_StatusTypeDef HAL_Init(void)
{
    
    
  /* Configure Flash prefetch */
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
    defined(STM32F102x6) || defined(STM32F102xB) || \
    defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
    defined(STM32F105xC) || defined(STM32F107xC)

  /* Prefetch buffer is not available on value line devices */
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif
#endif /* PREFETCH_ENABLE */

  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
  HAL_InitTick(TICK_INT_PRIORITY);

  /* Init the low level hardware */
  HAL_MspInit();

  /* Return function status */
  return HAL_OK;
}

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
    
    
  /* Configure the SysTick to have interrupt in 1ms time basis*/
  if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
  {
    
    
    return HAL_ERROR;
  }

  /* Configure the SysTick IRQ priority */
  if (TickPriority < (1UL << __NVIC_PRIO_BITS))
  {
    
    
    HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
    uwTickPrio = TickPriority;
  }
  else
  {
    
    
    return HAL_ERROR;
  }

  /* Return function status */
  return HAL_OK;
}

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
    
    
  /* USER CODE BEGIN SysTick_IRQn 0 */

  /* USER CODE END SysTick_IRQn 0 */
  HAL_IncTick();
  /* USER CODE BEGIN SysTick_IRQn 1 */

  /* USER CODE END SysTick_IRQn 1 */
}

Use STM32 standard library code:

/**
  * @brief  主函数
  * @param  无  
  * @retval 无
  */
int main(void)
{
    
    	
	/* LED 端口初始化 */
	LED_GPIO_Config();

	/* 配置SysTick 为10us中断一次 */
	SysTick_Init();

	for(;;)
	{
    
    

		LED1( ON ); 
		SysTick_Delay_Ms( 1000 );
		LED1( OFF );
	  
		LED2( ON );
		SysTick_Delay_Ms( 1000 );
		LED2( OFF );
	} 	
}

/**
  * @brief  启动系统滴答定时器 SysTick
  * @param  无
  * @retval 无
  */
void SysTick_Init(void)
{
    
    
	/* SystemFrequency / 1000    1ms中断一次
	 * SystemFrequency / 100000	 10us中断一次
	 * SystemFrequency / 1000000 1us中断一次
	 */
//	if (SysTick_Config(SystemFrequency / 100000))	// ST3.0.0库版本
	if (SysTick_Config(SystemCoreClock / 100000))	// ST3.5.0库版本
	{
    
     
		/* Capture error */ 
		while (1);
	}
}

// couter 减1的时间 等于 1/systick_clk
// 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
// 同时 CTRL 的 countflag 位会置1
// 这一个循环的时间为 reload * (1/systick_clk)

void SysTick_Delay_Us( __IO uint32_t us)
{
    
    
	uint32_t i;
	SysTick_Config(SystemCoreClock/1000000);
	
	for(i=0;i<us;i++)
	{
    
    
		// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1	
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	// 关闭SysTick定时器
	SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
}

void SysTick_Delay_Ms( __IO uint32_t ms)
{
    
    
	uint32_t i;	
	SysTick_Config(SystemCoreClock/1000);
	
	for(i=0;i<ms;i++)
	{
    
    
		// 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
		// 当置1时,读取该位会清0
		while( !((SysTick->CTRL)&(1<<16)) );
	}
	// 关闭SysTick定时器
	SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
}

HAL_InitTick(TICK_INT_PRIORITY);Correspondence SysTick_Init();
HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq))correspondence SysTick_Config(SystemCoreClock/1000000)
HAL_Delay(500);correspondenceSysTick_Delay_Ms(500);

Fourth, the delay in interrupt

In the GPIO interface - (3) ESP8266 study notes the HAL_GPIO_EXTI_Callbackadded key debounce

/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    
    
	if(GPIO_Pin==KEY1_Pin)
	{
    
    
        HAL_Delay(100);
        if(HAL_GPIO_ReadPin(KEY1_Pin_Port,KEY1_Pin)==1)
        {
    
    
            HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
        }
	}
}
/* USER CODE END 1 */

Now downloading into the MCU will only make it have no response after the button is pressed. This is why, in fact, the problem lies in HAL_Delay()it.

After entering the callback function've been HAL_Delaycaught in an endless loop, because Systick priority was too low.

The preemption priority of the Systick interrupt is the same as the preemption priority of the external interrupt. Then the Systick interrupt must not be triggered when the external interrupt is triggered. The problem has been found. Simply lower the preemption priority of the external interrupt. .

  • Preempt the priority, the smaller the number, the higher the priority
  • If the preemption priority is the same, determine the sub-priority. Similarly, the smaller the number, the higher the priority

Five, matters needing attention

User code to be added to USER CODE BEGIN Nand USER CODE END Nbetween, otherwise the next use after STM32CubeMX regenerate the code, it will be deleted.


Written by Leung on January 13, 2021

• Reference: "Embedded-STM32 Development Guide" Part Two Basics-Chapter 2 Systick System Timer (HAL Library)
    STM32CubeMX Practical Tutorial (3)-External Interrupt (Interrupt and HAL_Delay function to avoid pits)

Guess you like

Origin blog.csdn.net/qq_36347513/article/details/112553860