你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

质疑HAL库的延时函数HAL_Delay  

[复制链接]
GKoSon 提问时间:2018-4-20 08:55 /
是这样的,M3内核的滴答定时器一般用来做系统的时基,最频繁的变现就是延时函数了HAL_Delay。看一下延时函数的实现:
__weak void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = 0;
  tickstart = HAL_GetTick();
  while((HAL_GetTick() - tickstart) < Delay)
  {
  }
}


1.png

是一个空空死循环,只要HAL_GetTick() - tickstart 值没有大于你设置的Delay数值。
在看一下
__weak void HAL_IncTick(void)
{
  uwTick++;
}

__weak uint32_t HAL_GetTick(void)
{
  return uwTick;
}


其实这个HAL_GetTick()是一个全局变量。
static __IO uint32_t uwTick;
【预计上电以后默认是初始化为0的】

那么我的问题是:
比如我调用HAL_Delay(100),
此时uwTick是120,那么uwTick会随着时间脉冲++,
等uwTick到220的时候我的延时就从死循环出来了。
而如果【u32比较大 我就暂时当做u8吧 那就是255了】
我调用HAL_Delay(100),
此时uwTick是220,那么uwTick会随着时间脉冲++,理论到320的时候解除死循环,
而在255的时候,我擦,u8到了尽头了,会变到0!怎么办?


我想了一下 如果这样的话在255->0的时候回出现0-220的计算这个时候系统怎么处理呢?会直接解除死循环吗?
《我说的这种概率情况》
同时想起来刚刚做的笔试题目,是不是也是这个问题呢?
QQ截图20180420084329.png
收藏 2 评论25 发布时间:2018-4-20 08:55

举报

25个回答
XinLiYF 回答时间:2018-4-20 20:13:33
无符号的回环问题:(uint8_t)(0x00) - (uint8_t)(0xFF) = (uint8_t)(0x01)

这个是一个很好的例子:模仿kfifo实现的环形缓冲区

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

黑皮男 回答时间:2018-4-20 18:14:49
与龙共舞 发表于 2018-4-20 16:29
所以你的这思路就是把U32提升到U64 再次降低出现溢出的可能吗?

不是,是无符号数和有符号数的问题。http://www.cnblogs.com/hfyinsdu/p/4600052.html

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

七哥 回答时间:2018-4-20 09:13:49
本帖最后由 toofree 于 2018-4-20 09:15 编辑

HAL_Delay()函数的参数类型是uint32_t,即无符号32位int型。
如果超过32位的最大数(4亿多4294967296)的话,的确会有问题。那么延时会多长了呢,以标准的HAL_Delay()单位1ms计算,4294967296ms,4294967秒,1193小时。只能是人为判断,参数不要超过32位uint32_t。

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

freeelectron 回答时间:2018-4-20 09:09:17
1、楼主说的这种情况的确有的,但是你要考虑实际,谁会延迟u32 那么大的时间啊
2、一般这种有死循环多的,还是尽量开看门狗

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

wenyangzeng 回答时间:2018-4-20 09:46:13
uwTick是32位变量。不会出现楼主说的情况。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

wudianjun2001 回答时间:2018-4-20 09:50:25
32位的一般不会出现长时间的延时的

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

GKoSon 回答时间:2018-4-20 10:15:33
toofree 发表于 2018-4-20 09:13
HAL_Delay()函数的参数类型是uint32_t,即无符号32位int型。
如果超过32位的最大数(4亿多4294967296)的话 ...

哦 我传参是100 肯定OK  
我说的是(猜测) 比如此时ucTick数值就是4294967290 那会发生什么事呢?它++100会回到0
jjbboox 回答时间:2018-4-20 10:20:11
有什么好担心的,u32你知道需要等多少年吗?
time_t都没用完32位。

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

埃斯提爱慕 回答时间:2018-4-20 10:22:42
提示: 作者被禁止或删除 内容自动屏蔽
anobodykey 回答时间:2018-4-20 10:23:10
楼主可以多分析一下,建议你看下该链接https://www.stmcu.org.cn/module/forum/thread-608277-1-1.html,同样是讨论Hal_Delay的溢出问题,其实你就会发现ST把uwTick设计成为32位无符号型是有意义的,至于你说的把它改成u8类型其实适用于8位单片机系统,但stm32是32位的单片机系统,所以溢出问题不影响你的延时

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3

查看全部评分

wolfgang 回答时间:2018-4-20 10:49:21
HAL代码只是一个事例,具体情况具体分析,U32的循环完了,判断FF后又从0开始计数,或者直接忽略掉此处的溢出中断。循环往复了~~

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

七哥 回答时间:2018-4-20 11:54:22
与龙共舞 发表于 2018-4-20 10:15
哦 我传参是100 肯定OK  
我说的是(猜测) 比如此时ucTick数值就是4294967290 那会发生什么事呢?它++10 ...

会的,溢出后,肯定回到0
jjbboox 回答时间:2018-4-20 12:29:45
anobodykey 发表于 2018-4-20 10:23
楼主可以多分析一下,建议你看下该链接https://www.stmcu.org.cn/module/forum/thread-608277-1-1.html,同样是 ...

就算移植到8位的系统,uwTick也应该定义为uint32_t,就是unsigned long,怎么能改成uint_8呢?
Dandjinh 回答时间:2018-4-20 13:27:15
你的理解没错,是会溢出。可是不知道你注意到了没,跟tick相关函数的都是weak的,如果你觉得不够可以自己定义一套自己的tick

评分

参与人数 1蝴蝶豆 +2 收起 理由
zero99 + 2

查看全部评分

黑皮男 回答时间:2018-4-20 13:41:09
本帖最后由 黑皮男 于 2018-4-20 13:43 编辑

这个肯定会出现溢出,但是可以参考linux中的实现方法。下面是我的代码,只不过改了些名字,实现是一样的。
#define kernel_time_after(unknow, known)    ((long)(know)-(long)(unknow)<0)
#define kernel_time_before(unknow, know)    ((long)(unknow)-(long)(know)<0)
#define kernel_time_after_eq(unknow, know)  ((long)(unknow)-(long)(know)>=0)
#define kernel_time_before_eq(unknow, know) ((long)(know)-(long)(unknow)>=0)

void kernel_delay_ms(kernel_msec_t millis)
{
    unsigned long timeout = _kernel_wall_jiffies + millis/1000*KERNEL_HZ;
   
    while(kernel_time_before(_kernel_wall_jiffies, timeout));
        
}
zhdzhd 回答时间:2018-4-20 15:26:11
楼主这是什么试卷啊?
12下一页

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版