当前位置: 首页 > news >正文

STM32cubeMX配置Systick的bug

STM32cubeMX版本:6.11.0

现象

STM32cubeMX配置Systick的时钟,不管选择不分频 还是8分频。

生成的代码都是一样的,代码都是不分频。

即不管选择不分频还是8分频,Systick都是使用的系统时钟
在这里插入图片描述

函数调用

HAL_Init() →
HAL_InitTick(TICK_INT_PRIORITY) →
HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) →
SysTick_Config(TicksNumb)

各个函数的源码如下所示:

__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/if((uint32_t)uwTickFreq == 0UL){return HAL_ERROR;}/* Configure the SysTick to have interrupt in 1ms time basis*/if (HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)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;
}uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{return SysTick_Config(TicksNumb);
}__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk){return (1UL);                                                   /* Reload value impossible */}SysTick->LOAD  = (uint32_t)(ticks - 1UL);                         /* set reload register */NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */SysTick->VAL   = 0UL;                                             /* Load the SysTick Counter Value */SysTick->CTRL  = SysTick_CTRL_CLKSOURCE_Msk |SysTick_CTRL_TICKINT_Msk   |SysTick_CTRL_ENABLE_Msk;                         /* Enable SysTick IRQ and SysTick Timer */return (0UL);                                                     /* Function successful */
}

可以看到
HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq))
括号里的(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) 会被设置为SysTick的LOAD寄存器,即重装载值。
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */

Cortex M7内核手册有对Systick 的控制和状态寄存器的介绍。
bit2 CLKSOURCE 表明了Systick的时钟源。
为1 时,时钟源为处理器时钟,即系统时钟,也就是不分频或者说1分频。
为0 时,时钟源为外部时钟,也就是系统时钟的8分频。
在这里插入图片描述
而Systick的控制与状态寄存器的时钟源选择位设为1。
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk,即使用系统时钟。

不管选择不分频还是8分频,生成的代码都是这样的,也就是SysTick一直使用的是系统时钟。

配置时钟源HAL_SYSTICK_CLKSourceConfig

其实HAL是有选择时钟源的函数的,就是HAL_SYSTICK_CLKSourceConfig。
源码如下:

/*** @brief  Configures the SysTick clock source.* @param  CLKSource specifies the SysTick clock source.*         This parameter can be one of the following values:*             @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source.*             @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source.* @retval None*/
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
{/* Check the parameters */assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource));if (CLKSource == SYSTICK_CLKSOURCE_HCLK){SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;}else{SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK;}
}

我们可以看到 ,配置时钟源也就是设置状态与控制寄存器SysTick->CTRL。

但是这个函数从未被调用。

继续文件搜索这个函数

在stm32h7xx_hal_cortex.c文件中 ,发现了这么一段注释:

在这里插入图片描述

You can change the SysTick Clock source to be HCLK_Div8 by calling the macro
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the
HAL_SYSTICK_Config() function call. The HAL_SYSTICK_CLKSourceConfig() macro is defined
inside the stm32h7xx_hal_cortex.h file.

你可以通过在这个函数HAL_SYSTICK_Config()之后调用HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8)来更改SysTick的时钟源为HCLK_Div8 。

验证

我们来实验一下

main中的大循环里只有一个点灯程序,每1s切换一次。

在这里插入图片描述
修改HAL_SYSTICK_Config函数,在SysTick_Config之后调用HAL_SYSTICK_CLKSourceConfig。

uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{//return SysTick_Config(TicksNumb);uint32_t ret = 0;ret = SysTick_Config(TicksNumb);HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK_DIV8);return ret;
}

现象:led灯由原来的1s切换一次,变为8s切换一次。

这是因为SysTick的频率变为原来的1/8。

但是重装载值依然为原来1ms时的装载值(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) 。
也就是重装载值没变,但是速度变慢了8倍。

将(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq))修改为
(SystemCoreClock/ 8 / (1000UL / (uint32_t)uwTickFreq))。

现象:led灯1s切换一次。

http://www.lryc.cn/news/425175.html

相关文章:

  • 分享几个好用js片段
  • web前端之实现一只可爱的小杰尼乌龟、伪元素、动画
  • 银河麒麟服务器版在rc.local使用ifcong 配置IP和nmcli的区别
  • 【运维】深入理解 Linux 中的 `mv` 命令,使用 `mv` 移动所有文件但排除特定文件或文件夹
  • Xilinx课程,就这么水灵灵地上线了~
  • 【axios get请求 中文乱码】
  • 智能分析/视频汇聚EasyCVR安防视频融合管理云平台技术优势分析
  • arcgis-坡度坡向分析
  • 【银河麒麟高级服务器操作系统】实际案例分析,xfsaild占用过高
  • JS中【setTimeout】使用注意事项总结
  • 已解决ArkTS开发webview,html页面中的input和按钮等操作均无响应
  • ChatGPT无法登录,提示我们检测到可疑的登录行为,将阻止进一步的尝试。请与管理员联系
  • 【数据结构篇】~复杂度
  • 深入理解Python中的JSON模块:解析与生成JSON数据的实用指南
  • 机器学习三要素:模型、策略和算法
  • 利用红黑树封装map和set
  • python pyqt5暂停和恢复功能
  • CAN总线详解-理论知识部分
  • 【Java数据结构】---List(LinkedList)
  • 开发军用LabVIEW程序注意事项
  • A3VLM: Actionable Articulation-Aware Vision Language Model
  • 企业高性能web服务器
  • 数据库:深入解析SQL分组与聚合——提升数据查询效率的关键技巧
  • 【CSS】数字英文css没有转换成...换行点、没有换行、拆分的问题(非常常见的需求)
  • C++ string模拟实现
  • Lora 全文翻译
  • 结题阶段(2024年8月)
  • 贪吃蛇(C语言详解)
  • 国际以太网专线(IEPL)与国际专线(IPLC)服务
  • vue 子父组件互相改值