滚印车间
您当前的位置:贴片加工 > 基础知识

C语言编写的矩阵键盘程序为什么第一列的达成条件和后面三列不一样?

时间:2023-04-17 06:02:01  来源:  浏览量:

本帖最后由 程鹏_3 于 2020-2-16 13:53 编辑 前序:1.蓝桥杯相关。

2.上网查询了好几天,自己模仿写出来的矩阵键盘程序。

3.出现了和我想象中不一样的结果,原本第一列按键是无法按的,按照正确的代码(即“0x07fff”类型),后来我算错了,改成了“0x07777”类型,没想到居然可以实现!但是,后来又仔细思考了一下,发现我之前的算的结果错了。

想了蛮久,,,,没想出为什么错误的代码可以得出正确的结果,,,于是发帖求助。

说明:1.有原理图,原理图已上传,完整文件也已上传。

2.代码中有更为详细的说明。

3.num=0~num=3为第一列,num=4~num=7为第二列,num=8~num=11为第三列,num=12~num=15为第四列。

矩阵键盘扫描代码如下://实验效果:依次按下S7~S19,倒数第四个数码管会依次显示0~F。

//不足:所有按键在按下时那一刹那都会出现消隐的情况,若长按,数码管一直保持消隐状态,直至松手。

#include#include#includevoid Delay5ms();void Delay10us();unsigned char smg_Pxdata[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//数码管片选数据,共有八片,为共阳极数码管。

