当前位置: 首页 > 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切换一次。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • js原生模板引擎
  • 浅看MySQL数据库
  • 面试题 08.01. 三步问题
  • PULLTYPE
  • MoExtend: 模态和任务扩展调整的新专家
  • Windows安装mmdet3d v0.17.1(跑通版)
  • Linux-零拷贝技术
  • glm4-9B-chat,使用提示工程激活模型最大潜力
  • AR 眼镜之-开关机定制-实现方案
  • java语言中的websocket
  • 通过AI帮我分析实现的2019销售季度对比叠加图
  • nc的多种使用场景和各种反向shell方法
  • 【MySQL】什么是事务?在高并发场景使用事务会出现什么问题,该如何解决
  • 数据结构与算法 - 图
  • EFCore中结合Dapper执行SQL任意查询
  • 收藏网友的 源程序下载网
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • ERLANG 网工修炼笔记 ---- UDP
  • Fastjson的基本使用方法大全
  • JavaScript 奇技淫巧
  • JS 面试题总结
  • js中forEach回调同异步问题
  • PhantomJS 安装
  • Python爬虫--- 1.3 BS4库的解析器
  • React Native移动开发实战-3-实现页面间的数据传递
  • Webpack 4x 之路 ( 四 )
  • 订阅Forge Viewer所有的事件
  • 关于 Cirru Editor 存储格式
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 老板让我十分钟上手nx-admin
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 因为阿里,他们成了“杭漂”
  • ​第20课 在Android Native开发中加入新的C++类
  • #etcd#安装时出错
  • #include到底该写在哪
  • #stm32整理(一)flash读写
  • (1)Jupyter Notebook 下载及安装
  • (3)llvm ir转换过程
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (C#)一个最简单的链表类
  • (Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (ros//EnvironmentVariables)ros环境变量
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)ssm高校实验室 毕业设计 800008
  • (附源码)小程序 交通违法举报系统 毕业设计 242045
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (十一)图像的罗伯特梯度锐化
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (转)JAVA中的堆栈
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • *算法训练(leetcode)第四十七天 | 并查集理论基础、107. 寻找存在的路径