本帖最后由 prelbt 于 2013-5-14 14:15 编辑
矩阵键盘的一个奇怪 问题 本人的 开发板是普中科技的 HC6800-EM3 V2.2(2013)款带交通灯的那款。矩阵键盘是4*4的。单片机芯片是STC90C516RD+,矩阵键盘接P3口,数码管接P0口,P3.0-P3.3接行键盘,P3.4-P3.7接列键盘,程序的目的是实现利用矩阵键盘在数码管上显示键值。 程序如下: #include #define uchar unsigned char //宏的定义变量类型 uchar 代替 unsigned char #define uint unsigned int //宏的定义变量类型 uint 代替 unsigned int uchar dis_buf; //显示缓存 uchar temp; uchar key; //键顺序码 void delay(uchar x); //x*0.14MS ***it PH32 = P3^2; ***it PH33 = P3^3; // 此表为 LED 的字模 ,取反后为共阳极代码 ,未取反为共阴极代码 Unsigned char code LED7Code[]= {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F,~0x77,~0x7C,~0x39,~0x5E,~0x79,~0x71}; /************************************************************* * * * 延时子程序 * * * *************************************************************/ void delay(uchar x) //延时 x*0.14 ms { uchar j; while((x--)!=0) //CPU执行x*12次 { for(j=0;j<125;j++) {;} } } /************************************************************* * * * 键扫描子程序 (4*4 的矩阵) P3.4 P3.5 P3.6 P3.7为列 * * P3.1 P3.2 P3.3、P3.4为行 * * * *************************************************************/ void keyscan(void) { temp = 0; P3=0xF0; //高四位输入 列为高电平 行为低电平 temp=P3; //读P3口 temp=temp&0xF0; //屏蔽低四位 temp=~((temp>>4)|0xF0); if(temp==1) // P3.4 被拉低 key=1; //第1个按键键值 if(temp==2) // P3.5 被拉低 key=2; //第2个按键键值 if(temp==4) // P3.6 被拉低 key=3; //第3个按键键值 if(temp==8) // P3.7 被拉低 key=4; //第4个按键键值 P3=0x0F; //低四位输入 行为高电平 列为低电平 temp=P3; //读P3口 temp=temp&0x0F; temp=~(temp|0xF0); if(temp==1) //第一行 P3.0 被拉低 key=key+0; if(temp==2) //第二行 P3.1 被拉低 key=key+4; if(temp==4) //第三行 P3.2 被拉低 key=key+8; if(temp==8) //第四行 P3.3 被拉低 key=key+12; dis_buf = key; //键值入显示缓存 dis_buf = dis_buf & 0x0f; } /************************************************************* * * * 主程序 * * * *************************************************************/ main() { P0=0xFF; //置P0口 P3=0x0F; //置P3口,INT0,INT1置为高电平 // IT0=0; //低电平触发 IT0=1; //下降沿触发 EX0=1; IT1=1; //下降沿触发 EX1=1; EA=1; // delay(10); //延时 dis_buf=0; while(1) { P0 = LED7Code[dis_buf%16]&0x7f; //LED7, 0x7f为小数点 共阴和共阳此处也是不一样; %16表示输出16进制 } } /************************************************************* * * * 中断程序 * * * *************************************************************/ void cour(void) interrupt 0 { //EA=0; EX0=0; //关闭中断。 if(P3!=0x0F) //判断按键是否按下 如果按钮按下 会拉低P3其中的一个端口 { delay(40); // 延时6ms去抖动 keyscan(); } // while(!PH32);//检查键是否松开 //delay(10); EX1=1; } /********************************************************/ void cour2(void) interrupt 2 { //EA=0; EX1=0; if(P3!=0x0F) //判断按键是否按下 如果按钮按下 会拉低P3其中的一个端口 { delay(40); // 延时6ms去抖动 keyscan(); } // while(!PH32);//检查键是否松开 EX1=1; } 依次按下第三、四行键盘,显示9、a、b、........直到0。 奇怪的地方:这里P3.2接第三行键盘,P3.3接第四行键盘, int0设成下降沿中断,P3=0x0f,行接高电平,列接低电平,按住第三行任意一个键,P3.2从高电平跳变到低电平,形成下降沿脉冲,进入中断。 我的问题是:这个时候,按住第一个按键不放,过几秒,再按下另一个第三行按键,应该说没有下降沿了,不会再进入中断数码管数字应该不变啊,但是实际上会不停的跳变。第四行键盘重复以上动作,也会有同样现象。 我研究了一下,在扫描键盘的程序keyscan中,P3.3会从0x0f变成0xf0,会触发int1中断,但是int1中断优先级比int0低,程序不会响应。 按第四行键盘的时候,同样在keysan中,P3.2会从0x0f变成0xf0,会触发int0中断。 但是这都不会再按下另一个按键时再进入中断啊。 PS:去掉int1中断或者EX1=0,数码管也不会跳变了。 希望诸位大侠帮我找出问题所在。
|