在这一节,老师教了4个实验:3-1 独立按键控制LED亮灭
3-2 独立按键控制LED灯状态
3-3 独立按键控制LED显示二进制
3-4 独立按键控制LED移位
如图3-1所示,为独立按键模块的原理图。K1-K4为四个按键,按键右边连接GND(表示电源负极,低电平),按键左边连接P30-P31。要注意的是,单片机开发工程师这里搞错了,按键K1对应的是P31,K2-P30,K3-P32,K4-P33。
图3-1
IO口(输入输出接口):input/output 口,可以通过引脚向CPU里输入数据,CPU也可以通过引脚输出电压信号。单片机通电时候,所有IO口默认高电平,即直接读寄存器值为1。图3-2中,P00-P37这些全是IO接口。
如图3-2所示,我们直接找到独立按键对应的关键部分P30-P33。松开按键,P3相对于GND电位差5V,高电平;按下时,P3和GND导通,同等电位,电位差为0V,低电平。
也就是说,如果按键松开,直接读寄存器,应该是高电平,值为1。如果按键按下,直接读寄存器值应该为0。根据这个特点我们可以检测按键是否被按下。比如P3_1==0,则表示按键K1被按下。
我们向寄存器写一个值,它就会送到IO接口上;寄存器还可以检测IO口电平,然后再读回(1/0)到寄存器中。简单来说,就是寄存器是双向的,它既可以给IO口值,也可以根据IO的状态读回值。展现在按键上效果就是:如果按键松开,IO接口是高电平,寄存器读值为1;如果按键按下,IO接口是低电平,寄存器读值为0。根据这个特点我们可以检测按键是否被按下。
图3-2
按键松开时,金属弹片凸起,开关断开,如图3-3左边第三个图所示。按键按下时,金属弹片变平,开关连接,如图3-3右边第三个图所示。
图3-3
3-1 独立按键控制LED亮灭
按下按键K1亮灯D1,松开按键K1灭灯D1。按键有4个:K1-K4,灯有8个:D1-D8
#include <REGX52.H>
void main()
{
while(1)
{
if(P3_1==0)
P2_0=0;
else
P2_0=1;
}
}
同时按下按键K1和K2亮灯D1,松开按键K1和K2灭灯D1。
#include <REGX52.H>
void main()
{
while(1)
{
if(P3_1==0&&P3_0==0)
P2_0=0;
else
P2_0=1;
}
}
3-2 独立按键控制LED灯状态
按键使得LED长亮功能时,会遇到图3-3中金属弹片抖动的问题,也就是按键抖动。通常我们采用延时的方法,帮助我们度过按键抖动的过程。通俗点说,就是按键如果抖动10ms,我们就延时10ms,,这样我们就感受不到因按键抖动而产生的LED灯的闪烁了。
图3-4
按键消抖,检测松手,才改变LED灯的状态,使按下按键后长亮或长灭。
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
void main()
{
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
P2_0=~P2_0;
}
}
}
图3-5
如图3-5所示,方框1代码为按键消抖的延时代码,这是按键实现LED常亮,必写的代码。第1个Delay(20)是为了消除按键按下时的抖动;第二个Delay(20)是为了消除按键送开始的抖动。按键按下的时候,执行while空循环和P2_1取反操作。
方框2为对灯取反操作,前面说了,单片机通电时候,所有IO口默认高电平,直接读寄存器值为1。因此P2_0默认是1,高电平,D1灯没亮,取反之后变为0,D1灯亮。
注意:按键在按住的时候,灯并没有亮或者灭;而是按完之后,长亮或长灭。这是与第一个实验不同的地方,3-1实验按住按键灯亮,松开按键灯灭。也就是说,3-1实验,按住按键,P2_0直接就等于0,灯亮;松开按键,P2_0直接就等于1,灯灭。但是在3-2实验,想通过按键控制LED常亮或者长灭,按住按键,P2_0没有立刻取反(P2_0没有取反变为0),而是等松开按键的瞬间(也就是退出if 按下按键这个循环后),P2_0直接变成了0或者1。
重点:按键消抖,检测松手,才改变LED灯的状态
3-3 独立按键控制LED显示二进制
实现状态:通过不停的按下按键(按下按键后,灯会常亮,所以说会有按键抖动,需要消抖),使得灯以二进制的方式,不断往上加一,达到用灯来表示按键次数。
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDnum;
void main()
{
while(1)
{
if(P3_1==0) //P3_1±íʾµÚÒ»¸ö°´¼ü
{
Delay(20);
while(P3_1==0);
Delay(20);
LEDnum++;
P2=~LEDnum;
}
}
}
unsigned char LEDnum=0;//unsigned char直接定义8位二进制的数字,刚好符合单片机8位寄存器。
在void main主函数里面写unsigned char LEDnum=0则为局部变量,局部变量必须赋初始值。全局变量则不需要,如果不给初始值,则默认为0。
P2代表的8位二进制数,而P2_0只代表一位二进制数;另外刚开始P2=1111 1111,此时P2为为8位寄存器最大的数,如果继续给P2加1,则会溢出,变为0000 0000。所以我们经常用unsigned char定义变量,因为unsigned char LEDnum,数范围在0-255(1+2+4+8+16+32+64+128)之间,刚好符合8位寄存器,最大值为1111 1111(255),如果LEDnum继续加1,则会溢出,变为0000 0000,符合寄存器的情况。 unsigned char常用来表示寄存器(8位)。
3-4 独立按键控制LED移位
按下K1键,往左边移一位,以LED灯来展示。
//这段代码,按下按键K1,LED第一个灯才会亮
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDnum;
void main()
{
// P2=~(0x01);
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
if(LEDnum>=8)
{
LEDnum=0;
}
P2=~(0x01<<LEDnum);
LEDnum++;
}
}
}
下面这段代码,还没按K1键,LED第一个灯就亮了。
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDnum;
void main()
{
P2=~(0x01);
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
LEDnum++;
if(LEDnum>=8)
{
LEDnum=0;
}
P2=~(0x01<<LEDnum);
}
}
}
按下K1键,往左边移一位;按下K2键,往右边移一位,以LED灯来展示。
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDnum;
void main()
{
P2=~(0x01);
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
LEDnum++;
if(LEDnum>=8)
{
LEDnum=0;
}
P2=~(0x01<<LEDnum);
}
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
if(LEDnum==0)
LEDnum=7;
else
LEDnum--;
P2=~(0x01<<LEDnum);
}
}
}
实现这个功能,我自己写的代码
#include <REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDnum;
void main()
{
P2=~(0x01);
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
LEDnum++;
if(LEDnum>=8)
{
LEDnum=0;
}
P2=~(0x01<<LEDnum);
}
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
if(LEDnum<=0)
LEDnum=8;
LEDnum--;
P2=~(0x01<<LEDnum);
}
}
}
到此,独立按键控制LED灯,已全部写完。