今天来介绍另一个外设——按键与LED的配合工作,与开关不同,按键需要注意消除抖动带来的影响,代码逻辑也会更复杂一写,下面先为大家介绍独立式键盘的相关知识。
单片机的独立式键盘指的是一种不依赖于计算机或其他外部设备的键盘输入方式,由若干按键按照一定的规则组成,每一个按键实质就是一个按钮开关。而独立式键盘的各键相互独立,每个按键各接一条I/O口线,通过检测I/O输入线的电平状态,很容易地判断哪个按键被按下。
#include <reg52.h>
void delay10ms(void) //延时消抖程序,第三种delay,数量级为5~10k
{
unsigned char i,j;
for(i=40;i>0;i--)
for(j=250;j>0;j--);
}
void main()
{
unsigned char x;
P1=0xff; //led全灭
x=0;
while(1)
{
while(x==0) //无键被按下执行死循环,有键被按下才往下走
{x=P0; //第一次进入循环给x赋值,没有异常再取反恢复原值
x=~x;}
delay10ms(); //消抖
x=P0; //再次读键盘状态
x=~x;
if(x==0) continue;//如果无键按下则认为是按键抖动,重新扫描键盘
switch(x) //根据键值点亮对应的发光二极管
{
case 0x01: P1=0xfe; break; //点亮第一个发光二极管
case 0x02: P1=0xfd; break; //点亮第二个发光二极管
case 0x04: P1=0xfb; break; //点亮第三个发光二极管
case 0x08: P1=0xf7; break; //点亮第四个发光二极管
case 0x10: P1=0xef; break; //点亮第五个发光二极管
case 0x20: P1=0xdf; break; //点亮第六个发光二极管
case 0x40: P1=0xbf; break; //点亮第七个发光二极管
case 0x80: P1=0x7f; break; //点亮第八个发光二极管
default: break;
}
}
}
#include<reg52.h>
sbit S1=P1^0; //将S1位定义为P1.0引脚
sbit S2=P1^1; //将S2位定义为P1.1引脚
sbit S3=P1^2; //将S3位定义为P1.2引脚
sbit S4=P1^3; //将S4位定义为P1.3引脚
unsigned char keyval; //定义键值储存变量单元
void led_delay(void);//第一种延时函数,流水灯延时
void delay10ms(void);//按键消抖
void key_scan(void) ;//键盘扫描
void ledstate(); //switch封装,也可以写在主函数中
//void key(void);
//灯的四种变化
void forward(void); //从上至下
void backward(void);//从下至上
void Alter(void); //高四位与低四位互闪
void blink (void); //全闪
void main(void)
{
keyval=0; //键值初始化为0
while(1)
{ //key();
key_scan(); //调用键盘扫描函数
ledstate(); //调用灯光执行程序
}
}
void key_scan(void) //函数功能:键盘扫描
{
P1=0xff;
if((P1&0x0f)!=0x0f) //检测到有键按下
{
delay10ms(); //延时10ms再去检测
if(S1==0) keyval=1; //按键k1被按下
if(S2==0) keyval=2; //按键k2被按下
if(S3==0) keyval=3; //按键k3被按下
if(S4==0) keyval=4; //按键k4被按下
}
}
void forward(void) //函数功能:正向流水点亮LED
{
P3=0xfe; led_delay(); //LED0亮
P3=0xfd; led_delay(); //LED1亮
P3=0xfb; led_delay(); //LED2亮
P3=0xf7; led_delay(); //LED3亮
P3=0xef; led_delay(); //LED4亮
P3=0xdf; led_delay(); //LED5亮
P3=0xbf; led_delay(); //LED6亮
P3=0x7f; led_delay(); //LED7亮
}
void backward(void) //函数:反向流水点亮LED
{
P3=0x7f; led_delay(); //LED7亮
P3=0xbf; led_delay(); //LED6亮
P3=0xdf; led_delay(); //LED5亮
P3=0xef; led_delay(); //LED4亮
P3=0xf7; led_delay(); //LED3亮
P3=0xfb; led_delay(); //LED2亮
P3=0xfd; led_delay(); //LED1亮
P3=0xfe; led_delay(); //LED0亮
}
void Alter(void) //函数:交替点亮高4位与低4位LED
{
P3=0x0f;
led_delay();
P3=0xf0;
led_delay();
}
void blink (void) //函数:闪烁点亮LED
{
P3=0xff;
led_delay();
P3=0x00;
led_delay();
}
void led_delay(void) //函数:延时
{
unsigned char i,j;
for(i=0;i<220;i++)
for(j=0;j<220;j++)
;
}
void delay10ms(void) //函数:软件消抖延时10ms
{
unsigned char i,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
void ledstate()
{
switch(keyval)
{
case 1:forward(); //键值为1,调用正向流水点亮函数
break;
case 2:backward(); //键值为2,调用反向流水点亮函数
break;
case 3:Alter(); //键值为3,调用高、低4位交替点亮函数
break;
case 4:blink (); //键值为4,调用闪烁点亮函数
break;
}
}
//键盘扫描和灯光操作可以合并为一个函数,还能省下sbit命名
/*void key(void)
{
P1=0xff;
if((P1&0x0f)!=0x0f)
{delay10ms();
switch(~(P1&0x0f))
{case 0xf1:forward(); //键值为1,调用正向流水点亮函数
break;
case 0xf2:backward(); //键值为2,调用反向流水点亮函数
break;
case 0xf4:Alter(); //键值为3,调用高、低4位交替点亮函数
break;
case 0xf8:blink (); //键值为4,调用闪烁点亮函数
break; }
}
} */
?这里给大家展示了两个程序,第一个实例就是先检测按键的状态,然后用switch语句判断哪个键被按下,之后执行相应的点亮程序。第二个实例是把之前学过的LED点亮状态都封装成函数,然后在主程序里根据键盘的值执行相应的操作。
有两点需要注意
按键控制LED点亮
下面是多功能按键控制LED的案例,与前文不同,该案例是通过记录按键按下的次数来改变LED状态的。,在这种情况下,就需要考虑按住按键不松手的情况,以免一直进行灯光切换。
#include <reg52.h>
sbit key=P3^0;
unsigned char ID;
void delay10ms(void)
{
unsigned char i,j;
for(i=20;i>0;i--)
for(j=248;j>0;j--);
}
void keyonoff()
{
if(key==0) //检测按键被按下
{
delay10ms(); //去抖
if(key==0)
{
ID++;
while(key==0); //防止按住不松手,等待按键释放
if(ID==4)
{
ID=0;
}
}
}
}
void displayled()
{
switch(ID)
{
case 0: P1=0x0e;break; //点亮D1,熄灭其它LED
case 1: P1=0x0d;break; //点亮D2,熄灭其它LED
case 2: P1=0x0b;break; //点亮D3,熄灭其它LED
case 3: P1=0x07;break; //点亮D4,熄灭其它LED
} //end switch
}
void main(void)
{ P1=0x0f;
while(1)
{
//按键识别程序
keyonoff();
//根据按键结果,输出程序
displayled();
}
}
这个模式在没有按键被按下的情况下点亮第一个LED作为标志,大家也可以自行更改case的值设置双击或全灭等操作,或者把前文封装的函数放在switch里执行更多的功能。
多功能按键控制LED点亮
?以上就是按键控制LED灯点亮的过程,之后会介绍按键控制数码管显示的案例。谢谢大家。