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

STM32的HAL库的HAL_Delay问题和UART接受数据问题

[复制链接]
fuluoce 提问时间:2015-1-12 18:35 /
阅读主题, 点击返回1楼
收藏 1 评论30 发布时间:2015-1-12 18:35
30个回答
liudashuang 回答时间:2015-2-11 19:31:33
飞飞ARM 回答时间:2015-5-4 00:49:18
本帖最后由 飞飞ARM 于 2015-5-4 02:03 编辑

似乎是有这问题。其实以前的VB也有这个问题。
MSDN中也明确的提到了:"Retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days."。因此,如果是编写服务器端程序,此处一定要万分注意,避免引起意外的状况。

不过再MCU里连续工作49天那是很正常的。所以还是有一些问题的。

飞飞ARM 回答时间:2015-5-4 00:54:35
本帖最后由 飞飞ARM 于 2015-5-4 02:03 编辑

应该还是有问题的吧。。
在HAL库里,很多都是:if((Timeout == 0) || ((HAL_GetTick() - tickstart ) > Timeout))  这类判断

如果改成:if((Timeout == 0) || (HAL_GetTick() > (tickstart + Timeout))) 就好像没问题了

__weak void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = 0;
  tickstart = HAL_GetTick();
  while(HAL_GetTick() < (tickstart+ Delay))
  {
  }
}

gkcclm 回答时间:2015-5-22 22:42:36
这个bug感觉理论上无法解决。这种定时应该只能通过中断程序来实现(在SysTick_Handler中来处理)。

  1. uint32_t g_delay_request_flag = 0;
  2. uint32_t g_delay_timeout_flag = 0;
  3. uint32_t g_delay_target_tick;

  4. void HAL_Delay(__IO uint32_t Delay)
  5. {
  6.   HAL_SuspendTick();        //先停止定时器,或者禁止中断
  7.   
  8.   g_delay_target_tick = HAL_GetTick() + Delay;
  9.   
  10.   g_delay_timeout_flag = 0;
  11.   
  12.   g_delay_request_flag = 1;
  13.   
  14.   HAL_ResumeTick();
  15.   
  16.   while(!g_delay_timeout_flag)
  17.   {
  18.   }
  19. }

  20. /**
  21. * @brief This function handles System tick timer.
  22. */
  23. void SysTick_Handler(void)
  24. {
  25.   /* USER CODE BEGIN SysTick_IRQn 0 */

  26.   /* USER CODE END SysTick_IRQn 0 */
  27.   HAL_IncTick();
  28.   HAL_SYSTICK_IRQHandler();
  29.   /* USER CODE BEGIN SysTick_IRQn 1 */

  30.   if(g_delay_request_flag && g_delay_target_tick == HAL_GetTick())
  31.   {
  32.         g_delay_request_flag = 0;
  33.        
  34.         g_delay_timeout_flag = 1;
  35.   }
  36.   /* USER CODE END SysTick_IRQn 1 */
  37. }
复制代码
HenryChen 回答时间:2015-7-2 12:16:53
不懂,帮顶
广州星翼-萌主 回答时间:2015-7-2 15:20:54
本帖最后由 广州星翼-萌主 于 2015-7-2 15:22 编辑

uwTick是无符号32位,开机要不断运行49天才会溢出,你要是觉得短的话把uwTick改为u64类型的不就行了,这样就再也不用担心溢出了,至于HAL库中其他地方需要timeout做超时判断的地方,你应该不会设置超时49天吧,所以u32的timeout就可以了。
creep 回答时间:2015-7-2 17:12:20
ST在最新的HAL库里面已经修复了这个bug,新的延时函数如下:
  1. __weak void HAL_Delay(__IO uint32_t Delay)
  2. {
  3.   uint32_t tickstart = 0;
  4.         uwTick = 0xFFFFFFFF;
  5.   tickstart = HAL_GetTick();
  6.   while((HAL_GetTick() - tickstart) < Delay)
  7.   {
  8.   }
  9. }
复制代码
测试如下:

