51单片机4*5键盘程序。

刚刚写了个4*5的键盘程序,不知道对不对,请大家看下,行用P1.0_P1.3,列用P3.0_P3.4,要防抖还要排除按2个键或者多个键。#include<reg51.h>... 刚刚写了个4*5的键盘程序,不知道对不对,请大家看下,行用P1.0_P1.3,列用P3.0_P3.4,要防抖还要排除按2个键或者多个键。
#include <reg51.h>
unsigned char temph;
unsigned char templ;
sbit INT_0 =P3^2; // 将p3.2外部中断0
bit judge_hitkey();
void system_init(void ); //设定INT0的工作方式
void INT0_SCANkey(); //外部中断0处理程序
void scan_key(void); //扫描键盘
void delay(unsigned int N) ;//延时子程序,实现(16*N+24)us的延时

////////////////////////////////////////////////////////////////////
void main(void)
{
temph=0xff;
templ=0xff;
P1=temph;
P2=templ;
system_init() ;
while(1)
{
INT0_SCANkey() ;
}
}

void system_init(void )
{
.
.
.
}
void delay(unsigned int N)
{
int i;
for(i=0;i<N;i++);
}
void INT0_SCANkey() interrupt 0 using 1
{

{

INT_0 =judge_hitkey(); //消抖动
if( INT_0 != 0 ) //判断是否有键按下
{
delay(2000); //消抖动
if( INT_0 != 0 ) //再次判断是否有键按下
{
EA=0;
scan_key();
delay(50);
INT_0 =judge_hitkey();
while( INT_0 !=1); //等待按键释放
EA=1;
}
}
}

}

//--------------------------------------------------------------------------------------------------
// 函数名称: judge_hitkey
// 函数功能: //判断是否有键按下,有返回1,没有返回0
//--------------------------------------------------------------------------------------------------
bit judge_hitkey() //判断是否有键按下,有返回1,没有返回0
{
unsigned char keycode1,keycode2;
temph=0xff;
templ=0xff; //P1输出全1则无键闭合
P1=temph;
P2=templ;
keycode1=P1; //读P1的状态
keycode2=P2;
if((keycode1!=0xff)&&(keycode2!=0xff) )
return(1); //有键闭合
else
return(0); //否则无键闭合
}
void scan_key(void) //扫描键盘,返回键值(P1.0~P1.3四位代表行,P2.0~P2.4五位代表列)
{
unsigned char keycode2;

//扫描第一行

P1=0xfe;
templ=0xff; //P1输出全1则无键闭合
P2=templ;
keycode2=P2;
if(keycode2!=0xff)
{
delay(2);
{
switch(keycode2)
{
case(0xfe):manage_key1();break;

case(0xfd):manage_key2();break;

case(0xfb):manage_key3();break;

case(0xf7):manage_key4();break;

case(0xef):manage_key5();break;

}

}

}

.
.
.
.
感觉程序是对的,但是效果出不来,是不是硬件没焊好?
展开
 我来答
MCU_newplayers
2009-09-25
知道答主
回答量:8
采纳率:0%
帮助的人:0
展开全部
if( INT_0 != 0 ) //再次判断是否有键按下
{
EA=0;
scan_key();
delay(50);
INT_0 =judge_hitkey();
while( INT_0 !=1); //等待按键释放
EA=1;
}
在EA=0;这句前,有无加上了,重新把 INT_0 =judge_hitkey(); 再赋回来了?,,我在郭天祥的板子上调试不行; EXITE.C(93): warning C206: 'manage_key1': missing function-prototype;
这是我花两个多小时写得51单片机,矩阵键盘的显示,希望能对你有帮助;
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
sbit dula=P2^6;
sbit wela=P2^7;
void init();
void display(uchar);
uchar keyscan();
uchar temp,num; //键盘扫描
void delay(uint xms) //延时子函数
{
int i,j;
for(i=xms;i>0;i--) //延时xms毫秒
for(j=110;j>0;j--);
}
void main()
{
init();
while(1)
{
keyscan();//不断扫描键盘;
display(num);

}
}
void init()
{
num=0xff; //控制让程序开始时不出现乱码;
wela=1;
P0=0xc0; //打开数码管显示,静态显示;
wela=0;

}
uchar keyscan()
{
P3=0xfe;
temp=P3;
temp=temp&0xf0;//按位与,只能用&;
if(temp!=0xf0) //在用while语句时,一定要加上去抖动,否则程序会停不下来的哦;
{ //还是统一用if语句吧,只有在去抖动才一定要用if语句;
delay(5); //至于中括号加在那都无所谓啦;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:num=1;
break;
case 0xde:num=2;
break;
case 0xbe:num=3;
break;
case 0x7e:num=4;
break;
}
while (temp!=0xf0) //去抖动只能用while ,只有松开手才会执行下面的,才会有数码显;
{ ////一松开手,就相当于把P3口的电平改变了;所以去抖不能在switch前
temp=P3;
temp=temp&0xf0; //不能不要,只有松开手,才会退出这个循环;
}

}
}
P3=0xfd;
temp=P3;
temp=temp&0xf0;//按位与,只能用&;
if(temp!=0xf0)
{
delay(5);
if(temp!=0xf0)
{
temp=P3;
// temp=temp&0xf0; //该句子一定不能要,因为下面判断的,只是P3口的电平状态而已;
}

switch(temp)
{ case 0xed: num=5; break;
case 0xdd: num=6; break;
case 0xbd: num=7; break;
case 0x7d: num=8; break;
}
}
while (temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}

