51单片机(二十九)—— 矩阵键盘输入实验

一、矩阵键盘原理介绍

        在之前的文章中,我们介绍过独立按键的使用,独立按键需要每个按键使用一个IO口进行读取,如果按键比较多,对IO资源的占用比较多。使用矩阵键盘,并采用扫描的方式对按键进行读取是解决按键多的一个有效办法。采用矩阵按键的方式就可以有效的节省I/O资源。4*4的矩阵键盘只需要8个I/O口进行采集。6*6的矩阵键盘只需要12个I/O口就可以采集。

        本实验的硬件电路是一个4X4的矩阵键盘。矩阵键盘的原理图如下图所示。

51单片机(二十九)—— 矩阵键盘输入实验_第1张图片

        由原理图可以看出J23的1~4与矩阵键盘的每一行相连。5~8与矩阵键盘的每一列相连。每一列上设置了上拉电阻。矩阵键盘扫描时,令J23的1~4中的一个为低电平,如果相应的行有按键按下,则J23的5~8中与这个按键对应的信号也被拉低。从而可以判断出按下的按键。

        电路图中D21~D24的作用是实现中断功能。若令J23的1~4都为低电平,有按键按下时,必有一个列信号为低电平,由于二极管的作用,J24也被拉为低电平。如果将J24接在外部中断口上,就可以触发中断。

二、实验例程测试

实验1:查询扫描

        在这个实验中,我们采用查询的方式对矩阵键盘进行读取,这个实验的代码的主函数如下所示。

main()
{
	init_T0();
	for(;;)
	{
		keyma=KEYscan();
		keyvalue=Keychange(keyma);	
		if(keyvalue!=0xff)
		{
			for(n=0;n<7;n++)
			  showdata[n]=showdata[n+1];  //显示的数据向左移位
			showdata[7]=BJTY_DuanMa[keyvalue];     //读取最新的显示值
		}
	}
}

        在主函数中,先初始化T0,T0主要是设置数码管的扫描定时器。在定时器中断中,进行数码管的扫描。之后进入for循环,在否循环中,先调用KEYscan()函数,对矩阵键盘进行扫描,返回值为IO的码值。再调用Keychange(keyma); 函数把码值转换为按键的键值,最后将按键值赋值给数码管的断码进行显示。

        KEYscan()函数是对矩阵键盘进行扫描的函数,函数定义如下所示。函数返回值是8个IO口的码值。

 

unsigned char KEYscan(void) 
{
	unsigned char key;
	KEYboard=0xf0;     //低四位全部拉低
	if(KEYboard!=0xf0) //表示有按键按下
	{
		delay1ms(10);  //去抖
		if(KEYboard!=0xf0)
		{           //表示有按键按下
			KEYboard=0xfe; //扫描第一行将第一行拉低
			if(KEYboard!=0xfe)
			{
				delay1ms(10); //去抖
				if(KEYboard!=0xfe)
					key=KEYboard;
				while(KEYboard!=0xfe);   //等待按键释放
				return key;
			}
			KEYboard=0xfd; //扫描第二行将第二行拉低
			if(KEYboard!=0xfd)
			{
				delay1ms(10); //去抖
				if(KEYboard!=0xfd)
					key=KEYboard;
				while(KEYboard!=0xfd);   //等待按键释放
				return key;
			}
			KEYboard=0xfb; //扫描第三行将第三行拉低
			if(KEYboard!=0xfb)
			{
				delay1ms(10); //去抖
				if(KEYboard!=0xfb)
					key=KEYboard;
				while(KEYboard!=0xfb);   //等待按键释放
				return key;
			}
			KEYboard=0xf7; //扫描第四行将第四行拉低
			if(KEYboard!=0xf7)
			{
				delay1ms(10); //去抖
				if(KEYboard!=0xf7)
					key=KEYboard;
				while(KEYboard!=0xf7);   //等待按键释放
				return key;
			}
		}
	}
	return 0xff;
}

Keychange(keyma)函数的定义如下所示。

unsigned char Keychange(unsigned char y)
{
	switch(y)
	{
		case 0xee:return 0;break;//0 
		case 0xde:return 1;break;//1
		case 0xbe:return 2;break;//2
		case 0x7e:return 3;break;//3
		case 0xed:return 4;break;//4
		case 0xdd:return 5;break;//5
		case 0xbd:return 6;break;//6
		case 0x7d:return 7;break;//7
		case 0xeb:return 8;break;//8
		case 0xdb:return 9;break;//9
		case 0xbb:return 10;break;//a
		case 0x7b:return 11;break;//b
		case 0xe7:return 12;break;//c
		case 0xd7:return 13;break;//d
		case 0xb7:return 14;break;//e
		case 0x77:return 15;break;//f
		default:return 0xff;break;
	}
}

        烧写之后可以看到实验现象,按下矩阵键盘S1~S16中的任意一个按键,S1~S16这16个按键,分别与数值0~F相对应。按下的按键可以在数码管上显示出来。每按一次按键,数码管上的显示内容向左移一位。

 

    矩阵键盘的扫描与数码管的扫描大同小异。扫描个过程如下:

    1、令行线输出全为0;

    2、如果列线输入不全是1,则有按键按下;

    3、扫描第一行,如果列线不全是1,则第一行有按键按下,返回按键码值;

    4、扫描第二行,如果列线不全是1,则第二行有按键按下,返回按键码值;

    5、扫描第三行,如果列线不全是1,则第三行有按键按下,返回按键码值;

    6、扫描第四行,如果列线不全是1,则第四行有按键按下,返回按键码值。

实验2:中断扫描

        在这个实验中,我们采用中断方式进行矩阵键盘的读取。例程的主函数如下所示。

main()
{
	init_T0();
	EX0=1;         //打开外部中断0
	IT0=1;         //外部中断采用边沿触发

	for(;;)
	{
		KEYboard=0xf0;     //低四位全部拉低		
		if(flag==1)
		{
			flag=0;
			keyma=KEYscan();
			keyvalue=Keychange(keyma);	
			if(keyvalue!=0xff)
			{
				for(n=0;n<7;n++)
				  showdata[n]=showdata[n+1];  //显示的数据向左移位
				showdata[7]=BJTY_DuanMa[keyvalue];     //读取最新的显示值
			}
		}
	}
}

在主函数中,使能了外部中断的通道0,采用边沿触发模式。一旦有按键按下,则会触发外部中断,在中断处理函数中,将标志位flag置1。在主函数中,判断标志位为1时,进行键盘的扫描,并在数码管上显示。具体的扫描方法及显示方法与查询扫描方式是相同的。

你可能感兴趣的:(单片机应用)