×

51单片机笔记 51单片机学习纪实

51单片机学习纪实:5.2-使用多个独立按键控制不同LED点亮/熄灭_【增强实验1】

一哥 一哥 发表于2021-12-30 19:29:34 浏览1332 评论0

抢沙发发表评论

实验要求:

使用多个独立按键控制不同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。

少长咸集

群贤毕至

访客