• STM32 使用HAL库,HAL_Delay()会卡死, 程序一直卡在 HAL_GetTick( ) 函数中(已解决)


    今天遇到个很奇怪的问题, 不知道为什么, 单片机运行一会之后, 系统就没反应了, 经过调试发现, 系统卡在HAL_Delay()中了.
    之前也遇到过这个问题后来把HAL_Delay 去掉了. 然后发现不行, 还是得有它.不然发串口数据发的太快会乱掉. 得慢点发.

    然后调试到HAL_Delay()方法的内部发现 HAL_GetTick( )函数一直返回

    __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函数里
      while ((HAL_GetTick() - tickstart) < wait)
      {
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    再跟踪发现 HAL_GetTick() - tickstart 永远等于0
    这就很奇怪了.
    于是再深入看一下HAL_GetTick()函数. 代码如下

    __weak uint32_t HAL_GetTick(void)
    {
      return uwTick;
    }
    
    • 1
    • 2
    • 3
    • 4

    也就是说, uwTick 不再更新了. 数值永远是某个固定数值.
    那uwTick 到底是怎么更新的呢?
    最后发现
    在这里更新的.

    __weak void HAL_IncTick(void)
    { 
      uwTick += uwTickFreq;
    }
    
    • 1
    • 2
    • 3
    • 4

    调试发现 uwTickFreq ===0
    也就是说, uwTick 不再增加了.
    所以导致外层的while死循环了.
    那么uwTickFreq又是什么时候变成0的呢?
    我跟踪了很久也没有拦截到uwTickFreq 是什么时候更新的. keil工具也拦截不到是什么时候更新的.
    最后索性, 给uwTickFreq 一个默认值. 只要发现 uwTickFreq 为0了.
    就给它个默认值., 然后就把代码改成了下面这样的函数.
    由于源代码函数是__weak 的, 也就是说, 可以被覆盖的.
    于是我在自己的main.c 文件代码中重新写了一下. 如下:

    void HAL_IncTick(void)
    {
    	if(uwTickFreq==0)
    	{
    		uwTickFreq = HAL_TICK_FREQ_DEFAULT;
    	}
      uwTick += uwTickFreq;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如果不在乎延迟时间的精准度, 可以考虑.写成下面的这种, 更快一点

    void HAL_IncTick(void)
    { 
      uwTick += HAL_TICK_FREQ_DEFAULT;
    } 
    
    • 1
    • 2
    • 3
    • 4

    后来经过调试, 我猜测是因为定时器的停止和开启导致的.
    具体中间的原因就不再深入细究了. 有时间精力的朋友可以再追踪下去.
    找到原因欢迎分享.

    我用的是STM32F103C8T6 , 其中的定时器TIM3用来驱动ADC的采样频率.
    在循环中不停的停止和开启Tim3. 我估计是因为这个原因导致的. uwTickFreq 重新计算.

    而且我这里做了自动计算Tim3的自动重载计数值. 估计是跟它有关.
    具体的不再深入探究了.
    延迟时间就写死吧…

    后来我换了个定时器, 不再重置TIM定时器的PSC, 然后就好了. .

    昨天电脑坏了重装系统, 然后小半年的代码都没了. …我操…该死的Dell电脑, 恶心的要死, 故意搞的不能重装系统. 不能从u盘启动, 以后再也不买dell电脑了. …

  • 相关阅读:
    Celery笔记五之消息队列
    阿里云国际跨账号迁移CDN域名操作步骤
    如何用Jmeter编写脚本压测?
    二维码生成和解析工具包-zxing
    QT中使用moveToThread让任务在子线程中进行
    Deep Freeze冰点还原2024中文免费版恢电脑数据恢复工具
    常用CROS解决方案
    真不戳,Java 协程终于来了
    对齐管理后台中的账户体系的四种方法
    人与人之间的差异在于外界
  • 原文地址:https://blog.csdn.net/phker/article/details/134192972