历史上的今天
今天是:2025年08月20日(星期三)
2021年08月20日 | 51单片机-双模式函数封装
2021-08-20 来源:eefocus
学了这两种按键模式的代码,我们现在决定将这两种模式封装成一个函数,然后通过参数选择是支持连按还是不支持连按。
1.双按键
一直以来我们都是只用一个按键,现在利用两个按键来实现按键模式的切换,K3负责用来给K4做“支持连按”还是“不支持连按”的选择。
开发板的原理图告诉我们,在P2.3输出低电平的情况下,K1,K2,K3,K4就可以当独立按键。
2.题目
我们用最左端的数码管5来提示此时的K4是“支持连按”还是“不支持连按”,这个数码管显示0的时候不支持连按,显示1的时候支持连按。
用K3来切换按键模式,K3的按键模式是不支持连按的,按下松开就是把K4切换为另一种按键模式。
然后我们通过按K4,同样右边的3个数码管显示cnt的值,支持连按时,按下不放就一直自动累加,不支持连按时,按下松开才累加1。
3.代码
#include 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。所有知识点我们都已学过,不过还是希望大家认真地去分析每一处代码的作用。
上一篇:51单片机-代码对比
下一篇:51单片机-综合例程
史海拾趣
|
是不是校准了就可以不测量VREFINT 来自EEWORLD合作群:arm linux fpga 嵌入0(49900581)群主:wangkj… 查看全部问答> |
|
我的WINCE设备现在已经可以识别为U盘. 还有个问题,当我把USB线插上的时候,WINCE上NAND FLASH的盘符消失,同时PC上显示U盘盘符;但是当我拔掉USB线时,PC上的盘符消失,而WINCE上的盘符却没有显示出来,怎么让FLASH重新MOUNT一次?这个问题怎么解决啊?… 查看全部问答> |
|
问题是这样的: vxWorks下,我用routeAdd \"0.0.0.0\",\"192.168.1.1\"添加了一条路由,但是用routeDelete \"0.0.0.0\",\"192.168.1.1\"删除不掉。其实我是想修改网关的地址(先删再重新加),但是现在删不掉先前设置的。 请各位大大帮帮忙! … 查看全部问答> |
|
在使用s3c44b0的时候,看到有这么一条语句 rNCACHBE0=(((Non_Cache_End)>>12)12); 为什么这样就可以设置非cache区的起始和结束地址了? 另外为什么要写成((Non_Cache_End)>>12)… 查看全部问答> |
|
假如创建一个pty: ptyDevCreate(\"/pty/my.\", 512, 512);那么得到的主从设备依次为:\"/pty/my.M\"以及\"/pty/my.S\"。按照VxWorks的帮助是这么说的:主进程使用\"/pty/my.M\"进行写,从进程使用\"/pty/my.S\"进行读,按照,这样理解这个pty是单 ...… 查看全部问答> |
|
一个朋友最近送给我的一套【全美经典】系列教材,看了一点,感觉还可以,所以传上来给大家分享一下,全部免费下载,需要的朋友可以看一下。 [ 本帖最后由 fengxin 于 2010-10-23 11:49 编辑 ]… 查看全部问答> |
|
1、(定位)我们在开发一款路灯的时候,得先要有个定位(开发灯具条件表,如对灯具的大致结构,,电性能指标,发率,防护性能,期望重量等),目前,很多人对及系统了解得不够深入,知其然不知其所以然的。 目前国内LED道路照明标准尚正式出台,由 ...… 查看全部问答> |
|
今天遇到asm(\"pop.w R3\")报错 pop.w R2没报错 想问一下, 1.我们的程序里能用到那些寄存器? 2.那些寄存器是我们可以操作的? 3.移植OS需要操作R0到R15吗? 4。为什么msp430需要常数发生器? 5.常数发生器作用过程是怎样 ...… 查看全部问答> |




