[牛人杂谈] 程序中的“死循环等待”正确吗?

[复制链接]
 楼主| Thethree 发表于 2016-5-5 22:20 | 显示全部楼层 |阅读模式
在单片机程序中,有时候会需要“死循环等待”,也就是等到某一条件我们才需要执行下面的操作。这里以温度传感器DS18B20为例,主机首先需要发送一个存在检测脉冲,如果DS18B20存在,则它会以60us至240us的电平来回应主机,这里就会需要一个“死循环等待”,我们必须等到DS18B20“回应完成”,这时候主机才能继续发送指令到DS18B20中去,这时候很多人会采用这样的方式:(首先假设sbit ds18b20_io_bit = P3^7 ;)
则,while( !ds18b20_io_bit) ;
这样的代码其实是有问题的,在未连接DS18B20或者接触不良时,DS18B20并不能回应主机,这样的代码就会有问题,尤其在大工程中,所以,为了安全,我通常的做法是:
第一步:
while( (!ds18b20_io_bit) ;
P1=0x01 ; //led
如果,P1口的led有变化,则表示我们“程序在逻辑上和时序上没有问题”
第二步:
将上面的代码修改为:
unsigned long i=0
while( ( (!ds18b20_io_bit) && (i++)) ;
然后打印 i ,
因为i一般都很小,所以这时候我一般将unsigned long 修改为unsigned char 类型,然后最后修改为这样
while( (!ds18b20_io_bit)&& (i++ <250)) ;
注意这里的250不是随意写的,是经过测试的,经过测试,我读出的i值远小于250,我才这样做的,如果在其他类似的地方,打印出来i是其他较大的值,那就重新定义i的类型为unsigned int 或者unsigned long ,根据具体情况而定。

上面的修改似乎意义不大,但是在大工程中,这样不会因为DS18B20的“不存在”而导致整个程序“死循环等待”。

天灵灵地灵灵 发表于 2016-5-6 22:47 | 显示全部楼层
恩,很好,这样可以防止卡死,楼主这一招真是太考虑全面了。
玛尼玛尼哄 发表于 2016-5-7 12:16 | 显示全部楼层
楼主的方法太好了,的确是这个样子的,以前做了个东西要等待初始化完成,结果一个设备断线后就卡那没法往后面操作了。
落叶行健ywm 发表于 2016-5-7 15:07 | 显示全部楼层
定时等待。超过一定时间就返回,一般都会这么用的。不过没楼主的函数精简。

  1. //发送后,等待接受流程
  2. //第一步:发送后,设置接受标志为0;将三个判断条件进行设置,分别是功能码;目标地址;操作动作。
  3. //第二步:然后等待接受,当标志条件为1时,说明ok。等待时间为一定值
  4. //第三步:在接受函数里进行三个条件的判断和标志设置转换。

  5. //返回值:正常==0   有故障==2  超时没有直接死机,需要重启
  6. u8 WaitForRecvOK(u16 waitms)//至少20ms
  7. {
  8.         u16 waitforms = waitms;
  9.         while(1)
  10.         {
  11.                 if(errordata.Is_RevcOK == 1)
  12.                 {
  13.                         break;
  14.                 }
  15.                 if(waitforms <= 1)//超过等待时间了,判定没有接收到
  16.                 {
  17.                         //超时报错
  18.                         //直接无限循环报错,不能再进行
  19.                         OLED_StartDraw();
  20.                         OLED_ClrScr(0x0);
  21.                         Lcd_Decimal_Small((((errordata.TargertUnit & 0xe0) >> 5) * 100 + (errordata.TargertUnit & 0x1f)),7+12*1+3*1,10,1,3);
  22.                         Lcd_HZ_1212_GZXS(UISTR_HZ_DYMM, 1, 2, 2);//单元
  23.                         Lcd_HZ_1212_GZXS(UISTR_HZ_CQZTX+3, 1, 2+2, 2);//通讯
  24.                         Lcd_HZ_1212_GZXS(UISTR_HZ_JDQGZ+3, 1, 2+4, 2);//故障
  25.                         OLED_EndDraw();
  26.                         while(1)
  27.                         {
  28.                                 ;
  29.                         }

  30.                 }
  31.                 //第二:错误检测
  32.                 if(CheckAndShowError() == 1)
  33.                 {
  34.                         return 2;
  35.                 }
  36.                 bsp_DelayMS(1);
  37.                 waitforms--;
  38.         }
  39.         return 0;
  40. }
neeringstu 发表于 2016-5-7 22:33 | 显示全部楼层
程序中最好不要死循环等待吧,这样多浪费时间
zhuotuzi 发表于 2016-5-8 20:10 | 显示全部楼层
neeringstu 发表于 2016-5-7 22:33
程序中最好不要死循环等待吧,这样多浪费时间

对,以前不懂,浪费太多时间了,而且如果一个项目里多个分支如果都这么用,一个出了故障就整体宕机,就耽误大事了。
capturesthe 发表于 2016-5-9 17:54 | 显示全部楼层
这个死循环太降低程序的运行效率了,需要改进,引入调度的功能
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

236

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部