新手疑问:51延时函数为何要递减xms参数?

新手上路,请多包涵

void Delay1ms(unsigned int xms) //@11.0592MHz
{

unsigned char data i, j;
while(xms)
{
    _nop_();
    i = 2;
    j = 199;
    do
    {
        while (--j);
    } while (--i);
    xms--;
}

}
我是一名新手小白,正在学习51,这是一段延时代码,我有一个疑问,明明有了while循环了,为什么要在后面加xms--,按我的理解,每次循环后减1,最后不是会跳出循环了吗?
我不知道我的理解有没有问题?所有想请教大佬们给我解惑一番,感谢!!!

我想知道我的想法是正确的还是错误的,并且想弄明白为什么要添加递减。

阅读 709
1 个回答
新手上路,请多包涵

你的理解不完全正确。while(xms) 只是 “检查 xms 是否非 0”,不会改变 xms 的值。xms-- 是必须的。它把外层循环变成 “执行 xms 次后退出” 的计数器。没有 xms-- 就会死循环。

要点说明:

while(xms) 等价于 while(xms != 0)。它只是条件判断,不做自减。

xms-- 把 xms 每次减 1。这样外层循环会在 xms 次迭代后变为 0,循环才结束。

内层的 i 和 j 那些循环负责产生约 1ms 的延时。外层每迭代一次就是 ~1ms,所以外层要循环 xms 次以产生 xms 毫秒延时。

如果把 xms-- 去掉,xms 永远不变,while(xms) 永远为真(只要初值非 0),循环永不结束。

更清晰的写法(等价):

void Delay1ms(unsigned int xms)
{

unsigned char i, j;
while (xms--)    // post-decrement:先判断原值是否非0,再把它减1
{
    _nop_();
    i = 2;
    j = 199;
    do {
        while (--j);
    } while (--i);
}

}

或者用 for:

for (; xms; xms--) { / 延时体 / }

注意事项:

while(xms--) 用的是后缀自减。它在判断后再减,初值为 1 时会执行一次。不要在循环体里又额外再对 xms 做减操作,否则会多减。

若要在调试或对抗优化时保证延时循环不被编译器优化掉,建议把循环变量声明为 volatile(例如 volatile unsigned char i, j;)。

data 是 51 编译器的内存区说明符(Keil),用法没问题。

结论:外层的 xms-- 正是为了计次退出。你的直觉 “减到最后跳出循环” 是对的,但要理解那正是设计目的。如果不想显式减 xms,可以用 while(xms--) 或 for 的形式,但必须有某种自减来让循环终止。

宣传栏