STM32G474之HAL_Delay()会导致死机的原因

news2024/9/23 3:23:04

使用HAL库需要HAL_Delay()函数支持,离开这个函数,和这个函数有关的函数就无法调用了。遇到这个问题,我们肯定会否定HAL库,也确实它是有点差,但也有好的一面。

为什么HAL库初始化了SysTick定时器,也使能了相关中断,一旦调用HAL_Delay()函数就挂住了。大多数原因是在SysTick_Handler()中没有调用HAL_IncTick()函数,不清楚HAL库为什么没有写SysTick_Handler()中断服务程序,导致很多人认为HAL库会卡死。

__weak void HAL_IncTick(void)
{
  uwTick += uwTickFreq;//uwTick计数器加1
}

__weak uint32_t HAL_GetTick(void)
{
  return uwTick;//读uwTick计数器
}

__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();
  uint32_t wait = Delay;

  /* Add a freq to guarantee minimum wait */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  while ( (HAL_GetTick() - tickstart) <wait )
  {//uwTick 不增加,(0-0)<wait,所以一值循环
  }
}

如果uwTick 不增加,HAL_Delay()就一直循环,像是卡死了一样

 Source of time base is configured  to generate interrupts at regular
 time intervals. Care must be taken if HAL_Delay() is called from a
 peripheral ISR process, the Tick interrupt line must have higher priority
 (numerically lower) than the peripheral interrupt. Otherwise the caller
 ISR process will be blocked.

使用“ctrl+shift+F”搜索“HAL_IncTick”

 搜索结果如下:

添加程序如下:

//systick中断服务函数,1ms中断一次
//在调用HAL_Init()时,SysTick定时器初始化为使能中断

void SysTick_Handler(void)
{
    HAL_IncTick();
    //使能HAL_Delay()
    //若SysTick定时器的中断优先级低于当前的中断服务程序,则该中断服务程序不能使用HAL_Delay;

}

如果在SysTick_Handler()中调用HAL_IncTick()函数,但是HAL_Delay()用于其它中断服务程序,原因是:SysTick定时器的中断优先级低于当前的中断服务程序,导致SysTick定时器无法进入中断,从而导致该中断服务程序不能使用HAL_Delay()。这就是HAL库为什么要将SysTick定时器的中断优先级设置为最高级别的原因。为了保证HAL_Delay()能在任何地方使用,HAL库实在有点霸道,主要还是HAL库的延时程序写得差。我在看到这个优先级配置,也有点懵逼了,想了很久,才知道原因所在

解决方法:

有没有解决方法?

有,就是要少用HAL_Delay(),让HAL库独占这个函数。可以单独写自己的延时函数。如下:

static uint8_t  fac_us=0;                            //us延时倍乘数               
static uint16_t fac_ms=0;                            //ms延时倍乘数,在ucos下,代表每个节拍的ms数

//函数功能:delay函数初始化
//在调用HAL_Init()时,已经对SysTick定时器初始化了,因此这里无需初始化

void delay_init(void)
{
    uint32_t reload;

    fac_us=SystemCoreClock/1000000;
    //相当于将170MHz经过1000000分频用作SysTick的输入时钟,即周期为1us 

    reload=SystemCoreClock/1000000;
  //相当于将170MHz经过1000000分频用作SysTick的输入时钟,即周期为1us 
    reload*=1000;
    //SysTick溢出时间为1000*1us=1ms
    //reload为24位寄存器,最大值:16777216,在170MHz下,约合0.098s左右  
 
    fac_ms=1;
}

//函数功能:延时nus微妙
//nus:要延时的us数.    
//nus:0~204522252(最大值即2^32/fac_us@fac_us=168)    
                                      
void delay_us(uint32_t nus)
{        
    uint32_t ticks;
    uint32_t told,tnow,tcnt=0;
    uint32_t reload=SysTick->LOAD;
    //读取SysTick的LOAD寄存器的值
    
    ticks=nus*fac_us; //计算需要的节拍数 
    told=SysTick->VAL;//刚进入时的计数器值
    while(1)
    {
        tnow=SysTick->VAL;//读SYSTICK计数器值    
        if(tnow!=told)
        {        
            if(tnow<told)tcnt+=told-tnow;    //SysTick定时器是一个递减的计数器.
            else tcnt+=reload-tnow+told;        
            told=tnow;
            if(tcnt>=ticks)break;            //时间超过/等于要延迟的时间,则退出.
        }        
    }                                            
}

