Dotcpp  >  编程教程  >  独立按键  >  双模式函数封装

双模式函数封装

点击打开在线编译器,边学边练

学了这两种按键模式的代码,我们现在决定将这两种模式封装成一个函数,然后通过参数选择是支持连按还是不支持连按。

 

1.双按键

一直以来我们都是只用一个按键,现在利用两个按键来实现按键模式的切换,K3负责用来给K4做“支持连按”还是“不支持连按”的选择。

双按键                             

开发板的原理图告诉我们,在P2.3输出低电平的情况下,K1,K2,K3,K4就可以当独立按键。

 

2.题目

我们用最左端的数码管5来提示此时的K4是“支持连按”还是“不支持连按”,这个数码管显示0的时候不支持连按,显示1的时候支持连按。

用K3来切换按键模式,K3的按键模式是不支持连按的,按下松开就是把K4切换为另一种按键模式。

然后我们通过按K4,同样右边的3个数码管显示cnt的值,支持连按时,按下不放就一直自动累加,不支持连按时,按下松开才累加1。

 

3.代码

#include <reg52.h> 
sbit ADDR2 = P1^2;
sbit ADDR1 = P1^1;
sbit ADDR0 = P1^0;
sbit ENLED = P1^4;
sbit ADDR3 = P1^3;
  
sbit LED2  = P0^0;
sbit KEY4  = P2^7;
sbit KEY3  = P2^6;
unsigned char code LedChar[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};//数码管状态值初始化
unsigned char LedBuff[6]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};//数码管显示缓存区
unsigned char cnt;//在KEY_task()和SEG_task()里用
  
void SEG_task()//数码管显示函数
{
    static unsigned char i=0;
    LedBuff[0] = LedChar[cnt%10];   
    if(cnt>=10)  LedBuff[1]= LedChar[(cnt/10)%10]; //cnt没到达10之前不更新LedBuff[1]的初始值
    if(cnt>=100) LedBuff[2]= LedChar[(cnt/100)%10];//cnt没到达100之前不更新LedBuff[2]的初始值
    if(cnt==0){  LedBuff[1]=0xFF;LedBuff[2]=0XFF; }//cnt到达255之后再加1就溢出变为0了,这时候要再次熄灭这两个数码管
   
    P0=0xFF;//端口状态全部熄灭数码管里的LED达到刷新作用
    switch(i)
    {
        case 0:
        ADDR2 = 0;ADDR1 = 0;ADDR0 = 0;P0=LedBuff[0];i++;break;
        case 1:
        ADDR2 = 0;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[1];i++;break;     
        case 2:
        ADDR2 = 0;ADDR1 = 1;ADDR0 = 0;P0=LedBuff[2];i++;break;  
        case 3:
        ADDR2 = 1;ADDR1 = 0;ADDR0 = 1;P0=LedBuff[5];i=0;break; 
    }  
}
  
void KEY_task()//按键按下所需要执行的任务
{
    cnt++;
}
  
void KEY_mode(unsigned char mode)
{
    static unsigned char key_up=1;
    static unsigned int times=0; //用来记录进入过按键判断语句的次数 
   
    if(key_up==0)
    {      
        times++;   
        if(mode==1 && times>=1000)//mode等于1,该部分代码是用来实现支持连按的,1000是为了让连按的执行速度没那么快,如果改为500,那么连按速度将会加快
        {
            times=0;
            KEY_task();
        }
    
        else if(mode==0 && times>=500)//mode等于0,该部分代码是用来实现不支持连按的
        {
            if(KEY4==1)//按键已抬起
            {
                times=0;
                KEY_task();  
            }
        }
    }
    key_up=KEY4; //如果不松手,key_up就会等于0 
}
 
void main()
{  
    unsigned char mode=0;//初始时是不支持连按
    unsigned char key_up=1;
    unsigned int times=0;//用来记录进入过按键判断语句的次数
    ADDR3 = 1;//使能三八译码器
    ENLED = 0;// 
   
    P2 = 0xF7;//让K3,K4能具备有被拉低的条件先
    LedBuff[5]=LedChar[mode];//填充好数码管5要显示的按键模式参数
    while(1)
    {     
        SEG_task();    //数码管显示函数
        KEY_mode(mode);//K4的执行函数
    
        //以下是K3按键的功能代码
        if(key_up==0)
        {      
            times++;     
            if(times>=500&&KEY3==1)
            {
                times=0;
                mode=!mode;//每按一次K3就改变参数的传递
                LedBuff[5]=LedChar[mode];//用来显示此时的K4是支持连按还是不支持连按,显示0则不支持,1就是支持
            }
        }
        key_up=KEY3;
    }
}

主函数里的mode充当了两个身份,一个作用是作为参数传给“KEY_mode(mode);”,另一个作用是用来在数码管5上显示0或者1。所有知识点我们都已学过,不过还是希望大家认真地去分析每一处代码的作用。


本文固定URL:https://www.dotcpp.com/course/210

单片机教程
第一章 单片机入门
第二章 LED及入门
第三章 蜂鸣器
第四章 数码管
第五章 独立按键
第六章 多文件编程
第七章 外部中断
第八章 定时器
第九章 舵机与超声波模块
第十章 串口通信
第十一章 1602液晶屏
第十二章 IIC通信
第十三章 红外遥控与温度传感器
第十四章 AD与DA
第十五章 混合例程
第十六章 完结
Dotcpp在线编译      (登录可减少运行等待时间)