[HAL]5.中断里调用HAL_Delay()进入死循环的原因

中断里调用HAL_Delay()进入死循环的原因 

摘自:http://blog.csdn.net/alwxkxk/article/details/47204677

CUBE生成的程序中, SysTick是中断型延时(利用中断来查询时间到了没)。

  /* Use systick as time base source and configure 1ms tick (default clock after Reset is MSI) */

  HAL_InitTick(TICK_INT_PRIORITY);

#define  TICK_INT_PRIORITY            ((uint32_t)0x000F)    /*!< tick interrupt priority */    

SysTick是内核中断,优先级别默认最低。

(可以用内核函数来修改~   当然,这就要看内核M3的书了,而不是看STM32的参考手册那么简单。暂时就不深入研究,日后更新。)

总结起来就是,就是传说中优先级别默认最低,虽然SysTick一直在跑,但是没进入到中断来读取它的值~

(不知是哪里让我潜意识地认为SysTick级别比外设都高,导致这问题)

如果中断里调用HAL_Delay就会停在那里,因为根本不会进入那个级别更低的中断。

 资料补充:

 网上还有一种写 法是时间摘取法,是一直读取SysTick产生延时函数~(原子的例程就是用这种方法)

其次,有人提到,中断里面不应该使用延时,中断所占的时间越短越好~有道理~

附上原子的时间摘取法的程序,很有学习价值~

  1 //////////////////////////////////////////////////////////////////////////////////  
  2 
  3 //本程序只供学习使用,未经作者许可,不得用于其它任何用途
  4 
  5 //Mini STM32开发板
  6 
  7 //使用SysTick的普通计数模式对延迟进行管理
  8 
  9 //包括delay_us,delay_ms
 10 
 11 //正点原子@ALIENTEK
 12 
 13 //技术论坛:www.openedv.com
 14 
 15 //修改日期:2010/5/27
 16 
 17 //版本:V1.2
 18 
 19 //版权所有,盗版必究。
 20 
 21 //Copyright(C) 正点原子 2009-2019
 22 
 23 //All rights reserved
 24 
 25 //********************************************************************************
 26 
 27 //V1.2修改说明
 28 
 29 //修正了中断中调用出现死循环的错误
 30 
 31 //防止延时不准确,采用do while结构!
 32 
 33 //////////////////////////////////////////////////////////////////////////////////  
 34 
 35 static u8  fac_us=0;//us延时倍乘数
 36 
 37 static u16 fac_ms=0;//ms延时倍乘数
 38 
 39 //初始化延迟函数
 40 
 41 //SYSTICK的时钟固定为HCLK时钟的1/8
 42 
 43 //SYSCLK:系统时钟
 44 
 45 void delay_init(u8 SYSCLK)
 46 
 47 {
 48 
 49 SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
 50 
 51 fac_us=SYSCLK/8;     
 52 
 53 fac_ms=(u16)fac_us*1000;
 54 
 55 }     
 56 
 57 //延时nms
 58 
 59 //注意nms的范围
 60 
 61 //SysTick->LOAD为24位寄存器,所以,最大延时为:
 62 
 63 //nms<=0xffffff*8*1000/SYSCLK
 64 
 65 //SYSCLK单位为Hz,nms单位为ms
 66 
 67 //对72M条件下,nms<=1864 
 68 
 69 void delay_ms(u16 nms)
 70 
 71 {        
 72 
 73 u32 temp;    
 74 
 75 SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
 76 
 77 SysTick->VAL =0x00;           //清空计数器
 78 
 79 SysTick->CTRL=0x01 ;          //开始倒数  
 80 
 81 do
 82 
 83 {
 84 
 85 temp=SysTick->CTRL;
 86 
 87 }
 88 
 89 while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
 90 
 91 SysTick->CTRL=0x00;       //关闭计数器
 92 
 93 SysTick->VAL =0X00;       //清空计数器        
 94 
 95 }   
 96 
 97 //延时nus
 98 
 99 //nus为要延时的us数.         
100 
101 void delay_us(u32 nus)
102 
103 {
104 
105 u32 temp;       
106 
107 SysTick->LOAD=nus*fac_us; //时间加载     
108 
109 SysTick->VAL=0x00;        //清空计数器
110 
111 SysTick->CTRL=0x01 ;      //开始倒数   
112 
113 do
114 
115 {
116 
117 temp=SysTick->CTRL;
118 
119 }
120 
121 while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
122 
123 SysTick->CTRL=0x00;       //关闭计数器
124 
125 SysTick->VAL =0X00;       //清空计数器  
126 
127 }
128 
129  
如果问题解决起来不妥或者有更好的解决办法,麻烦请告知,帮助曾经和你一样的入门者,谢谢。
原文地址:https://www.cnblogs.com/ourran/p/4809892.html