打印
[STM32F4]

stm32的hal库的hal_delay问题

[复制链接]
19291|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
fuluoce|  楼主 | 2015-1-29 17:41 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
STM32, TI, ck, ic, ui


void HAL_IncTick(void)
{
  uwTick++;
}
中断函数是1ms进来一次,也就是说uwTick+1就代表1ms
void SysTick_Handler(void)
{
  HAL_IncTick();
}
void HAL_Delay(__IO uint32_t Delay)
{
  __IO uint32_t timingdelay;

  timingdelay = uwTick + Delay;
  //while(HAL_GetTick() < timingdelay)
        while(uwTick < timingdelay)
  {;
  }
}
在HAL库里 我就没看到哪里对uwTick溢出进行处理,也就是说uwTick=0xffffffff的时候 再加1就是uwTick=0了  那这一时刻的延时不就延时不准确了吗?


uint32_t HAL_GetTick(void)
{
  return uwTick;  
}  
这函数,很多库文件调用,用来timeout 延时
我觉得调用了uint32_t HAL_GetTick(void)函数的延时都是有问题的
不过我算了一下 要连接上电46天多才会出现bug (0xffffffff个ms)
沙发
Serge_Ding| | 2015-1-30 16:01 | 只看该作者
少用延时才是硬道理

使用特权

评论回复
板凳
fuluoce|  楼主 | 2015-1-31 15:23 | 只看该作者
但是这是官方的延时bug  确实根据条件来判断会好过延时

使用特权

评论回复
地板
ticomi| | 2015-1-31 17:23 | 只看该作者
这个函数最大的问题不是这个,是这个函数需要调用中断函数的结果,如果一个更高级的中断需要调用这个函数,就无法得到延时而是直接一直等,所以最好重新写这个函数!

使用特权

评论回复
5
人民币的幻想| | 2015-2-2 08:14 | 只看该作者
如果一个更高优先级的中断打断它,那么根本延时就不准了,需要想办法用systick做延时。

使用特权

评论回复
6
人民币的幻想| | 2015-2-2 08:15 | 只看该作者
非中断方式来搞。

使用特权

评论回复
7
fuluoce|  楼主 | 2015-2-4 09:42 | 只看该作者
问题是 HAL库很多地方都是用到这uwTick变量来延时
uint32_t HAL_GetTick(void)
{
  return uwTick;  
}  
这函数,很多库文件调用,用来timeout 延时
我觉得调用了uint32_t HAL_GetTick(void)函数的延时都是有问题的
不过我算了一下 要连接上电46天多才会出现bug (0xffffffff个ms)

使用特权