//函数功能:延时nms毫秒
//nms:要延时的ms数
//nms:0~65535

void delay_ms(uint32_t nms)
{  
    delay_us((uint32_t)(nms*1000));//普通方式延时
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2090756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

书生大模型实战营(1)——InterStudio基础知识+Vscode SSH连接远程服务器+Linux基础指令

参加书生.浦江大模型实战训练营&#xff0c;学习大模型知识和微调技术&#xff0c;所有课程免费&#xff0c;通过闯关的形式学习&#xff0c;也比较有趣。一起来了解LLM的世界。邀请链接 产品简介 InternStudio 是大模型时代下的云端算力平台。基于 InternLM 组织下的诸多算法…

Android Handler消息机制完全解析(二)

欢迎转载&#xff0c;转载请注明出处&#xff1a;https://blog.csdn.net/dmk877/article/details/141690289 在阅读本篇博客之前建议先阅读此篇 Android Handler消息机制完全解析(一) 在看Looper源码之前必须要理解ThreadLocal&#xff0c;ThreadLocal在Handler消息机制中起到…

信息安全--(五)物理与环境安全技术(二)机房安全分析与防护

在使用本博客提供的学习笔记及相关内容时&#xff0c;请注意以下免责声明&#xff1a;信息准确性&#xff1a;本博客的内容是基于作者的个人理解和经验&#xff0c;尽力确保信息的准确性和时效性&#xff0c;但不保证所有信息都完全正确或最新。非专业建议&#xff1a;博客中的…

FlowUs 小程序:开启高效之旅,订阅内容超精彩

一、丰富多样的订阅选择 FlowUs 小程序提供了极为丰富的订阅内容。无论你是对知识管理、项目管理感兴趣&#xff0c;还是专注于创意写作、时间规划&#xff0c;都能在这里找到适合自己的订阅选项。从专业的行业资讯到实用的技巧指南&#xff0c;从激发灵感的创意案例到深入的学…

业务解耦-Spring事件监听的三种实现方式

实现ApplicationListener 步骤如下&#xff1a; 1.写Event类&#xff0c;需要继承Spring的ApplicationEvent类 2.写监听类&#xff0c;需要实现Spring的ApplicationListener接口&#xff0c;加上Component注解 3.监听类实现onApplicationEvent方法 4.通过ApplicationContext.p…

开放大世界的全局寻路

开放大世界的寻路一直是很困扰我的一个点&#xff0c;地图大、还是动态可变的&#xff0c;所以寻路会有很多要求。就我们项目来讲&#xff0c;有这几个要求&#xff1a; 能满足极大范围的地图&#xff1b; 地图寻路数据能实时构建&#xff0c;且重建代价很小&#xff1b; 寻路的…

地质灾害监测预警系统的作用

在地球的广阔舞台上&#xff0c;自然灾害如同不可预测的演员&#xff0c;时常上演着惊心动魄的剧目。地震的震撼、滑坡的肆虐、泥石流的咆哮&#xff0c;这些地质灾害不仅给人类生命财产带来巨大威胁&#xff0c;也考验着社会的防灾减灾能力。为了应对这一挑战&#xff0c;地质…

【Linux】在 bash shell 环境下,当一命令正在执行时,按下 control-Z 会?

目录 题目分析答案 题目 分析 ctrl-c&#xff1a; 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序&#xff1b;ctrl-z&#xff1a; 发送 SIGTSTP信号给前台进程组中的所有进程&#xff0c;常用于挂起一个进程&#xff1b;ctrl-d&#xff1a; 不是发送信…

乐城堡 JoyCastle Unity岗位笔试题

1)实现 move(GameObjct gameObject, Vector3 begin, Vector3 end, float time, bool pingpong){ } 使 gameObject 在 time 秒内&#xff0c;从 begin 移动到 end&#xff0c;若 pingpong 为 true&#xff0c;则在结束时 使 gameObject 在 time 秒内从 end 移动到 begin&#xf…

