楼主的那个程序我看不太懂:不过根据你的大概意思更改了一下程序,希望对你有帮助!下面是我的程序代码:
/********************************************************************
* 文件名 : 矩阵键盘.c
* 描述 : 该文件实现了 4 * 4 键盘的试验。通过数码管的最后一位来显示
当前的按键值。
*********************************************************************/
#include
#include
#define uint unsigned int
#define uchar unsigned char
uchar code table[16] = {0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71}; //用于数码管显示 本程序未用
uchar Key; //读出的键值
/********************************************************************
* 名称 : Delay_1ms()
* 功能 : 延时子程序,延时时间为 1ms * x
* 输入 : x (延时一毫秒的个数)
* 输出 : 无
***********************************************************************/
void Delay_1ms(uint i)//1ms延时
{
uchar x,j;
for(j=0;j
for(x=0;x<=148;x++);
}
/********************************************************************
* 名称 : delay()
* 功能 : 延时,延时时间大概为140US。
* 输入 : 无
* 输出 : 无
***********************************************************************/
void delay()
{
int i,j;
for(i=0; i<=10; i++)
for(j=0; j<=2; j++);
}
/********************************************************************
* 名称 : Keyscan()
* 功能 : 实现按键的读取。下面这个子程序是按处理 矩阵键盘 的基本方法处理的。
* 输入 : 无
* 输出 : 按键值
***********************************************************************/
uchar Keyscan(void)
{
uchar i,j, temp, Buffer[4] = {0xef, 0xdf, 0xbf, 0x7f};
for(j=0; j<4; j++)
{
P1 = Buffer[j];
temp = 0x01;
for(i=0; i<4; i++)
{
if(!(P1 & temp))
{
return (i+j*4); //这里返回的是按键牌排列值!
}
temp <<= 1;
}
}
}
/********************************************************************
* 名称 : InitTimer0()
* 功能 : 用于定时器初始化。
* 输入 : 无
* 输出 :
***********************************************************************/
unsigned int Timer_1s=0;//定时器中断响应次数变量
//定时时间长度=定时中断响应时间*定时中断响应次数
void InitTimer0()
{
// AUXR=0x80; //定时时钟为Sysclk,即晶振时钟 实用于具有单时钟周期的单片机系列
//特别的还需要注意时钟设置在其它模块中的设置,如波特率的定时器1时钟设置
TMOD = 0x21; //定时器0工作于方式1,,16位定时,定时器1为波特率发生器
//特别地,高四位控制定时器1,低四位控制定时器0,
//所以此处需要注意程序中是否并存定时器1工作,如串口就需要定时1的设置为TMOD=0x20
TH0 = 0x0B8; //定时装如初值 //定时1000us 即1ms
TL0 = 0x00; //定时其它值可由需要重新计算初值
ET0 = 1; //允许中断
TR0 = 1; //启动定时器
}
/********************************************************************
* 名称 : Timer0Interrupt()interrupt 1
* 功能 : 定时器中断。
* 输入 : 无
* 输出 :
***********************************************************************/
void Timer0Interrupt() interrupt 1
{
TR0 = 0; //关闭定时器
TH0 = 0x0B8; //重装初值
TL0 = 0x00;
Timer_1s++; //中断响应次数自加1
if(Timer_1s=20) //可以在此处调节按键的扫描时间
{
/*一下是扫描按键并带返回值的结果*/
P1 = 0xf0;
if(P1 != 0xf0)
{
Delay_1ms(15); //按键消抖
if(P1 != 0xf0)
{
Key = Keyscan();
}
}
}
TR0 = 1; //启动定时器
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void Main(void)
{
InitTimer0();//初始化定时器
EA =1; //开中断
while(1)
{
switch (Key) //判断键值(那一个键按下)
{
case 0: /*加入需要执行该按键下的程序*/; break; //假设0号按键被按下
case 1: /*加入需要执行该按键下的程序*/; break;
case 2: /*加入需要执行该按键下的程序*/; break;
case 3: /*加入需要执行该按键下的程序*/; break;
case 4: /*加入需要执行该按键下的程序*/; break;
case 5: /*加入需要执行该按键下的程序*/; break;
case 6: /*加入需要执行该按键下的程序*/; break;
case 7: /*加入需要执行该按键下的程序*/; break;
case 8: /*加入需要执行该按键下的程序*/; break;
case 9: /*加入需要执行该按键下的程序*/; break;
case 10: /*加入需要执行该按键下的程序*/; break;
case 11: /*加入需要执行该按键下的程序*/; break;
case 12: /*加入需要执行该按键下的程序*/; break;
case 13: /*加入需要执行该按键下的程序*/; break;
case 14: /*加入需要执行该按键下的程序*/; break;
case 15: /*加入需要执行该按键下的程序*/; break;
default: break;
}
}
}
办法1、直接把你编写的这部分程序拷到中断服务中,注意变量的声明,注意其他位置不好调用keyi()和delay()了。风险是按住键不松开的话,会影响中断的时间。楼上兄弟意识到这个问题,但解决的不够完美。
办法2、针对你的设计,我写了个50mS中断扫描做的行反转读键,你调调看。通过判断按键次数来去抖,松开时处理。如果需要连续处理,也可稍微改动下完成。在main主程序中分支语句处理CurrentKey,处理完后清零即可。【个人认为,我的比较精炼点,欢迎砸砖】
unsigned char CurrentKey;
void ISRForT0(void) interrupt 1
{
unsigned char key;
static unsigned char LastKey=0,dd=0;
TH0=(-50000)>>8;
TL0=(-50000)&0xff;
//P1=0xf0;//无需延时,退出时预置,此处取掉。
key=P1;
P1=key|0xf; P1=key|0xf; P1=key|0xf; P1=key|0xf;//简单延时
key=P1;
P1=0xf0;
if(key==0xff) //键松开处理
{
if(dd>(200/50)) //1、假设200mS抖动,50为实际定时时间。
{
CurrentKey=LastKey; //键值CurrentKey.
dd=0;
}
LastKey=0; //2、不满足抖动条件。
}
if((key==LastKey)&&(dd<100)) dd++;
if((key!=0xff)&&(key!=LastKey)) //新键按下
{LastKey=key; dd=0;} //保存新的按键。
}
以TR0为例
void time_init(void)
{
TMOD=0x11;
TH0=(65536-t)/256; //time ms
TL0=(65536-t)%256;
ET0=1;
EA=1;
}
void time_0(void) interrupt 1
{
TH0=(65536-t)/256; //time ms
TL0=(65536-t)%256;
judge();//键扫描
//keyboard_mark=1;//若键扫描执行时间太长则不适用直接调用,加入扫描指针
}
bit keyboard_mark;
void main ()
{
system_set();//端口初始化
time_init();//定时器初始化
TR0=1;
/*
if(keyboard_mark)
{ judge();//键扫描
keyboard_mark=1;}
*/
}