实验要求:
使用多个独立按键控制不同LED灯按下点亮,再次按下熄灭LED。
实验思路:
1、独立按键K1-K4控制脚分别接P0.0-P0.3管脚,LED灯D1-D4控制脚分别接P2.7-P2.4管脚
2、宏定义K1-K4按下为:KEY1_PRESS~KEY4_PRESS,无按键按下为:KEY_UNPRESS
3、定义一个延时函数delay_10us,定义一个按键扫描函数key_scan
完整代码:
/**************************** 程序信息 ******************************** * 实验名称:使用多个独立按键控制不同LED点亮与熄灭 * 文件名称:main.c * 版 本:V1.00 * 日 期:2021-12-29 * 编 著:gefon * 说 明:使用普中A7开发版,使用独立按键K1-K4控制D1-D4灯按下点亮/熄灭 ****************************** 声明区 ********************************/ #include "reg52.h" //定义独立按键控制脚 sbit KEY1=P0^0; sbit KEY2=P0^1; sbit KEY3=P0^2; sbit KEY4=P0^3; //定义LED灯控制脚 sbit LED1=P2^7; sbit LED2=P2^6; sbit LED3=P2^5; sbit LED4=P2^4; //重定义系统数据类型 typedef unsigned char U8; typedef unsigned int U16; //宏定义独立按键按下的键值 #define KEY1_PRESS 1 #define KEY2_PRESS 2 #define KEY3_PRESS 3 #define KEY4_PRESS 4 #define KEY_UNPRESS 0 /****************************** 子程序 ******************************** * 函 数 名 :delay_10us * 函数功能 :延时函数,当传入变量ten_us=1时,约延时10us * 输 入 :ten_us * 输 出 :无 ***********************************************************************/ void delay_10us(U16 ten_us) { while(ten_us--); } /****************************** 子程序 ******************************** * 函 数 名 :key_scan * 函数功能 :按键扫描函数 * 输 入 :mode=0时,单次扫描 mode=1时,连接扫描 * 输 出 :KEY1_PRESS:K1按下 KEY2_PRESS:K2按下 KEY3_PRESS:K3按下 KEY4_PRESS:K4按下 KEY_UNPRESS:无按键按下 ***********************************************************************/ U8 key_scan(U8 mode) { static U8 keep=1; if(mode)keep=1; if(keep==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)) { delay_10us(1000); //按键消抖 keep=0; if(KEY1==0) return KEY1_PRESS; //返回K1按下 else if(KEY2==0) return KEY2_PRESS; else if(KEY3==0) return KEY3_PRESS; else if(KEY4==0) return KEY4_PRESS; } else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1) { keep=1; } return KEY_UNPRESS; //返回无按键按下 } /****************************** 主程序 ******************************** * 函 数 名 :main * 函数功能 :主函数 * 输 入 :无 * 输 出 :无 ***********************************************************************/ void main() { U8 key=0; while(1) { key=key_scan(0); if(key==KEY1_PRESS) LED1=!LED1; //点亮和熄灭LED else if(key==KEY2_PRESS) LED2=!LED2; else if(key==KEY3_PRESS) LED3=!LED3; else if(key==KEY4_PRESS) LED4=!LED4; else if(key==KEY_UNPRESS); //无按键按下 } }
实验分析:
实验要求是按下点亮LED,再次按下熄灭LED。按键扫描函数key_scan有一个输入形参mode。
当mode=0时为单次扫描,如果LED赋值为低电平"0",下一次再按下时依然会赋值为"0",这样就无法做到再次按下时熄灭LED。因此这里LED的赋值为取反LED的状态。当按下点亮LED后,再次按下时会取反LED现在的状态,也就可以熄灭LED了。
当mode=1时为连续扫描,程序会对按键进行持续的扫描,这时按下按键LED会不停的闪烁。当你松开按键时,LED会保存最后一次取反的状态,有可能会是"0",也有可能会是"1"。按本实验的思路是不合适的。但可以通过修改按键按下时的LED赋值和修改无按键按下(KEY_UNPRESS)的语句实现:按下时点亮LED,松开时熄灭LED。修改代码如下:
key=key_scan(1); if(key==KEY1_PRESS) LED1=0; //点亮和熄灭LED else if(key==KEY2_PRESS) LED2=0; else if(key==KEY3_PRESS) LED3=0; else if(key==KEY4_PRESS) LED4=0; else if(key==KEY_UNPRESS) //无按键按下 {LED1=1;LED2=1;LED3=1;LED4=0;}
修改以上代码,将按下时LED赋值改为"0",并修改无按键按下(KEY_UNPRESS)时,LED1-LED4都赋值1即可实现按下时点亮LED,松开时熄灭LED。