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

} } 现象分析: 理论 上, 每 执行 1 条 指 令大 概 1 微秒 左右 , 但是 实 际上 , 我们 看 到的 实 验 现象 , 发现 累 计循 环 才 50 00 次, 按理论计算, 应该 产生 0.005 秒左右 的延时才合 理, 但是实际上 居然能产生 类似 0.5 秒的 闪烁效果, 中 间相差 100 倍!为什么 ?C 语言 跟机器指令 之间是存在 翻译的 “中间商”环节 ,一条 C 指令并不代表一 条机 器指令, 往往…

100%1 / 836
81.2.1 灌入式驱动 8 LED
#include "REG52.H"
sbit P0_0=P0^0; //利用 sbit 和符号“^”的组合,把变量名字 P0_0 P0.0 引脚关联起
unsigned long i; //for 循环用的累计变量
//unsigned int i; //如果把 for 循环的变量 i 改成 unsigned int 类型,闪烁的频率会加快。
void main()
{
while(1)
{
//第(1)步
P0_0=0; //LED 灯亮。
//第(2)步
for(i=0;i<5000;i++) //累计的循环次数越大,这里的延时就越长,“亮”持续的时间就越长
{
; //分号代表一条空指令
}
//第(3)步
P0_0=1; //LED 灯灭。
//第(4)步
for(i=0;i<5000;i++) //累计的循环次数越大,这里的延时就越长,“灭”持续的时间就越长
{
; //分号代表一条空指令
}
//第(5)步:这里已经触碰到主循环 while(1)的“底线”,所以接着跳转到第(1)步继续循环
}
}
现象分析:
理论上,执行 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 引脚关联起