1. 急求一個由89C51單片機的代碼!要求用4*4矩陣鍵盤控制LED矩陣輸出0~9的數字!
/*
分別按下4×4鍵盤的按鍵,顯示0~16鍵值
*/
#include<reg51.h>
sbit speaker=P3^;
/////////////////鍵盤
sbit v1=P2^0;
sbit v2=P2^1;
sbit v3=P2^2;
sbit v4=P2^3;
sbit h1=P2^4;
sbit h2=P2^5;
sbit h3=P2^6;
sbit h4=P2^7;
/////////////////顯示
sbit shu1=P1^3;/*第1位數碼管共陰端*/
sbit shu2=P1^2;/*第2位數碼管共陰端*/
sbit shu3=P1^1;/*第3位數碼管共陰端*/
sbit shu4=P1^0;/*第4位數碼管共陰端*/
////////////////
void delayms(unsigned int i);
unsigned char yima[]={0xeb,0x88,0xb3,0xba,0xd8,0x7a,0x7b,0xa8,0xfb,0xfa};/*解碼表,此表數據和硬體相關*/
unsigned int b=0;/*要顯示的數據*/
unsigned int b_count=0;/*掃描次數*/
void delayms(unsigned int i);
unsigned int keyboar();
unsigned int b;
void t0()interrupt 1 using 1 /*中斷程序負責顯示b的值 */
{
unsigned char a1=0,a2=0,a3=0,a4=0;
static int k=0;
/*數碼管掃描顯示*/
a1=b/1000;/*取b的千位*/
a2=b%1000/100;/*取b的百位*/
a3=b%100/10;/*取b的十位*/
a4=b%10;/*取b的個位*/
if(k==0){shu4=1;shu1=0;shu2=0;shu3=0;P0=yima[a1];}
else if(k==1){shu4=0;shu1=1;shu2=0;shu3=0;P0=yima[a4];}
else if(k==2){shu4=0;shu1=0;shu2=1;shu3=0;P0=yima[a3];}
else if(k==3){shu4=0;shu1=0;shu2=0;shu3=1;P0=yima[a2];}
k++;
if(k>3)k=0;
TH0=240;
}
main()
{
EA=1;/*開全局中斷 */
TR0=1;/*定時器0開始計數 */
ET0=1;/*定時器0開中斷 */
TMOD=0X01;/*定時器0工作在方式1:16位計數模式 */
while(1)
{
b= keyboar(); /*把按鍵的代表的值給b */
}
}
void delayms(unsigned int i)
{
unsigned int j;
for(;i>0;i--)
for(j=100;j>0;j--);
}
//////////////////////////////////////////////////////////////////////////////////
//掃描法:逐行掃描查詢 一般用在按鍵比較少的場合
int keyscan()
{
unsigned char k k_temp;
P1=0xf0; //低位置0,准備查詢按鍵
k=P1; //取得當前P1口狀態
if(k!=0xf0) //如果有變化則表示有按鍵按下
{
delay(10); //延遲 消抖
k_temp=p1;
if(k==k_temp) //確實有鍵按下
{
k=0xfe;
do //循環掃描每一行
{
p1=k;
if(k!=p1)
{
switch(P1) //判斷按鍵 並返回鍵值
{
//第1行
case 0x7e:{return 0; break;}
case 0xbe:{return 1; break;}
case 0xde:{return 2; break;}
case 0xee:{return 3; break;}
//第2行
case 0x7d:{return 4; break;}
case 0xbd:{return 5; break;}
case 0xdd:{return 6; break;}
case 0xed:{return 7; break;}
//第3行
case 0x7b:{return 8; break;}
case 0xbb:{return 9; break;}
case 0xdb:{return 10;break;}
case 0xeb:{return 11;break;}
//第4行
case 0x77:{return 12;break;}
case 0xb7:{return 13;break;}
case 0xd7:{return 14;break;}
case 0xe7:{return 15;break;}
}
}
k=_crol_(k,1); //移位 進入下一行掃描
}
while(k!=0xef); //超過列范圍 退出掃描
}
}
}
////////////////////////////////////////////////////////////////////////////////
//線反轉法 :只需2步便可獲得按鍵位置,最常用
unsigned int keyboar()/*線反轉法 */
{
static unsigned int a=0;
unsigned char a1=0,b1=0;
/*行線為輸入線,列線為輸出線 */
v1=v2=v3=v4=0;
h1=h2=h3=h4=1;
if(P2<0xf0)/*檢查行是否有按鍵按下 */
{
delayms(10);
if(P2<0xf0)
{
/*行線為輸入線,列線為輸出線 */
v1=v2=v3=v4=0;
h1=h2=h3=h4=1;
a1=P2;
/*行線為輸出線,列線為輸入線 */
h1=h2=h3=h4=0;
v1=v2=v3=v4=1;
b1=P2;
a=a1|b1;
}
}
if (a==0xe7) { return 7; }
else if(a==0xeb) { return 8; }
else if(a==0xed) { return 9; }
else if(a==0xee) { return 13;}
else if(a==0xd7) {return 4; }
else if(a==0xdb) {return 5; }
else if(a==0xdd) {return 6; }
else if(a==0xde) {return 12;}
else if(a==0xb7) {return 1; }
else if(a==0xbb) {return 2; }
else if(a==0xbd) {return 3; }
else if(a==0xbe) {return 11;}
else if(a==0x77) {return 0; }
else if(a==0x7b) {return 15;}
else if(a==0x7d) {return 16;}
else if(a==0x7e) {return 10;}
else return 17;
}
/*******************************************
流水燈寫法1
while(1)
{
a=0x01; //賦初值00000001
for(i=0;i<8;i++) //循環8次
{
P0=a;
delay(500);
a=a<<1; //左移1位
}
}
流水燈寫法2:
a=0x01; //賦初值00000001
while(1)
{
P0=a; //先點亮第1個led
delay(500);
a=_crol_(a,1); //將a循環左移1位後再賦給a
}
流水燈寫法3:
while(1)
{
a=0x01; //賦初值00000001
for(i=0;i<7;i++)
{
P0=a;
delay(500);
a=a<<1; //左移
}
for(i=0;i<7;i++)
{
P0=a;
delay(500);
a=a>>1; //右移
}
}
寫法3:
void t0() interrupt 1 //中斷服務函數
{
TH0=(65536-50000)/256; //計數寄存器高8位重新載入
TL0=(65536-50000)%256; //計數寄存器低8位重新載入
num++;
if(num>=10) //500ms 調整流水速度
{
num=0;
P0=1<<i; //進入位移操作,熄滅相對應位的LED P0=1然後P0右移i位
i++;
if(i>7) i=0;
}
}