【單片機】— {STC15}—{矩陣鍵盤&Proteus}
矩陣鍵盤
Proteus仿真
一、Proteus仿真STC15的問題
> 據說P0口存在BUG,不會被正常拉低,而是產生短路。
二、原理圖
1、CPU
2、矩陣鍵盤
3、顯示部分
程序
一、矩陣鍵盤_單行掃描_普通寫法
#include<STC15.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6 //定義矩陣鍵盤接口
uchar Key_res =0;
uchar i=0;
void GPIO(void); //IO口初始化函數
void Delay10ms(); //@12.000MHz
void Delay5ms(); //@12.000MHz
void Delay1ms(); //@12.000MHz
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數
void main(void)
{
GPIO();
while(1)
{
Key_res =0;
i=Key16_Scan(); //矩陣鍵盤掃描函數子程序
Key16_Function(); //矩陣鍵盤服務(功能)子函數
}
}
//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
P0M1=0;
P0M0=0;
P1M1=0;
P1M0=0;
P2M1=0;
P2M0=0;
P3M1=0;
P3M0=0;
P4M1=0;
P4M0=0;
P5M1=0;
P5M0=0;
}
//------------------------------------軟件延時---------------------------------------//
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//
uchar Key16_Scan(void)
{
uchar temp = 0;
uchar Key_res = 0;
KeyBus = 0XFF;
KeyBus = 0X7F; //0111 1111 掃描第一行
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms(); //按鍵消抖
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=16;break;
case 0X0D: Key_res=15;break;
case 0X0B: Key_res=14;break;
case 0X07: Key_res=13;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
KeyBus = 0XFF;
KeyBus = 0XBF; //1011 1111 掃描第二行
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms();
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=12;break;
case 0X0D: Key_res=11;break;
case 0X0B: Key_res=10;break;
case 0X07: Key_res=9;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
KeyBus = 0XFF;
KeyBus = 0XDF; //1101 1111 掃描第三行
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms();
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=8;break;
case 0X0D: Key_res=7;break;
case 0X0B: Key_res=6;break;
case 0X07: Key_res=5;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
KeyBus = 0XFF;
KeyBus = 0XEF; //1110 1111 掃描第四行
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms();
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=4;break;
case 0X0D: Key_res=3;break;
case 0X0B: Key_res=2;break;
case 0X07: Key_res=1;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
return Key_res;
}
//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void)
{
if(i != 0)
{
switch(i)
{
case 1: P1=0XFE;P2=0XFF;break;
case 2: P1=0XFD;P2=0XFF;break;
case 3: P1=0XFB;P2=0XFF;break;
case 4: P1=0XF7;P2=0XFF;break;
case 5: P1=0XEF;P2=0XFF;break;
case 6: P1=0XDF;P2=0XFF;break;
case 7: P1=0XBF;P2=0XFF;break;
case 8: P1=0X7F;P2=0XFF;break;
case 9: P1=0XFF;P2=0XFE;break;
case 10: P1=0XFF;P2=0XFD;break;
case 11: P1=0XFF;P2=0XFB;break;
case 12: P1=0XFF;P2=0XF7;break;
case 13: P1=0XFF;P2=0XEF;break;
case 14: P1=0XFF;P2=0XDF;break;
case 15: P1=0XFF;P2=0XBF;break;
case 16: P1=0XFF;P2=0X7F;break;
default:P1=0X00;P2=0X00;break;
}
}
}
二、矩陣鍵盤_單行掃描_外部中斷
(代碼未能實現,改進ing)
#include<STC15.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6 //定義矩陣鍵盤接口
uchar Key_res =0;
uchar i=0;
void GPIO(void); //IO口初始化函數
void Delay10ms(); //@12.000MHz
void Delay5ms(); //@12.000MHz
void Delay1ms(); //@12.000MHz
void INT1_INIT(void); //外部中斷1初始化函數
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數
void main(void)
{
GPIO();
INT1_INIT();
while(1)
{
KeyBus=0X0F;
Key16_Function(); //矩陣鍵盤服務(功能)子函數
}
}
//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
P0M1=0;
P0M0=0;
P1M1=0;
P1M0=0;
P2M1=0;
P2M0=0;
P3M1=0;
P3M0=0;
P4M1=0;
P4M0=0;
P5M1=0;
P5M0=0;
}
//------------------------------------軟件延時---------------------------------------//
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
//---------------------------------------外部中斷1初始化函數-----------------------------//
void INT1_INIT(void)
{
IT1=1;
EX1=1;
EA=1;
}
//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//
uchar Key16_Scan(void)
{
uchar temp = 0;
uchar Key_res = 0;
KeyBus = 0XFF;
KeyBus = 0X7F; //0111 1111
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms();
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=16;break;
case 0X0D: Key_res=15;break;
case 0X0B: Key_res=14;break;
case 0X07: Key_res=13;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
KeyBus = 0XFF;
KeyBus = 0XBF; //1011 1111
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms();
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=12;break;
case 0X0D: Key_res=11;break;
case 0X0B: Key_res=10;break;
case 0X07: Key_res=9;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
KeyBus = 0XFF;
KeyBus = 0XDF; //1101 1111
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms();
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=8;break;
case 0X0D: Key_res=7;break;
case 0X0B: Key_res=6;break;
case 0X07: Key_res=5;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
KeyBus = 0XFF;
KeyBus = 0XEF; //1110 1111
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
Delay10ms();
temp=KeyBus;
temp=temp&0X0F;
if(temp!=0X0F)
{
temp=temp&0X0F;
switch(temp)
{
case 0X0E: Key_res=4;break;
case 0X0D: Key_res=3;break;
case 0X0B: Key_res=2;break;
case 0X07: Key_res=1;break;
default: break;
}
while(temp!=0X0F) //鬆手檢測
{
temp=KeyBus;
temp=temp&0X0F;
}
}
}
return Key_res;
}
//--------------------------------------外部中斷1服務函數-----------------------------//
void INT1_ISR() interrupt 2
{
i = Key16_Scan(); //矩陣鍵盤掃描函數子程序
}
//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void)
{
if(i != 0)
{
switch(i)
{
case 1: P1=0XFE;P2=0XFF;break;
case 2: P1=0XFD;P2=0XFF;break;
case 3: P1=0XFB;P2=0XFF;break;
case 4: P1=0XF7;P2=0XFF;break;
case 5: P1=0XEF;P2=0XFF;break;
case 6: P1=0XDF;P2=0XFF;break;
case 7: P1=0XBF;P2=0XFF;break;
case 8: P1=0X7F;P2=0XFF;break;
case 9: P1=0XFF;P2=0XFE;break;
case 10: P1=0XFF;P2=0XFD;break;
case 11: P1=0XFF;P2=0XFB;break;
case 12: P1=0XFF;P2=0XF7;break;
case 13: P1=0XFF;P2=0XEF;break;
case 14: P1=0XFF;P2=0XDF;break;
case 15: P1=0XFF;P2=0XBF;break;
case 16: P1=0XFF;P2=0X7F;break;
default:P1=0X00;P2=0X00;break;
}
}
}
三、矩陣鍵盤_多行掃描_普通寫法
#include<STC15.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6 //定義矩陣鍵盤接口
uchar Key_res =0;
uchar i=0;
void GPIO(void); //IO口初始化函數
void Delay10ms(); //@12.000MHz
void Delay5ms(); //@12.000MHz
void Delay1ms(); //@12.000MHz
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數
void main(void)
{
GPIO(); //IO口初始化函數
while(1)
{
Key_res =0;
i=Key16_Scan(); //矩陣鍵盤掃描函數子程序
Key16_Function(); //矩陣鍵盤服務(功能)子函數
}
}
//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
P0M1=0;
P0M0=0;
P1M1=0;
P1M0=0;
P2M1=0;
P2M0=0;
P3M1=0;
P3M0=0;
P4M1=0;
P4M0=0;
P5M1=0;
P5M0=0;
}
//------------------------------------軟件延時---------------------------------------//
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//
uchar Key16_Scan(void)
{
uchar X_temp = 0,Y_temp = 0;
uchar Key_down = 0;
KeyBus = 0XFF;
KeyBus = 0X0F; //高4位置0,低4位置1,此時有按鍵按下時,低四位的某一位會被拉低,由此定位按下的按鍵在第幾列
Y_temp = KeyBus&0X0F;
if(Y_temp!=0X0F) //如果檢測到某列有按鍵按下(有按鍵按下時,低四位會有一位被拉低)
{
Delay5ms(); //按鍵消抖(不知道有無必要)
KeyBus = 0X0F;
Y_temp = KeyBus&0X0F;//將KeyBus低四位的按鍵信息賦值給Y_temp
if(Y_temp!=0X0F)
{
KeyBus = 0X0F;
Y_temp = KeyBus&0X0F; //將KeyBus低四位的按鍵信息賦值給Y_temp,反應列信息
KeyBus = 0XF0;
X_temp = KeyBus&0XF0; //將KeyBus高四位的按鍵信息賦值給X_temp,反應行信息
if(Key_down == 0) //按鍵擡起檢測,
{
switch(Y_temp) //判斷列
{
case 0X07: Key_res=1; break;
case 0X0B: Key_res=2; break;
case 0X0D: Key_res=3; break;
case 0X0E: Key_res=4; break;
default: return 0; //無按鍵按下,返回0
}
switch(X_temp) //判斷行
{
case 0X70: return Key_res+12;break;
case 0XB0: return Key_res+ 8;break;
case 0XD0: return Key_res+ 4;break;
case 0XE0: return Key_res; break;
default: return 0; //無按鍵按下,返回0
}
}
}
}
else
Key_down = 0; //按鍵被鬆開
if(Key_res)
Key_down = 1; //標誌按鍵被按下,防止重入
return Key_res;
}
//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void)
{
if(i != 0) //按鍵按下
{
switch(i)
{
case 1: P1=0XFE;P2=0XFF;break;
case 2: P1=0XFD;P2=0XFF;break;
case 3: P1=0XFB;P2=0XFF;break;
case 4: P1=0XF7;P2=0XFF;break;
case 5: P1=0XEF;P2=0XFF;break;
case 6: P1=0XDF;P2=0XFF;break;
case 7: P1=0XBF;P2=0XFF;break;
case 8: P1=0X7F;P2=0XFF;break;
case 9: P1=0XFF;P2=0XFE;break;
case 10: P1=0XFF;P2=0XFD;break;
case 11: P1=0XFF;P2=0XFB;break;
case 12: P1=0XFF;P2=0XF7;break;
case 13: P1=0XFF;P2=0XEF;break;
case 14: P1=0XFF;P2=0XDF;break;
case 15: P1=0XFF;P2=0XBF;break;
case 16: P1=0XFF;P2=0X7F;break;
default:P1=0X00;P2=0X00;break;
}
}
}
四、矩陣鍵盤_多行掃描_外部中斷
(僅能檢測到列,檢測不到行,改進ing)
#include<STC15.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define KeyBus P6 //定義矩陣鍵盤接口
uchar Key_res =0;
uchar i=0;
void GPIO(void); //IO口初始化函數
void Delay10ms(); //@12.000MHz
void Delay5ms(); //@12.000MHz
void Delay1ms(); //@12.000MHz
void INT1_INIT(void); //外部中斷1初始化函數
uchar Key16_Scan(void);//矩陣鍵盤掃描函數子程序
void Key16_Function(void); //矩陣鍵盤服務(功能)子函數
void main(void)
{
GPIO(); //IO口初始化函數
INT1_INIT();
while(1)
{
KeyBus = 0X0F;
Key16_Function(); //矩陣鍵盤服務(功能)子函數
}
}
//-----------------------------------IO口初始化函數-----------------------------//
void GPIO(void)
{
P0M1=0;
P0M0=0;
P1M1=0;
P1M0=0;
P2M1=0;
P2M0=0;
P3M1=0;
P3M0=0;
P4M1=0;
P4M0=0;
P5M1=0;
P5M0=0;
}
//------------------------------------軟件延時---------------------------------------//
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void Delay5ms() //@12.000MHz
{
unsigned char i, j;
i = 59;
j = 90;
do
{
while (--j);
} while (--i);
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
//---------------------------------------外部中斷1初始化函數-----------------------------//
void INT1_INIT(void)
{
IT1=1;
EX1=1;
EA=1;
}
//---------------------------------------矩陣鍵盤掃描函數子程序-------------------------//
uchar Key16_Scan(void)
{
uchar X_temp = 0,Y_temp = 0;
uchar Key_down = 0;
KeyBus = 0XFF;
KeyBus = 0X0F; //高4位置0,低4位置1,此時有按鍵按下時,低四位的某一位會被拉低,由此定位按下的按鍵在第幾列
Y_temp = KeyBus&0X0F;
if(Y_temp!=0X0F) //如果檢測到某列有按鍵按下(有按鍵按下時,低四位會有一位被拉低)
{
Delay1ms(); //按鍵消抖(不知道有無必要)
KeyBus = 0X0F;
Y_temp = KeyBus&0X0F;//將KeyBus低四位的按鍵信息賦值給Y_temp
if(Y_temp!=0X0F)
{
KeyBus = 0X0F;
Y_temp = KeyBus&0X0F; //將KeyBus低四位的按鍵信息賦值給Y_temp,反應列信息
KeyBus = 0XF0;
X_temp = KeyBus&0XF0; //將KeyBus高四位的按鍵信息賦值給X_temp,反應行信息
if(Key_down == 0) //按鍵擡起檢測,
{
switch(Y_temp) //判斷列
{
case 0X07: Key_res=1; break;
case 0X0B: Key_res=2; break;
case 0X0D: Key_res=3; break;
case 0X0E: Key_res=4; break;
default: return 0; //無按鍵按下,返回0
}
switch(X_temp) //判斷行
{
case 0X70: return Key_res+12;break;
case 0XB0: return Key_res+ 8;break;
case 0XD0: return Key_res+ 4;break;
case 0XE0: return Key_res; break;
default: return 0; //無按鍵按下,返回0
}
}
}
}
else
Key_down = 0; //按鍵被鬆開
if(Key_res)
Key_down = 1; //標誌按鍵被按下,防止重入
return Key_res;
}
//--------------------------------------外部中斷1服務函數-----------------------------//
void INT1_ISR() interrupt 2
{
i = Key16_Scan(); //矩陣鍵盤掃描函數子程序
}
//-----------------------------------矩陣鍵盤服務(功能)子函數-------------------//
void Key16_Function(void)
{
EX1=0;
if(i != 0) //按鍵按下
{
switch(i)
{
case 1: P1=0XFE;P2=0XFF;break;
case 2: P1=0XFD;P2=0XFF;break;
case 3: P1=0XFB;P2=0XFF;break;
case 4: P1=0XF7;P2=0XFF;break;
case 5: P1=0XEF;P2=0XFF;break;
case 6: P1=0XDF;P2=0XFF;break;
case 7: P1=0XBF;P2=0XFF;break;
case 8: P1=0X7F;P2=0XFF;break;
case 9: P1=0XFF;P2=0XFE;break;
case 10: P1=0XFF;P2=0XFD;break;
case 11: P1=0XFF;P2=0XFB;break;
case 12: P1=0XFF;P2=0XF7;break;
case 13: P1=0XFF;P2=0XEF;break;
case 14: P1=0XFF;P2=0XDF;break;
case 15: P1=0XFF;P2=0XBF;break;
case 16: P1=0XFF;P2=0X7F;break;
default:P1=0X00;P2=0X00;break;
}
}
EX1=1;
}