本帖最后由 程鹏_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每相。
|