打印
[牛人杂谈]

程序中的“死循环等待”正确吗?

[复制链接]
1474|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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 | 只看该作者
定时等待。超过一定时间就返回,一般都会这么用的。不过没楼主的函数精简。

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

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

                }
                //第二:错误检测
                if(CheckAndShowError() == 1)
                {
                        return 2;
                }
                bsp_DelayMS(1);
                waitforms--;
        }
        return 0;
}

使用特权

评论回复
5
neeringstu| | 2016-5-7 22:33 | 只看该作者
程序中最好不要死循环等待吧,这样多浪费时间

使用特权

评论回复
6
zhuotuzi| | 2016-5-8 20:10 | 只看该作者
neeringstu 发表于 2016-5-7 22:33
程序中最好不要死循环等待吧,这样多浪费时间

对,以前不懂,浪费太多时间了,而且如果一个项目里多个分支如果都这么用,一个出了故障就整体宕机,就耽误大事了。

使用特权

评论回复
7
capturesthe| | 2016-5-9 17:54 | 只看该作者
这个死循环太降低程序的运行效率了,需要改进,引入调度的功能

使用特权

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

本版积分规则

21

主题

236

帖子

4

粉丝