本帖最后由 南来之风 于 2023-7-31 22:42 编辑
#申请原创# 目前ST官方库有1ms的延迟函数:HAL_Delay(),但是有时候需要用到1us延迟,官方没有提供HAL库供我们调用。此时可以使用功能强大的TIM模块来产生任意时间点延迟,并最终实现呼吸灯效果。
关于TIM模块的基本用法,可以参考我的上一篇帖子:【STM32WBA52CG测评】-4- 定时器模块TIM例程分析 https://bbs.21ic.com/icview-3318482-1-1.html
本次我们将修改main.h中TIM模块相关参数,实现一个1us的中断,然后在ISR中,放置一个计数器,之后封装一个微秒延迟接口供主函数调用。
- /* USER CODE BEGIN Private defines */
- /*
- In this example TIM2 input clock (TIM2CLK) is set to APB1 clock (PCLK1),
- since APB1 prescaler is equal to 1.
- TIM2CLK = PCLK1
- PCLK1 = HCLK
- => TIM2CLK = HCLK = SystemCoreClock
- To get TIM2 counter clock at 2 MHz, the Prescaler is computed as following:
- Prescaler = (TIM2CLK / TIM2 counter clock) - 1
- Prescaler = (SystemCoreClock /2 MHz) - 1
- Note:
- SystemCoreClock variable holds HCLK frequency and is defined in system_stm32wbaxx.c file.
- Each time the core clock (HCLK) changes, user had to update SystemCoreClock
- variable value. Otherwise, any configuration based on this variable will be incorrect.
- This variable is updated in three ways:
- 1) by calling CMSIS function SystemCoreClockUpdate()
- 2) by calling HAL API function HAL_RCC_GetSysClockFreq()
- 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
- ----------------------------------------------------------------------- */
- /* Compute the prescaler value to have TIMx counter clock equal to 2000000 Hz (2 MHz) */
- #define PRESCALER_VALUE (uint32_t)(((SystemCoreClock) / (2000000)) - 1)
- /* Initialize TIMx peripheral as follows:
- + Period = 10000 - 1
- + Prescaler = (SystemCoreClock/1000000) - 1
- + ClockDivision = 0
- + Counter direction = Up
- */
- #define PERIOD_VALUE (2 - 1);
复制代码 上面的代码,把TIM模块100MHz的时钟,通过预分频器后得到2MHz的时钟,接着定义Period参数为1,这样就是2MHz/(Period + 1) = 1MHz
每1us进入如下函数执行,其中myCounter是一个静态全局变量:
- /**
- * [url=home.php?mod=space&uid=247401]@brief[/url] Period elapsed callback in non blocking mode
- * @param htim : TIM handle
- * @retval None
- */
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- myCounter++;
- BSP_LED_Toggle(LD3);
- }
复制代码
接着封装一个延迟函数:
- void my_delay_us(uint32_t Nus){
-
- uint32_t i = myCounter;
- while((myCounter - i ) <= Nus){
- ;
- }
- }
复制代码
主函数中通过如下简单的延迟,即可实现呼吸灯的效果
- while (1)
- {
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- for(i = 0; i < interVal; i++){
- BSP_LED_Off(LD1);
- my_delay_us(i);
- BSP_LED_On(LD1);
- my_delay_us(interVal-i);
- }
- for(i = 0; i < interVal; i++){
- BSP_LED_On(LD1);
- my_delay_us(i);
- BSP_LED_Off(LD1);
- my_delay_us(interVal-i);
- }
- }
复制代码
最终效果:
|
|