一、前言
关于单片机的开发,无论是C51单片机还是STM32单片机,或者其他类型的单片机。我们开发的第一个项目都是点灯,所以我们先进行点灯入门
单片机的学习最基础就是要会看开发板的原理图和型号的手册说明
这是两个很重要的资料,在蓝桥杯的比赛中,需要完成客观题,有时候客观题就是在这两个资料里面出的,所以笔者建议在学习的时候要经常查看这两个资料。
在这LED灯这个程序学习中,我们暂时不需要看手册,但是需要用到原理图
二、原理图
基本原理
在开发板上,LED灯是L1~L8,在原理图上对于就是这个
![](https://i-blog.csdnimg.cn/blog_migrate/3f6d6f7dbe26f4a0aed0916dcb43827f.png)
可容易看出来,原理图上面的LED灯L1~L8的最右边接了VCC,就是接了电源,我们知道要一个电路形成通路,我们需要有电流,电压,所以很明显在L1~L8的左端需要给低电平,就是Q0~Q7需要给低电平,LED灯才可以接通,LED才可以亮。在图Q0~Q7之前,电路经过了74HC573
74HC573是拥有八路输出的透明锁存器,输出为三态门。当锁存使能端LE为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。当锁存使能变低时,符合建立时间和保持时间的数据会被锁存。
OE,LE的状态不同,产生的效果不同
![](https://i-blog.csdnimg.cn/blog_migrate/63f6c625ff89c9d67d680f0502299034.png)
从74HC573这个图不难看出,OE端口接了GND,所以我们只需要控制LE为高电平,我们输入什么(D1~D7),输出就是什么(Q0~Q7)
在74HC573这个图中LE端口是连接了Y4C,Y4C连接的是74HC138译码器
![74HC138译码器](https://i-blog.csdnimg.cn/blog_migrate/cca84c577b478247204ae4665e437eef.png)
74HC138译码器:三路输入控制八路互斥的低有效输出
三路输入为A0,A1,A2,用二进制控制输入启动
![](https://i-blog.csdnimg.cn/blog_migrate/75b5b2e79104c005bb7597858e39581f.png)
在74HC138译码器原理图上面看出来,我们是只需要控制Y4~Y7即可。
所以我们只需要控制P25,P26,P27就可以控制74HC138译码器。
原理总结
单片机要通过74HC573锁存器控制LED灯,锁存器受74HC138译码器控制,而译码器受P25,P26,P27引脚控制。
三、代码实现功能
1、点亮一个LED灯
#include <STC15F2K60S2.H>
void main()
{
//选择锁存器通道4
P2 = (P2 & 0x1f) | 0x80;
// P2^0 = 0;
// P2^1 = 0;
// P2^2 = 0;
// P2^3 = 0;
// P2^4 = 0;
// P2^5 = 0;
// P2^6 = 0;
// P2^7 = 1;
//L1灯点亮
P0 = ~0x01; //0111 1111
}
(1)配置锁存器通道
通过上面是三路输入的图可以知道,我们要设置锁存器的4通道,需要设置P25=0,P26=0,P27=1三个引脚,我们可以直接写成
P2^5 = 0;
P2^6 = 0;
P2^7 = 1;
但是再后面的程序中我们不只是用到一个锁存器通道,如果每一个都这么配置,一个是我们代码复杂化,难以表达,一个是单片机cpu运行了不必要的数据,大大影响效率。所以我们这里通过与或运算,把关于P2端口配置设置为P2 = (P2 & 0x1f) | 0x80;
& :X(任何数字)& 1(代表真)=1;
|:X(任何数字)| 0(代表假) = 0;
所以不难看出P2 = (P2 & 0x1f) | 0x80相当于
P2^0 = 0;
P2^1 = 0;
P2^2 = 0;
P2^3 = 0;
P2^4 = 0;
P2^5 = 0;
P2^6 = 0;
P2^7 = 1;
这样可以大大减少代码数量。
(2)控制LED灯亮灭
//L1灯点亮
P0 = ~0x01;//1111 1110
在上面提到,我们要L1灯亮,则需要配置P00引脚为低电平,这样电路才可以通,L1灯才可以亮,
所以关于P0引脚的配置是1111 1110(高位在左,低位在右),除了第一位为0,其他都为1。
二进制换成十六进制是每四位二进制数为一个十六进制数的一位,所以1111 1110就是F E。
~:取反 ~0x01 = 0xFE
所以实现点亮一个LED灯,只需要
#include <STC15F2K60S2.H>
void main()
{
P2 = (P2 & 0x1f) | 0x80;
P0 = ~0x01;
}
2、流水灯
#include <STC15F2K60S2.H>
#include <intrins.H>
sbit A0 = P2^5;
sbit A1 = P2^6;
sbit A2 = P2^7;
unsigned char i;
void Delay100ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1)
{
A0 = 0;
A1 = 0;
A2 = 1;
for(i = 0;i < 8;i++)
{
P0 = ~(0x01 << i);
Delay100ms();
}
}
}
这个就是笔者上面提到的直接配置P25=0,P26=0,P27=1三个引脚,也可以这样配置
(1)流水灯形成
流水灯就是相隔的LED灯在一定时间内,依次点亮,L1亮,一段时间后灭,紧接着L2灯亮,L1灯灭,一段时间后,L3灯亮,L2灯灭......所以我们先要设置这个“一段时间”
一段时间就是我们的延时函数,在控制LED,数码管 延时都是不可缺少的。
我们可以在STC-ISP上面配置我们需要的延时函数
在上面一段,我们找到软件延时计算器,通过选择系统频率,定时长度,8051指令集进行函数选择,在8051指令集中,不同单片机型号是不一样的延时,一般选择STC-Y5
这里我们就选择100ms的延时函数,_nop_()是一个空指令函数,在头文件声明一个#include <intrins.H>即可。
(2)LED灯依次点亮
要依次点亮,最简单的方法就是使用循环,我们需要点亮8盏灯,所以就需要使用for(i = 0;i < 8;i++)循环8次,然后在每一盏灯亮灭交替时,我们延时一段时间,就可以实现流水灯。
for(i = 0;i < 8;i++)
{
P0 = ~(0x01 << i);
Delay100ms();
}
使用P2 = (P2 & 0x1f) | 0x80,笔者把这个想法放在这里,给读者提供参考
#include <STC15F2K60S2.H>
#include <intrins.H>
unsigned char i;
void Delay100ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
P2 = (P2 & 0x1f) | 0x80;
while(1)
{
for(i = 0;i < 8;i++)
{
P0 = ~(0x01 << i);
Delay100ms();
}
}
}