中断方式的扩展矩阵键盘

  来电了! 电工总算烦了,没想到会这么快,多亏阿福,外面真是只能凑合,还是自个儿宿舍舒服,明天开焊!

总图

 最小系统&数码管

与门实现键盘中断触发

译码器实现矩阵键盘的扩展

扩展的矩阵键盘

程序代码:

 

 

#include //头文件

#include

#define uchar unsigned char //宏定义

#define uint  unsigned int

 

code uchar table[]={0x3f,0x06,0x5b,//数码管显示的数值

0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,

0x77,0x7c,0x39,0x5e,0x79,0x71};

code uchar key_tab[32]={   //此数组为键盘编码 加号前为按前j的值即扫描值,加号后卫按键按下后P0取高位的值

0xf0+0xe0,0xf0+0xd0,0xf0+0xb0,0xf0+0x70,   // 0,,,3,

0xf1+0xe0,0xf1+0xd0,0xf1+0xb0,0xf1+0x70,   // 4,,,7,

0xf2+0xe0,0xf2+0xd0,0xf2+0xb0,0xf2+0x70,   // 8,,,11,

0xf3+0xe0,0xf3+0xd0,0xf3+0xb0,0xf3+0x70,   // 12,,,15,

0xf4+0xe0,0xf4+0xd0,0xf4+0xb0,0xf4+0x70,   // 16,,,19,

0xf5+0xe0,0xf5+0xd0,0xf5+0xb5,0xf5+0x70,   // 20,,,23,

0xf6+0xe0,0xf6+0xd0,0xf6+0xb0,0xf6+0x70,   // 24,,,27,

0xf7+0xe0,0xf7+0xd0,0xf7+0xb0,0xf8+0x70,   // 28,,,31,

}; //  c,d,e,f,

uchar l_key=0x00; //定义变量,存放键值

uchar l_keyold=0xff; //作为按键放开否的凭证

uchar flag,flag1;//flag为了使最初不显示数字,flag1

void readkey();    //扫描键盘,获取键值

void display(uchar *lp); //显示子函数

void delay1(uint z)

{

uint x,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}void delay();  //延时子函数

void main()

{

EA=1;  //打开总中断

EX0=1; //打开外部中断

P0=0x0f; //键值高位为高电平,低位为低电平

while(1)

{

display(&l_key); //调用显示子函数

}  

}

void key_scan() interrupt 0//外部中断,的优先级最高

{

EX0=0;  //在读键盘时,关闭外部中断,防止干扰带来的多次中断

TMOD=0xf1; //设置定时器为工作方式 ,定时器零为方式1,16位定时器模式        

TH0=0x2e;  //设置初值,为毫秒,

TL0=0x00;

ET0=1;  //开启定时器中断

  TR0=1;  //启动定时器计数

flag=1;

flag1++;

}

void time0() interrupt 1   //定时器的中断函数

{

TR0=0;     //关闭定时器

readkey(); //定时ms后产生中断,调用此函数,读取键值

void readkey()    //扫描键盘子函数

{

uchar i,j,key; //定义局部变量

j=0xf0;   //设定初值

key=0xff;

for(i=0;i<8;i++) // 逐行扫描键盘

{

P0=j;

if((P0&0xf0)!=0xf0) //有按键按下,高位不可能全为

{

key=P0&0xf0; //读取P0口的值,退出循环,否则循环下次

break;

}

j++; //此函数的功能是:左移循环

  }

if(key==0xff)   //如果读取不到P0口的值,如干扰,则返回

  {

  l_keyold=0xff; 

P0=0x0f;    // 恢复P0口的值,等待按键按下,很重要,否则一直为低电平,无法触发中断

EX0=1;    //在返回前,打开外部中断

  return;

}

if(l_keyold==key) // 检查按键放开否,如果相等表明没有放开

{

TH0=0x2e; //设置初值

TL0=0x00;

TR0=1; //继续启动定时器,检查按键放开否

return;

}

TH0=0x2e;  

TL0=0;

TR0=1;  //启动定时器

l_keyold=key; //获取键值,作为放开否的凭证

key+=j;

for(i=0;i<32;i++)   //查表获得相应的进制值存放到l_key中

{

if(key==key_tab[i])

{

l_key=i;

break;

}

 }

 //程序运行到此,就表明有键值存放到l_key中,主程序

 //就可以检测键盘值并作相应的处理

}

void display(uchar *lp) //显示子函数

{

uchar i,temp,j;

P2=0;    //P2口为输出值

P1=0xff;

if(*lp<16)

P1=0xfd;

else 

P1=0xfe; //点亮第二个数码管

temp=flag1;

j=*lp;

if(flag==1)

{

if(j>15)

j-=16;

for(i=0;i<=j;i++)

{

if(flag1>temp)

break;

P2=table[i]; //查表获得相应的要显示的数字的数码段

delay();  //延时

delay1(500);

P2=0;  //清零,准备显示下一个数值

}

}

}

void delay() //延时子函数

{

_nop_();_nop_();_nop_();_nop_();_nop_();

}

 

 

你可能感兴趣的:(单片机)