吸取各位前辈的经验,将之前二极管用量多的问题优化一下,目前不用二极管能接6键,2只二极管能接12键,6只二极管能接18键,9只二极管能接21键,第22键要单独占用3只二极管最不化算。
实验用89S51作试验,电路接线就是P1.2,P1.3,P1.4接键盘,P1.0接显示器。
(原文件名:GIF.gif)
(原文件名SC00015.JPG)
/*==================================================================*
*3个IO接识别22键测试程序*
*------------------------------------------------*
*MCU:AT89C2051*
*OSC:12Mcysytel*
*程序设计:Cowboy*
*程序版本:V1.0*
*==================================================================*/
#include
//==================IO口线连接==================
sbitBus=P1^0;
sbitIO_a=P1^4;
sbitIO_b=P1^3;
sbitIO_c=P1^2;
//==================变量声明====================
unsignedcharDisp_buf[3];
unsignedcharDig;
unsignedcharKey_count;
unsignedcharbdataKey_state;
sbitKB0=Key_state^0;
sbitKB1=Key_state^1;
sbitKB2=Key_state^2;
sbitKB3=Key_state^3;
sbitKB4=Key_state^4;
sbitKB5=Key_state^5;
//==================表格数据====================
codeunsignedcharLED_font[24]=
{
0x84,0x9f,0xa2,0x8a,0x99,0xc8,0xc0,0x9e,0x80,//012345678
0x88,0x90,0xc1,0xe4,0x83,0xe0,0xf0,0xff,0xfb,//9abcdef-
};
codeunsignedcharKey_tab[64]=//键码映射表
{//0123456789
22,0,2,0,0,0,0,0,4,0,//0
0,0,0,0,0,18,0,0,0,0,//1X
0,0,0,0,0,0,3,14,0,0,//2X
20,10,6,0,0,0,0,0,1,19,//3X
0,5,0,0,0,15,0,11,0,0,//4X
0,17,0,0,13,8,0,21,0,9,//5X
16,12,7,0//6X
};
//===============检测按键=================
voidKey_scan()
{
unsignedchari;
Key_count--;//扫描次序
Key_count&=3;
switch(Key_count)//按次序处理
{
case2://第一轮扫描
KB0=IO_b;
KB1=IO_c;
IO_a=1;
IO_b=0;
break;
case1://每二轮扫描
KB2=IO_c;
KB3=IO_a;
IO_b=1;
IO_c=0;
break;
case0://每三轮扫描
KB4=IO_a;
KB5=IO_b;
IO_c=1;
break;
default://每四轮扫描
if(!IO_a)KB0=0;
if(!IO_b)KB2=0;
if(!IO_c)KB4=0;
IO_a=0;
//======更新显示缓冲区=======
i=Key_tab[Key_state];
if(i==0)
{
Disp_buf[2]=0x11;//显示三横
Disp_buf[1]=0x11;
Disp_buf[0]=0x11;
}
else
{
Disp_buf[2]=0x0c;//字符"C"
Disp_buf[1]=i/10;//键码十位
Disp_buf[0]=B;于//键码个位
}
Key_state=0;
}
}
/*===================================================================
ONEWIRE显示总线驱动程序
===================================================================*/
//===============发送一位=================
voidSend_bit(bitDat)
{
unsignedchari=3;
if(!Dat)Bus=0;
else
{
Bus=0;
Bus=1;
}
while(--i);//延时8us
Bus=1;
}
//===============总线驱动=================
voidBus_drive()
{
unsignedchari=0;
unsignedcharSdat;
Send_bit(1);//Bit6消隐
doBus=1;while(--i);//延时768us
doBus=0;while(--i);//延时768us
Bus=1;
Sdat=LED_font[Disp_buf[Dig++]];//获取显示数据
Send_bit(Sdat&0x01);//发送位0
Send_bit(Sdat&0x02);//发送位1
Send_bit(Sdat&0x04);//发送位2
Send_bit(Sdat&0x08);//发送位3
Send_bit(Sdat&0x10);//发送位4
Send_bit(Sdat&0x20);//发送位5
Send_bit(Dig&0x01);//发送位选1
Send_bit(Dig&0x02);//发送位选2
while(--i);//延时512us
Send_bit(Sdat&0x40);//发送位6
for(i=7;i>0;i--)Send_bit(1);//位6移至Dout
if(Dig==3)Dig=0;
}
/*===================================================================
延时5ms程序
===================================================================*/
voidDelay_5ms()
{
while(!TF1);
TF1=0;
TH1=(-5000)/256;
TL1=(-5000)%256;
}
/*===================================================================
主程序
===================================================================*/
voidmain()
{
TMOD=0x10;//定时器1,16位模式
TCON=0xc0;//TR1=1;TF1=1;
while(1)//主循环
{
Bus_drive();//显示总线驱动
Key_scan();//检测按键
Delay_5ms();//延时5MS
}