机器学习中的增量学习(Incremental Learning,IL)策略是什么?

机器学习中的增量学习&#xff08;Incremental Learning&#xff0c;IL&#xff09;策略是什么&#xff1f; 在当今快速发展的数据驱动世界中&#xff0c;传统的静态机器学习模型逐渐显露出局限性。随着数据量的增长和分布的变化&#xff0c;模型需要不断更新&#xff0c;以保…

opc da 服务器数据 转IEC61850项目案例

目录 1 案例说明 1 2 VFBOX网关工作原理 1 3 应用条件 2 4 查看OPC DA服务器的相关参数 2 5 配置网关采集opc da数据 4 6 用IEC61850协议转发数据 6 7 网关使用多个逻辑设备和逻辑节点的方法 9 8 在服务器上运行仰科OPC DA采集软件 10 9 案例总结 12 1 案例说明 在OPC DA服务…

使用 Vue3 Element Plus 实现el-table中的特定单元格编辑,下拉选择等

效果预览 完整代码(后面有解析) <template><div style="display: flex;align-items: center;justify-co

磁性齿轮箱市场报告:前三大厂商占有大约79.0%的市场份额

磁性齿轮箱是一种用于扭矩和速度转换的非接触式机构。它们无磨损、无摩擦、无疲劳。它们不需要润滑剂&#xff0c;并且可以针对其他机械特性&#xff08;如刚度或阻尼&#xff09;进行定制。 一、全球磁性齿轮箱行业现状与洞察 据 QYResearch 调研团队最新发布的“全球磁性齿轮…

成都高温限电:当电动汽车「无电可充」

8月末的成都&#xff0c;因为高温限电了。 近几日&#xff0c;成都市气象台连续发布了高温红色预警信号。据新华社报道&#xff0c;8月21日&#xff0c;四川电网用电负荷两次创下历史新高&#xff0c;最高达6797万千瓦&#xff0c;较去年最大用电负荷增长近13%&#xff0c;电力…

Golang | Leetcode Golang题解之第385题迷你语法分析器

题目&#xff1a; 题解&#xff1a; func deserialize(s string) *NestedInteger {index : 0var dfs func() *NestedIntegerdfs func() *NestedInteger {ni : &NestedInteger{}if s[index] [ {indexfor s[index] ! ] {ni.Add(*dfs())if s[index] , {index}}indexreturn…

HarmonyOS鸿蒙开发:在线短视频流畅切换最佳实践

简介 为了帮助开发者解决在应用中在线短视频快速切换时容易出现快速切换播放时延过长的问题&#xff0c;将提供对应场景的解决方案。 该解决方案使用&#xff1a; 视频播放框架AVPlayer和滑块视图容器Swiper进行短视频滑动轮播切换。绘制组件XComponent的Surface类型动态渲染…

挂载5T大容量外接硬盘到ubuntu

挂载5T大容量外接硬盘到ubuntu S1&#xff1a;查看硬盘 使用 $ sudo fdisk -l找到对应盘&#xff0c;例如下图所示 /dev/sdc S2: 创建分区 使用 $ sudo fdisk /dev/sdc对上硬盘进行创建分区&#xff1b;可以依次使用以下指令 m &#xff1a;查看命令&#xff1b; g &…

前端篇-html

day1: 超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language&#xff0c;简称&#xff1a;HTML&#xff09;是一种用于创建网页的标准标记语言。 作用&#xff1a;可以使用 HTML 来建立自己的 WEB 站点&#xff0c;HTML 运行在浏览器上&#xff0c;由浏览器…

基于贝叶斯优化CNN-LSTM网络的数据分类识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 卷积神经网络&#xff08;CNN&#xff09; 4.2 长短期记忆网络&#xff08;LSTM&#xff09; 4.3 BO-CNN-LSTM 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) B…

基于物联网的低成本便携式传感器节点用于火灾和空气污染的检测与报警

目录 摘要 引言 材料和方法 传感器节点 IoT 微控制器 颗粒物传感器 环境和气体传感器 MQTT代理 Node-Red监控平台 系统结构 数据存储 工作描述 实验结果 讨论 结论 致谢 参考文献 这篇论文的标题是《Low-cost IoT-based Portable Sensor Node for Fire and Air…