Paderboy 回答时间:2015-7-2 17:30:50
多谢,楼上。
hpdell 回答时间:2016-1-6 10:24:33
fuluoce 发表于 2015-1-30 10:50
而且这bug不好改! 太多的地方调用uint32_t HAL_GetTick(void)函数了,,又不能随便给uwTick;清零 ...

这个问题确实是比较难解决,比较调用共用的太多了,

或者建立一个定时器表,各自都分配一个id,更具不同的定时器id判断各自的定时时间,估计这样会比较好,
jiaozhu88 回答时间:2016-1-9 17:29:05
转自21
一楼的写法的确是有BUG的,并非是溢出问题,假设延时 30ms  0x1E:
void HAL_Delay(__IO uint32_t Delay)
{
   __IO uint32_t timingdelay;

   timingdelay = uwTick + Delay;             //假设此时uwTick=0xFFFFFFF0  Delay=0x1E 则 timingdelay=0x1 0000000E,溢出后保留32位=0x0000000E。
   //while(HAL_GetTick() < timingdelay)
         while(uwTick < timingdelay)          //此时的uwTick仍是0xFFFFFFF0或任何小于0xFFFFFFFF的值,则 if(0xFFFFFFF0<0x0000000E) 为假,立即退出,并没有延时30ms。
   {;
   }
}

正确的写法应该是这样,仍然假设延时 30ms  0x1E:
__weak void HAL_Delay(__IO uint32_t Delay)
{
  uint32_t tickstart = 0;
  tickstart = HAL_GetTick();                         //假设此时uwTick=0xFFFFFFF0  Delay=0x1E 则 tickstart=0xFFFFFFF0。
  while((HAL_GetTick() - tickstart) < Delay)   //此时的uwTick仍是0xFFFFFFF0或任何小于0xFFFFFFFF的值时,假如是0xFFFFFFF5-0xFFFFFFF0=0x05,if(0x05<0x1E)为真,继续等待。
                                                                 //如果溢出后 uwTick=0x0000000D,则0x0000000D-0xFFFFFFF0=0x1D,if(0x1D<0x1E)为真,继续等待。
                                                                 //继续 uwTick=0x0000000E,则0x0000000E-0xFFFFFFF0=0x1E,if(0x1E<0x1E)为假,延时完成,退出。
  {
  }
}

个人感觉这个解答很好,新版本的HAL也确实是按照他说的这个改的。改了后uwTick的溢出对这个延迟函数没有任何影响。但这个uwTick的溢出是否在别的地方有影响还不好说。得看具体情况了。
jiaozhu88 回答时间:2016-1-9 17:31:19
creep 发表于 2015-7-2 17:12
ST在最新的HAL库里面已经修复了这个bug,新的延时函数如下:
测试如下:

这样改了应该不行的吧       每次调用这个延迟函数的时候都改变了uwTick的值,但这个uwTick不光是在这个延迟函数里用的啊   在别的地方还有用到呢   
creep 回答时间:2016-1-11 08:44:53
jiaozhu88 发表于 2016-1-9 17:31
这样改了应该不行的吧       每次调用这个延迟函数的时候都改变了uwTick的值,但这个uwTick不光是在这个 ...

不小心把我测试的代码也添加进去了,应该是下面这样的!
  1. __weak void HAL_Delay(__IO uint32_t Delay)
  2. {
  3.   uint32_t tickstart = 0;
  4.   tickstart = HAL_GetTick();
  5.   while((HAL_GetTick() - tickstart) < Delay)
  6.   {
  7.   }
  8. }
复制代码


党国特派员 回答时间:2016-1-11 09:45:42
不清零,很多地方者阿以使用。
清零了,就只有一个地方可以使用。

权衡一下,还是不要清零的好。。。
潇潇雨歇pku 回答时间:2016-1-11 09:48:47
creep 发表于 2016-1-11 08:44
不小心把我测试的代码也添加进去了,应该是下面这样的!

改成这样确实不会有问题了!
潇潇雨歇pku 回答时间:2016-1-11 09:50:34
jiaozhu88 发表于 2016-1-9 17:29
转自21
一楼的写法的确是有BUG的,并非是溢出问题,假设延时 30ms  0x1E:
void HAL_Delay(__IO uint32_t D ...

这个讲解很耐心

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版