第5章 成为点灯大师
第五章 成为点灯大师
1. 硬件设计
上一章说到,怎么点亮LED灯,很简单啊,就是把P2口设置成低电平就行了。接下来让我们更进一步,完成LED闪烁、流水灯实验
2. 软件设计
2.1 LED闪烁实验
为了使LED闪烁,我们自然而然的想到要使用延时函数,那么就来写一个吧
void delay_us(unsigned int set_us) // 定义函数,函数名:delay_us.参数:set_us
{
while(set_us) // 直到参数0循环停止
}
下面看整体代码:
#include <REGX52.H>
sbit LED1 = P2^0; //将P2.0管脚定义为LED1
void delay_us(unsigned int set_us)
{
while(set_us--);
}
void main()
{
while(1)
{
LED1 = 0; // 低电平点亮
delay_us(50000); //大约延时450ms
LED1 = 1; // 熄灭
delay_us(50000);
}
}
2.2 流水灯实验
所谓流水灯,就是让几个灯逐个点亮、熄灭,这个时候就需要用到for循环和移位操作符,即IO口按顺序输出低电平,如何实现,先看主程序:
void main()
{
unsigned char i;
while(1)
{
for(i = 0; i < 8 ;i++)
{
P2 = ~(0x01 << i); // 0000 0001
delay_us(50000);
}
}
}
那么主函数是怎么完成流水现象的呢?for循环不必解释,循环八次代表八个灯。主要在于P2 = ~(0x01 << i);怎么理解:
0x01
是一个8位的二进制数,其形式是00000001
。左移操作<<
将这个数按位向左移动,移动的位数由循环变量i
决定。- 在循环中,
i
的值从 0 递增到 7。因此,左移操作0x01 << i
将会得到不同位被置位的结果。例如,当i
为 0 时,结果是00000001
,当i
为 1 时,结果是00000010
,以此类推。 ~
运算符是按位取反操作符,它将每个位上的值取反。因此,~(0x01 << i)
将会生成一个具有与左移操作相反的位值的二进制数。- 最后,
P2 = ~(0x01 << i);
将取反后的值写入到P2
寄存器中,控制对应的 LED 灯的亮灭状态。
除了我们自己写函数外,其实KEIL有可以使用的库函数,下面我们用库函数再写一遍:
#include "reg52.h"
#include "intrins.h" // 移位操作需要包含的头文件
void main()
{
unsigned char i;
P2 = 0xFE; // 1111 1110 代表先点亮第一个灯,其他全灭
delay_10us(50000);
while(1)
{
for(i = 0; i < 8 ;i++) //将 led 左移一位
{
P2 = _crol_(P2, 1); // _crol_移位函数,参数(串口,要移动的位数)
delay_us(50000);
}
/*for(i = 0; i < 7 ;i++) //将 led 右移一位
{
P2 = _cror_(P2, 1);
delay_us(50000);
}
*/
}
}
那么,我们就完成成了两个代码的基本编写。注意:以上代码均为片段,还需自己补充延时函数及其他省略的
3.小结
在这一章,我们主要是学会了通过延时函数来使LED闪烁,再通过for循环或者库函数实现流水灯
这里再具体讲解一下流水灯到底是怎么实现的
//初始状态:
LED_PORT=1111 1110
i=0: LED_PORT=1111 1101
i=1: LED_PORT=1111 1011
i=2: LED_PORT=1111 0111
i=3: LED_PORT=1110 1111
i=4: LED_PORT=1101 1111
i=5: LED_PORT=1011 1111
i=6: LED_PORT=0111 1111
i=7: LED_PORT=1111 1110
我们初始就给了P2一个值P2=0xFE(十六进制)转换成二进制-1111 1110(即最低为0,即第一个灯为低电位-也就点亮)
后面我们再不断移位,D2->D3->....如此便完成的流水灯,还是很好理解的
2024.6.24修订,后期不再维护