P3=0xfb;
temp=P3;
temp=temp&0xf0;//按位与,只能用&;
if(temp!=0xf0)
{
delay(5);
if(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
if(temp!=0xf0)
{
temp=P3;
// temp=temp&0xf0;
}
switch(temp)
{ case 0xeb: num=9; break;
case 0xdb: num=10; break;
case 0xbb: num=11; break;
case 0x7b: num=12; break;
}

while (temp!=0xf0) //去抖动只能用while ,只有松开手才会执行下面的,才会有数码显;
{ ////一松开手,就相当于把P3口的电平改变了;所以去抖不能在switch前
temp=P3;
temp=temp&0xf0; //不能不要,只有松开手,才会退出这个循环;
}

P3=0xf7;
temp=P3;
temp=temp&0xf0;//按位与,只能用&;
if(temp!=0xf0)
{
delay(5);
if(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
if(temp!=0xf0) //该句子不能用while语句,因为如果用while语句,如果松手了,P3的电平就改变了,temp的值也会改变的。
//因此建议,非必要,还是用if语句;
{
temp=P3;
// temp=temp&0xf0;
}
switch(temp)
{ case 0xe7: num=13; break;
case 0xd7: num=14; break;
case 0xb7: num=15; break;
case 0x77: num=16; break;
}
while (temp!=0xf0) //去抖动只能用while ,只有松开手才会执行下面的,才会有数码显;
{ ////一松开手,就相当于把P3口的电平改变了;所以去抖不能在switch前
temp=P3;
temp=temp&0xf0; //不能不要,只有松开手,才会退出这个循环;
}

return num;

}
void display(uchar num)
{
P0=table[num-1];
dula=1;
dula=0;
}

下面的是郭天祥老师写的
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0};
uchar num,temp,num1;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
uchar keyscan();
void display(uchar aa);
void main()
{
num=17;
dula=1;
P0=0;
dula=0;
wela=1;
P0=0xc0;
wela=0;

while(1)
{
display(keyscan());
}
}
void display(uchar aa)
{
dula=1;
P0=table[aa-1];
dula=0;
}
uchar keyscan()
{
P3=0xfe;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:num=1;
break;
case 0xde:num=2;
break;
case 0xbe:num=3;
break;
case 0x7e:num=4;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}

P3=0xfd;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:num=5;
break;
case 0xdd:num=6;
break;
case 0xbd:num=7;
break;
case 0x7d:num=8;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}

P3=0xfb;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:num=9;
break;
case 0xdb:num=10;
break;
case 0xbb:num=11;
break;
case 0x7b:num=12;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}

P3=0xf7;
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:num=13;
break;
case 0xd7:num=14;
break;
case 0xb7:num=15;
break;
case 0x77:num=16;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
}
}
return num;

}
意法半导体(中国)投资有限公司
2023-06-12 广告
单片机的原理是比较复杂的,但是可以通过浅显易懂的语言来解释。单片机是一种集成电路芯片,通常包含处理器、存储器和各种输入输出(I/O)端口。处理器负责执行程序代码,并处理数据和指令;存储器用于存储程序代码和数据;输入输出端口用于与外部设备交互... 点击进入详情页
本回答由意法半导体(中国)投资有限公司提供
csatong
2009-09-25 · 超过30用户采纳过TA的回答
知道答主
回答量:62
采纳率:0%
帮助的人:0
展开全部
程序的原理都有些错误了.
1.主程序中最好不要调用中断程序
2.键盘的程序如果是行列扫描式的最好就不要用外部中断,实现起来比较不方便,实际上在该程序中,中断是没有任何实际意义的.
实际原理应为:
1.不用中断,每隔一段时间扫描一次键盘.
2.用定时中断,每隔一段时间扫描一次键盘,自动读取键码.
参考程序:
#include <reg51.h>
unsigned long fscancode;
unsigned long fkeycode;
unsigned char keytimer;
#define KEYTIMERDATA 3
sbit KEYC1PIN=P3^0;
sbit KEYC2PIN=P3^1;
sbit KEYC3PIN=P3^2;
sbit KEYC4PIN=P3^3;
sbit KEYC5PIN=P3^4;