unsigned char smg_Dxdata[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//数码管段选数据,依次为0~f。

int buzz();int smg(tem);int button();unsigned char num;//全局变量,使用于按键函数和数码管显示函数中。

int main(){ while(1) { buzz(); button(); smg(num); } return 0;}int buzz(){ XBYTE[0xA000]=0;//关闭蜂鸣器。

return 0;}int smg(tem)//数码管显示程序,和按键函数结合使用,用于判断按下哪个键。

{ XBYTE[0xC000]=0;//片选信号——消隐。

Delay10us(); XBYTE[0xE000]=smg_Dxdata[tem];//段选信号。

XBYTE[0XC000]=smg_Pxdata[3];//片选信号——始终显示一片数码管。

Delay10us(); return 0;}int button()//P3.0~P3.3为行线,P3.4、P3.5、P4.2、P4.4为列线。

{ unsigned int key; P44=0,P42=1,P3=0x7f;//所有8个端口中,只令1个端口为低电平,若1个按键按下,那么肯定有另外1个端口会被拉低。

因此,通过扫描就可以知道是哪个按键按下了。

key=P3&0x0f;//和0x0f相与,让高四位在任何情况下始终为0000,也就是让case后的值始终是0x0****形式。

P44=1,P42=0,P3=0xbf; key=(key<<4)|(P3&0x0f);//为保留上一行扫描的数据,故将数据左移4位。

此处“P3&0x0f”是为了将高四位清0,进而再进行位运算时不会清除之前的数据。

P44=1,P42=1,P3=0xdf; key=(key<<4)|(P3&0x0f); P44=1,P42=1,P3=0xef; key=(key<<4)|(P3&0x0f); if(((key&0x0f000)!=0x0f000)|((key&0x00f00)!=0x00f00)|((key&0x000f0)!=0x000f0)|((key&0x0000f)!=0x0000f))//通过位运算,提取出按下不同按键时各自独有的数据部分,并加以判断。

{ Delay5ms();//第一次消抖开始:消除按键前沿抖动,即按下抖动。

P44=0,P42=1,P3=0x7f; key=P3&0x0f; P44=1,P42=0,P3=0xbf; key=(key<<4)|(P3&0x0f); P44=1,P42=1,P3=0xdf; key=(key<<4)|(P3&0x0f); P44=1,P42=1,P3=0xef; key=(key<<4)|(P3&0x0f); if(((key&0x0f000)!=0x0f000)|((key&0x00f00)!=0x00f00)|((key&0x000f0)!=0x000f0)|((key&0x0000f)!=0x0000f)) { P44=0,P42=1,P3=0x7f; key=P3&0x0f; P44=1,P42=0,P3=0xbf; key=(key<<4)|(P3&0x0f); P44=1,P42=1,P3=0xdf; key=(key<<4)|(P3&0x0f); P44=1,P42=1,P3=0xef; key=(key<<4)|(P3&0x0f);//第一次消抖结束。

switch(key)//开始判断key的值,并依此赋予num不同的值,然后将值传递给数码管显示函数。

{ case 0x0fffe:num=15;break; case 0x0fffd:num=14;break; case 0x0fffb:num=13;break; case 0x0fff7:num=12;break; case 0x0ffef:num=11;break; case 0x0ffdf:num=10;break; case 0x0ffbf:num=9;break; case 0x0ff7f:num=8;break; case 0x0feff:num=7;break; case 0x0fdff:num=6;break; case 0x0fbff:num=5;break; case 0x0f7ff:num=4;break; case 0x0eeee:num=3;break;//正确的代码应该是0x0efff 。

case 0x0dddd:num=2;break;//正确的代码应该是0x0dfff。

case 0x0bbbb:num=1;break; //正确的代码应该是0x0bfff。

case 0x07777:num=0;break;//正确的代码应该是0x07fff 。

default://倘若有的按键按下没有达到预期效果,根据这个来判断key的值是否正确。

{ XBYTE[0x8000]=0xf5;//LED灯亮。

Delay5ms(); XBYTE[0x8000]=0xff;//LED灯灭。

} } while (((key&0x0f000)!=0x0f000)|((key&0x00f00)!=0x00f00)|((key&0x000f0)!=0x000f0)|((key&0x0000f)!=0x0000f))//第二次消抖开始:消除后沿抖动,即松手抖动。

{ P44=0,P42=1,P3=0x7f; key=P3&0x0f; P44=1,P42=0,P3=0xbf; key=(key<<4)|(P3&0x0f); P44=1,P42=1,P3=0xdf; key=(key<<4)|(P3&0x0f); P44=1,P42=1,P3=0xef; key=(key<<4)|(P3&0x0f); }//第二次消抖结束。

} } return 0;} void Delay5ms() //单片机内部晶振频率@11.0592MHz{ unsigned char i, j; i = 54; j = 199; do { while (--j); } while (--i);}void Delay10us() //单片机内部晶振频率@11.0592MHz{ unsigned char i; _nop_(); i = 25; while (--i);}
卧槽!!!解决了!!!原因是因为我J5短接帽接到独立键盘那里去了!!!!!刚刚调试单片机的时候无意中看到了!!卧槽!!!!!!我TM可是想了一天没想出来为什么!!!!!!卧槽!!!!!!!!!!!!!!!!!!!!!!!!!!!!!这个代码是没啥问题的。

这个代码与网上大部分代码不一样的是,这个代码加了去抖动部分。

大家只要把第一列的代码改成正确的代码,弄好短接帽,就可以正常运行了!这个帖子就供大家参考吧。


给你写了一个异组非顺序端口4*4矩阵按键示例,完全可以移植到你的程序中,可以消除按键干扰数码管显示,并大幅简化代码。

仿真没有P4,用P2代替。

#include #define uint unsigned int#define uchar unsigned char#define PD ((P2<<3&0x80)|(P2<<4&0x40)|(P3&0x3f))//P4.4/P4.2sbit dula=P2^6; //573段选sbit wela=P2^7; //573位选uchar code table[]={ //数组 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71};uchar data dis_buf[2];uchar key=0;bit wei=0;void PX(uchar x){ P3&=0xc0; //低6位清0,P36、37不变 P3|=(x&0x3f); //P3低6位赋值 P2&=0xeb; //P44、42清0,其它位不变 P2|=((x>>3&0x10)|(x>>4&0x04));//P44、42赋值}void keyscan() //按键扫描程序{ static bit sign=0; //按键自锁标志 static uint count=0; //消抖计数变量 uchar num=0; //临时变量 PX(0xf0); //赋值PX 1111 0000 if(PD!=0xf0) //检测有按键按下 { if((++count>=100)&&(sign==0)) //100~1000,根据主循环周期调整约10~20ms { sign=1; //按键自锁标志置1 num=PD; //保存PD值xxxx 0000,x为0或1 num|=0x0f; //保存num按位或0x0f值xxxx 1111 PX(num); //赋值PX xxxx 1111 num=PD; //保存PD xxxx xxxx switch(num) { case 0xee: key= 1; break; case 0xde: key= 2; break; case 0xbe: key= 3; break; case 0x7e: key= 4; break; case 0xed: key= 5; break; case 0xdd: key= 6; break; case 0xbd: key= 7; break; case 0x7d: key= 8; break; case 0xeb: key= 9; break; case 0xdb: key=10; break; case 0xbb: key=11; break; case 0x7b: key=12; break; case 0xe7: key=13; break; case 0xd7: key=14; break; case 0xb7: key=15; break; case 0x77: key=16; break; } } } else //键抬起 { sign=0; //按键自锁标志清0 count=0; //消抖计数清0 }}int main(){ while(1) { keyscan(); dis_buf[0]=table[key/10]; dis_buf[1]=table[key%10]; P0=0x00;//消隐 dula=1; dula=0; if(wei==0) { P0=0xfe;//送位码 wela=1; wela=0; P0=dis_buf[0];//送段码 dula=1; dula=0; wei=1; } else { P0=0xfd; wela=1; wela=0; P0=dis_buf[1]; dula=1; dula=0; wei=0; } }}

  • DSP28335 外接键盘通过spi输入数据现需要dsp编程实现外接键盘通过spi输入数据,同时能读出dsp中的数据用数码管显示,新手一枚,不太明白键盘按下后会产生一个什么样的值发送给dsp吗?有没有关于dsp键盘程序的参考资

  • labview小白求助!如何把循环和条件我有两个文件夹,第一个文件夹中的文件名字为“1-20.txt”“2-100.txt”“3-50.txt”.....“序列号-数字.txt”的格式;第二个文件夹是“20.txt”“50.txt”“100.txt”...文件

  • 单片机4×4矩阵键盘设计方案 4月08日 第三届·无线通信技术研讨会 立即报名 12月04日 2015•第二届中国IoT大会 精彩回顾 10月30日ETF•智能硬件开发技术培训会 精彩回顾 10月23日ETF•第三届 消费

  • 谁帮我做台三相电源,有意详谈。 谁帮我做台三相电源,有意详谈。


    功能要求:市电220V输入,输出2组三相交流电压、1组三相交流电流。


    输出电压1为3*57.5/100V,电流1A每相,电压2为3*220/380,电流1A每相。


  • 推荐资讯
    相关文章
    栏目更新
    栏目热门
    关于我们
    电脑周边
    家用电器
    通讯
    地区
    新闻中心
    深圳贴片加工厂
     
    • ☆电源板
    • ☆U盘
    • ☆网卡
    • ☆显卡
    • ☆监控摄像头
    • ☆电脑主板
    • ☆平板电脑主板
    • ☆DVD主板
    • 解码板
    • 伺服板
    • 高频头板
    • 复读机板
    • 音响主板
    • ☆手机主板
    • ☆手机按键板
    • ☆无线电话机
    • ☆对讲机主板
    • ☆深圳
    • 东莞
    • 广州
    • 龙岗
    • 宝安
    • 龙华
    • 坂田