从单片机基础到程序框架(全集 2019pdf版).pdf - 第355页

第八十二节: Delay“阻塞”延时控制 LED 闪烁。 【82.1 “阻塞”与“非阻塞” 。 】 做项 目写程 序, 大框 架大思 路上 就是 在“阻 塞” 与“ 非阻 塞”这 两种 模式下 不断 切换。 “阻塞 ”可 以理 解成“单任务处理”模式, “非阻塞”可以理解成“多任务并行处理”模式。 “阻塞 ”的优点是它全神贯注不 分心地专注 于当下这一 件事, 它等待某个 事件的响应 速度是 最快的,同时省去了 “来回切换 、 反复扫描…

100%1 / 836
}
}
现象分析:
理论上,执行 1 令大 1 微秒左右但是际上我们到的现象发现计循 5000
次,按理论计算,应该产生 0.005 秒左右的延时才合理,但是实际上居然能产生类似 0.5 秒的闪烁效果,
间相差 100 倍!为什么?C 语言跟机器指令之间是存在翻译的“中间商”环节,一条 C 指令并不代表一条机
器指令,往往一条 C 指令翻译后产生 N 条机器指令比如上面的代码用到 for 循环变量 i用的 unsigned
long 变量,意味着 4 个字节,即使一条 C 语言赋值指令估计可能也要消耗 4 条单周期指令,在加上 for 循环
的判断指令,和累加指令,以及跳转指令,所以我们看到的 for(i=0;i<5000;i++)并不代表是真正仅仅执
5000 个指令周期而是有可能执行了 500000 条指令周期!假如我们把上述代码中的 i 改成 unsigned int
变量(2 字节),是会看到闪烁的速度明显加快的,其中原因就是 C 编译器与机器指令之间存在翻译后的“1
N”的关系。
第八十二节: Delay“阻塞”延时控制 LED 闪烁。
【82.1 “阻塞”与“非阻塞”
做项目写程序,大框架大思路上就是在“阻塞”与“非阻塞”这两种模式下不断切换。“阻塞”可以理
解成“单任务处理”模式,“非阻塞”可以理解成“多任务并行处理”模式。“阻塞”的优点是它全神贯注不
分心地专注于当下这一件事,它等待某个事件的响应速度是最快的,同时省去了“来回切换反复扫描
额外开销,而且在编程思路上不用太费脑力只需“记流水账式”的编程即可,但是它的缺点是当下只能干一
件事,其它事情无法兼顾,做不到多任务并行处理。而非阻塞”恰恰相反,它的有优点就是“阻塞”的缺
点,它的缺点就是“阻塞”的优点,对于“非阻塞”本节暂时不多讲。在实际项目中,有时候“ 阻塞”
中分支了 N 个“小 非阻塞”,也有时候“大 非阻塞”中分支了 N 个“小 阻塞”。能在“阻塞”与“非阻塞”
之间运用自如者,谓之神
“阻塞等待”是指单片机在某个死循环里比如“while(1)”这类)一直不断循环地在等待某个标志变
量的状态,如果这个标志变量满足条件才会跳出这个死循环然后才能干其它的事情,否则一直在死循环里死
等,给人一种全神贯注心无旁骛的感觉
“阻塞延时”是指单片机在产生“延时时间”的时候做不了别的事,延时多久它就要被“阻塞”多久,
只有延时过后它才能解脱去干别的事。比如,在编程上,常用 for 循环产生 N 个空指令来达到产“延时时
间”的目的,这种编程方式就是最常见的“阻塞延时”
【82.2 Delay 阻塞延时的一个例子。
现在利用“Delay 阻塞延时”编写一个练习程序,让一个 LED 灯闪烁。例子如下:
82.2.1 灌入式驱动 8 LED
#include "REG52.H"
void Delay(unsigned long u32DelayTime); //函数的声明
sbit P0_0=P0^0; //利用 sbit 和符号“^”的组合,把变量名字 P0_0 P0.0 引脚关联起
void Delay(unsigned long u32DelayTime) //产生“阻塞延时”的延时函数
{
static unsigned long i; //函数在频繁调用时,加 static 可以省去一条额外的初始化语句的开销
for(i=0;i<u32DelayTime;i++);
}
void main()
{
while(1)
{
//第(1)步
P0_0=0; //LED 灯亮。
//第(2)步
Delay(5000); //这里就是阻塞延时,时间就越长,“亮”持续的时间就越长
//第(3)步
P0_0=1; //LED 灯灭。
//第(4)步
Delay(5000); //这里就是阻塞延时,时间就越长,“灭”持续的时间就越长
//第(5)步:这里已经触碰到主循环 while(1)的“底线”,所以接着跳转到第(1)步继续循环
}
}
【82.3 累加型和累减型的两种 Delay 函数,哪家强?】
上述 82.2 例子中,用到一个 Delay 函数,该函数内部的 for 循环用的是“累加型”的,比如:
void Delay(unsigned long u32DelayTime)
{
static unsigned long i; //“累加型”函数内部多开销了一个变量 i。
for(i=0;i<u32DelayTime;i++); //因为这里的“i++”是加法运算,所以称为“累加型”
}
现在在跟大家分享一种“累减型”的 Delay 函数,例子如下:
void Delay(unsigned long u32DelayTime)
{
//“累减型”函数内部节省了一个变量 i
for(;u32DelayTime>0;u32DelayTime--); //“u32DelayTime--”意味着“累减型”
}
仔细对比“累加型”和“累减型,会发现在实现同样“阻塞延时”的功能下,因为“累减型”巧妙