#define KEY14 0X07FFFF
#define KEY13 0X0BFFFF
#define KEY12 0X0DFFFF
#define KEY11 0X0EFFFF
#define KEY24 0X0F7FFF
#define KEY23 0X0FBFFF
#define KEY22 0X0FDFFF
#define KEY21 0X0FEFFF
#define KEY34 0X0FF7FF
#define KEY33 0X0FFBFF
#define KEY32 0X0FFDFF
#define KEY31 0X0FFEFF
#define KEY44 0X0FFF7F
#define KEY43 0X0FFFBF
#define KEY42 0X0FFFDF
#define KEY41 0X0FFFEF
#define KEY54 0X0FFFF7
#define KEY53 0X0FFFFB
#define KEY52 0X0FFFFD
#define KEY51 0X0FFFFE

//键盘扫描码对应位置:COL-ROW对应于scancode数据中的相应位如下
// B19 B18 B17 B16 B15 B14 B13 B12 B11 B10 B09 B08 B07 B06 B05 B04 B03 B02 B01 B00
// 1-4 1-3 1-2 1-1 2-4 2-3 2-2 2-1 3-4 3-3 3-2 3-1 4-4 4-3 4-2 4-1 5-4 5-3 5-2 5-1
unsigned long keyscan(void)
{ unsigned long scancode;
P3=0xff; //第1-5列键盘扫描关闭

KEYC1PIN=0; //第1列键盘扫描使能
scancode=P1&0xf; //在scancode中保存第1列键盘扫描数据
KEYC1PIN=1; //第1列键盘扫描关闭

KEYC2PIN=0; //第2列键盘扫描使能
scancode<<=4; //scancode中空出保存当前列键盘扫描数据的位置
scancode+=(P1&0xf); //在scancode中保存当前列键盘扫描数据
KEYC2PIN=1; //第2列键盘扫描关闭

KEYC3PIN=0; //第3列键盘扫描使能
scancode<<=4; //scancode中空出保存当前列键盘扫描数据的位置
scancode+=(P1&0xf); //在scancode中保存当前列键盘扫描数据
KEYC3PIN=1; //第3列键盘扫描关闭

KEYC4PIN=0; //第4列键盘扫描使能
scancode<<=4; //scancode中空出保存当前列键盘扫描数据的位置
scancode+=(P1&0xf); //在scancode中保存当前列键盘扫描数据
KEYC4PIN=1; //第4列键盘扫描关闭

KEYC5PIN=0; //第5列键盘扫描使能
scancode<<=4; //scancode中空出保存当前列键盘扫描数据的位置
scancode+=(P1&0xf); //在scancode中保存当前列键盘扫描数据
KEYC5PIN=1; //第5列键盘扫描关闭

return scancode;
}

unsigned long getkey(void)
{ unsigned long scancode,keycode;
keycode=0;
scancode=keyscan();
if(scancode != fscancode)
keytimer=KEYTIMERDATA;
else if(keytimer == 0)
{ //按键无抖动
if(scancode == fkeycode)
{ //按键无改变
//这里可增加按下后自动重发按键码的程序代码
}
else
{ //按键已改变
keycode=scancode;
fkeycode=keycode;
}
}
fscancode=scancode;
return keycode;
}
void delay(unsigned int N)
{ int i;
for(i=0;i<N;i++);
}

void main(void)
{unsigned long keycode;
while(1)
{
keycode=getkey();
if(keycode == KEY11)
{ //这里增加键盘处理程序
}

//以下两句程序也可用10mS中断实现,效果会更好
delay(1000); //延时约10mS
if(keytimer>0) keytimer--; //键盘防抖倒计时器减1

}
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
百度网友7644a69
2009-09-24 · TA获得超过361个赞
知道小有建树答主
回答量:967
采纳率:0%
帮助的人:524万
展开全部
调试还是要自己动手的,下载程序到板子 试一下不就明了。 如果方法理论正确就是对了 看程序是看不出来 按键处理得如何了
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
一万光年MEGn0
2009-09-25 · TA获得超过3712个赞
知道大有可为答主
回答量:4602
采纳率:67%
帮助的人:1048万
展开全部
感觉是对的,但不一定对
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(2)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式