评论回复
8
yyblike| | 2015-5-14 14:38 | 只看该作者
fuluoce 发表于 2015-2-4 09:42
问题是 HAL库很多地方都是用到这uwTick变量来延时
uint32_t HAL_GetTick(void)
{

好像确实存在这个问题,我觉得可以重写HAL_Delay函数,在每次调用之前或之后清零uwTick,尽量不要让uwtick满,不知道思路对不对?

使用特权

评论回复
9
sadfasdfare| | 2015-5-14 16:38 | 只看该作者
这个不算bug,除非你用来延时超过46天
因为用的是无符号整形,不存在出现负数情况
1-0xffffffff=2
不会有问题的

使用特权

评论回复
10
yyblike| | 2015-5-15 07:52 | 只看该作者
本帖最后由 yyblike 于 2015-5-15 08:28 编辑
sadfasdfare 发表于 2015-5-14 16:38
这个不算bug,除非你用来延时超过46天
因为用的是无符号整形,不存在出现负数情况
1-0xffffffff=2


看他们都这样说也没有细想,看你这么一说似乎确实没有问题,这个数据类型在这里似乎真没有问题,为了防止意外,我还是计划重写下HAL_InitTick函数为0.1ms中断一次,用4天多的时间运行下看结果。另外以前讨论过一个问题,
unsigned char a = 0;
a = a-1;
if(a == 0xff)
{
printf("aaa");
}
else
{
printf("bbb");
}

结果输出的结果是“bbb”,编译器将a的数据类型提升为了unsigned int类型,结果a-1后的结果是0xffff,不过这里应该不会出现这个问题,32位应该是最大数据宽度了,不存在数据类型提升问题。我在MDK环境下看了下,如你所说。

QQ截图20150515082623.jpg (108.06 KB )

QQ截图20150515082623.jpg

使用特权

评论回复
11
sadfasdfare| | 2015-5-16 21:11 | 只看该作者
yyblike 发表于 2015-5-15 07:52
看他们都这样说也没有细想,看你这么一说似乎确实没有问题,这个数据类型在这里似乎真没有问题,为了防止 ...

我看过u-IP、Linux都是这样用的
没有人去判断过溢出,没必要

就好像计算LRC,有人喜欢弄个32位整数去累计,最后&0x000000ff
我都是直接弄个一个BYTE直接累计,直接就是结果了

使用特权

评论回复
12
yyblike| | 2015-5-17 09:16 | 只看该作者
sadfasdfare 发表于 2015-5-16 21:11
我看过u-IP、Linux都是这样用的
没有人去判断过溢出,没必要

嗯,累加是没有任何问题的,但是有减的时候还是需要注意下,但是在这里确实是没有任何问题的。

使用特权

评论回复
13
fuluoce|  楼主 | 2015-5-27 11:24 | 只看该作者
sadfasdfare 发表于 2015-5-14 16:38
这个不算bug,除非你用来延时超过46天
因为用的是无符号整形,不存在出现负数情况
1-0xffffffff=2

这里不是一直延时46天会出现,而是每46天就出现溢出的状况!和你需要延时多久是没关系的!
下面的算法可以解决问题
#define TIMER_DIFF(END,BEGIN)        ((END - BEGIN + 0xffffffff) % 0xffffffff)//计算时间差
END是当前时间值
BEGIN是记录的时间点
TIMER_DIFF是计算从记录时间点到当前时间的延时

使用特权

评论回复
14
fuluoce|  楼主 | 2015-5-27 11:31 | 只看该作者
sadfasdfare 发表于 2015-5-16 21:11
我看过u-IP、Linux都是这样用的
没有人去判断过溢出,没必要

你看到Linux里应该也有算法的,
下面的算法可以解决问题
#define TIMER_DIFF(END,BEGIN)        ((END - BEGIN + 0xffffffff) % 0xffffffff)//计算时间差

void HAL_Delay(__IO uint32_t Delay)
{
  __IO uint32_t timingdelay;

  timingdelay = uwTick;
  while(TIMER_DIFF(uwTick ,timingdelay) < Delay)
  {;
  }
}

使用特权

评论回复
15
fuluoce|  楼主 | 2015-5-27 11:32 | 只看该作者
下面的算法可以解决问题
#define TIMER_DIFF(END,BEGIN)        ((END - BEGIN + 0xffffffff) % 0xffffffff)//计算时间差

void HAL_Delay(__IO uint32_t Delay)
{
  __IO uint32_t timingdelay;

  timingdelay = uwTick;
  while(TIMER_DIFF(uwTick ,timingdelay) < Delay)
  {;
  }
}

使用特权

评论回复
16
wowow| | 2015-5-27 17:58 | 只看该作者
9楼正确,没有溢出bug。实际应用中谁会去HAL_Delay (50天)? 想延时50天用uint32_t也表示不出来啊。

使用特权

评论回复
17
sadfasdfare| | 2015-5-29 22:48 | 只看该作者
fuluoce 发表于 2015-5-27 11:31
你看到Linux里应该也有算法的,
下面的算法可以解决问题
#define TIMER_DIFF(END,BEGIN)        ((END - BEGIN + ...

你这个define没有任何意义
除非你在用64位的编译环境

使用特权

评论回复
18
WAMCNCN| | 2015-5-30 15:19 | 只看该作者
如何确定中断函数1ms进去一次,那个不是系统滴答的中断函数吗。每来一个系统脉冲,就进入中断一次,系统时钟是9MHz

使用特权

评论回复
19
fuluoce|  楼主 | 2015-6-8 15:20 | 只看该作者
sadfasdfare 发表于 2015-5-29 22:48
你这个define没有任何意义
除非你在用64位的编译环境

这里还是一样的达到目的
如果是32位的单片机  可以把后面的%0xffffffff去掉
64位的单片机  就得这样写

使用特权

评论回复
20
fuluoce|  楼主 | 2015-6-8 15:24 | 只看该作者
WAMCNCN 发表于 2015-5-30 15:19
如何确定中断函数1ms进去一次,那个不是系统滴答的中断函数吗。每来一个系统脉冲,就进入中断一次,系统时 ...

不是每次来一个脉冲就进中断一次,应该是累计脉冲次数,达到设定的值就进一次中断,9Mhz的脉冲,这个设定的值应该是9000

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

37

帖子

0

粉丝