|
最近在看马潮老师:< AVR单片机嵌入式系统原理与应用实践>一书,我将其中的矩阵键盘扫描函数按照马老师的方法,移植到AT89S52芯片,写了个键测试函数,用以测试新做的键盘和液晶板,可是没有效果,程序贴出来了,自己水平有限,找了数天找不出原因,拜请大侠帮小弟找找.(注:我想硬件电路应没错,因为其它的键扫都有效果)
#define U8 unsigned char
#define U16 unsigned int
#define NULL 0
#define KEY_INPORT P1
键扫程序:/*-------------------在此定义扫描函数的全局变量---------------------------*/
static U8 data sg_keyState = 0;//按键状态,状态0,1,2
static U8 data sg_lineScan; //行扫描
static U8 data sg_keyCol; //变量用以读取列值
U8 data g_keyValue = 255; //扫描得到的键值
/*-------------------在此定义键扫函数---------------------------*/
//===============================================================
// Name : uchar ScanKeyboard()
// Fuction: 4*4矩阵键盘键扫描函数,返回键值
// 备注: 按键释放才返回键值,否则,返回255(即没有键按下的键值)
//===============================================================
#define KEY_ORIGIN 0x0f
U8 ScanKeyboard()
{
static U8 data s_keyReturn = 255;//无键按下//版本1.1
U8 data i = 0;
switch (sg_keyState)
{
case 0 : //零状态
{
KEY_INPORT = KEY_ORIGIN; //发P1原始状态00001111
sg_keyCol = KEY_INPORT & 0x0f; //读回列值
if (sg_keyCol != KEY_ORIGIN) //有键按下
{
sg_keyState++; //转状态1
sg_lineScan = 0x80; //行扫描开始,行线要依次输出低电平,因为keil中移位运算符是补零,所以取0x80= 10000000,取反为01111111
KEY_INPORT = ~sg_lineScan; // P1=0x07,(01111111) 行线依次输出低电平
for (i = 0; i < 5; i++) //逐行扫描,即使行线依次输出低电平
{
sg_keyCol = KEY_INPORT & 0x0f; //读回列值,其有按键按下,则连接按键的那根列线通过按键被行线低电平拉低
if (sg_keyCol == KEY_ORIGIN) //没扫描到按键,继续扫描
{
sg_lineScan >>= 1; // //右移,左端补零,而不是补1,所以,行扫描要取反初值本应是0x7f,不得不取反为0x80
KEY_INPORT = ~sg_lineScan;
}
else {sg_lineScan = KEY_INPORT & 0xf0; break;} //扫描到按键,保存按键列信息在keyCol ,行信息在lineScan
}
}
break; //无按键按下,返回
}
case 1 :
{
if (KEY_INPORT == (sg_lineScan | sg_keyCol))// 仍是同一按键
{
switch (sg_lineScan | sg_keyCol) // 行码与列码合成键码(XXXX0000 | 0000XXXX) = XXXXXXXX
{ //switch002
case 0x77 :
s_keyReturn = 0; //0键
break;
case 0x7b :
s_keyReturn = 1; //1键
break;
case 0x7d :
s_keyReturn = 2; //2键
break;
case 0x7e :
s_keyReturn = 3; //3键
break;
case 0xb7 :
s_keyReturn = 4; //4键
break;
case 0xbb :
s_keyReturn = 5; //5键
break;
case 0xbd :
s_keyReturn = 6; //6键
break;
case 0xbe :
s_keyReturn = 7; //7键
break;
case 0xd7 :
s_keyReturn = 8; //8键
break;
case 0xdb :
s_keyReturn = 9; //9键
break;
case 0xdd :
s_keyReturn = 10; //a键
break;
case 0xde :
s_keyReturn = 11; //b键
break;
case 0xe7:
s_keyReturn = 12; //c键
break;
case 0xeb :
s_keyReturn = 13; //d键
break;
case 0xed:
s_keyReturn = 14; //e键
break;
case 0xee:
s_keyReturn = 15; //f键
break;
default :break;
}//end of switch002
sg_keyState++;//转状态2
}
else
{
sg_keyState = 0;//两次按键不同,返回状态1
}
break;
}
case 2 :
KEY_INPORT = KEY_ORIGIN;//发按键端口原始状态
KEY_INPORT = KEY_ORIGIN;//再发一次按键端口原始状态
if ((KEY_INPORT & 0x0f) == KEY_ORIGIN)//读列线,
{
sg_keyState = 0; //按键已释放,转0状态
return s_keyReturn; //版本1.1添加语句
}
break;
}//switch
return 255;
}
别外附上硬件连接图:
![](http://cache.amobbs.com/bbs_upload782111/files_46/ourdev_678525TF0MSB.JPG)
(原文件名:未命名2.JPG) |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|