カップブルーブリッジ - 通常のキーボードスキャンマトリックス

まず、原則として一部

ここに画像を挿入説明

注:P36ターンP42、P37のスイッチP44、およびジャンパコネクタ1 2

スキャンキーステータス

2つのキーの状態があり、バウンス状態で、状態が押されました。持続時間は、キーが押さまたは状態決意ボタンによってポップされるかどうかを決定しました。キーの状態とキーは、その後、いくつかの時間後に、キーの状態が再び変更され、状態の変化が発生を説明したのと同じではないの以前の状態がバウンスを完了するために、ボタンを押すと、スキャン状態のキーストローク一定の時間を設定します。このときの動作するので、このキーに対応する機能を実行することができます。使用してkeysta[4][4]ストアに現在のキーを使用しkeyback[4][4]、ボタンの状態を格納します。走査方式によって決定さkeysta[i][j] != keyback[i][j]、ボタンの状態が変更された一致しない場合、この時間が再び決定されkeysta[i][j] != 0、次いで離鍵、すなわち、完全な押圧操作とバウンスは、対応する実行可能ゼロでない場合、キー機能。keystaに割り当てられた値は、好都合keybackすなわちキー状態決意時間の変更後完了したと判断すべきである、なおkeyback[i][j] = keysta[i][j];

unsigned char keysta[4][4] = {{1, 1, 1, 1},      //4*4矩阵按键的状态,1为抬起,0为按下
					  		  {1, 1, 1, 1},
					 		  {1, 1, 1, 1},
							  {1, 1, 1, 1}};
							  
static unsigned char keyback[4][4] = {{1, 1, 1, 1},     
								     {1, 1, 1, 1},
								     {1, 1, 1, 1},
								     {1, 1, 1, 1}};

ラインスキャンとキー列を取得するためにスキャン

定義配列keybuff[4][4]の全て0xffのは、マトリックスキー初期状態と等価です。KEYOUTは、switch文を介してローレベルのみ一行を達成するために、0から3までの時間をそれぞれ可変ラインスキャンサイクルを用いて。スキャンを完了します。次の4つのライン、すなわち、列走査。KEYOUTラインがローに引き下げられると、このときこの時点で、ボタンを押す、そしてのみ対応する列走査IOポートがローレベルになると、ローレベルは、この時点で移動するように左の列を走査することによって得られます対応する位置keybuff。
理想的な状態(ジッタ)キーを1ミリ秒を押下するとし、また、走査間隔は1msであり、対応するkeybuffに対応する値が0xFEのなります。キーは8msの又はより長い場合、またはスキャン間隔は1msを押下された場合も同様に、対応する値に対応するkeybuffは0x00になるであろう。実際には、ボタンジッタ、ジッタが、比較的短い時間だけ一定の連続した期間内で決定され、ボタンの状態は、デバウンス連続動作を完了するために押圧されます。
次いで、必要にkeybuff各数が0x00で、すなわちに等しいか否かが判定される、今ボタンが押下され、スキャン間隔は1msであり、セットデバウンス時間が8msのであると仮定しkeybuff[keyout][i] == 0x00た場合、対応するキーが実際に押さ等しい場合、キーが押されていない等しくないです。デバウンス時間が設定されている場合も同様に、それは、少なくとも4msの4msのキー、すなわち文ができ、アクティブな状態に押圧されることを示している(keybuff[keyout][i]&0x0f) == 0x00と判断することができます。ボタンが4MSよりも長く押された場合に4msのは唯一、かどうかを0に4位を決定する必要があるためと0x0Fのは、高い4の影響を除去することで、簡単な判断はkeybuff[keyout][i] == 0xf0確かに受け入れられません。
決意ボタンが押された後、すなわち、それはすなわち、キーを押して説明割り当てられた番号0を、対応keystaできます。
同様に離鍵が決定され、割り当てられたkeystaの対応する数は、すなわち、離鍵について説明します。

sbit key_out_1 = P3^0;//行扫描
sbit key_out_2 = P3^1;
sbit key_out_3 = P3^2;
sbit key_out_4 = P3^3;

sbit key_in_1 = P4^4;//列扫描
sbit key_in_2 = P4^2;
sbit key_in_3 = P3^5;
sbit key_in_4 = P3^4;

void keyscan()
{
	uchar i;
	static uchar keyout = 0;
	static uchar keybuff[4][4] = {{0xff,0xff,0xff,0xff},
								  {0xff,0xff,0xff,0xff},
							  	  {0xff,0xff,0xff,0xff},
								  {0xff,0xff,0xff,0xff}};
	switch(keyout)
	{
		case 0:key_out_1 = 0;key_out_4 = 1;break;
		case 1:key_out_2 = 0;key_out_1 = 1;break;
		case 2:key_out_3 = 0;key_out_2 = 1;break;
		case 3:key_out_4 = 0;key_out_3 = 1;break;
	}

	keybuff[keyout][0]=keybuff[keyout][0]<<1|key_in_1;
	keybuff[keyout][1]=keybuff[keyout][1]<<1|key_in_2;
	keybuff[keyout][2]=keybuff[keyout][2]<<1|key_in_3;
	keybuff[keyout][3]=keybuff[keyout][3]<<1|key_in_4;

	for(i=0;i<4;i++)
	{
		if((keybuff[keyout][i]&0x0f) == 0x00)
		{
			keysta[keyout][i] = 0;
		}

		else if((keybuff[keyout][i]&0x0f) == 0x0f)
		{
			keysta[keyout][i] = 1;
		}
	}
   keyout++;
   keyout &=0x03;
}

第二に、コード部分

実験プラットフォーム:CT107D
実験チップ:stc15f2k60s2
実験結果:1-16、それぞれは、対応するキーが押下されることを示します。
コードは以下の通りです

#include<stc15f2k60s2.h>

#define uchar unsigned char
#define uint unsigned int

sbit buzz = P0^6;

sbit key_out_1 = P3^0;//行扫描
sbit key_out_2 = P3^1;
sbit key_out_3 = P3^2;
sbit key_out_4 = P3^3;

sbit key_in_1 = P4^4;//列扫描
sbit key_in_2 = P4^2;
sbit key_in_3 = P3^5;
sbit key_in_4 = P3^4;


uchar code duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};//定义段码数组
uchar disbuff[8];//定义显示数字数字

uchar keysta[4][4] = {{1, 1, 1, 1},      //4*4矩阵按键的状态,1为抬起,0为按下
					  {1, 1, 1, 1},
					  {1, 1, 1, 1},
					  {1, 1, 1, 1}};

uchar keymap[4][4] = {{1,2,3,4},	   //按键值数组
					  {5,6,7,8},
					  {9,10,11,12},
					  {13,14,15,16}};

uchar index,num = 0; 
uchar count = 0;

void keyscan()//循环扫描按键
{
	uchar i;
	static uchar keyout = 0;
	static uchar keybuff[4][4] = {{0xff,0xff,0xff,0xff}, //按键初始态
								  {0xff,0xff,0xff,0xff},
							  	  {0xff,0xff,0xff,0xff},
								  {0xff,0xff,0xff,0xff}};
	switch(keyout)//行扫描,保证每一个时刻只有一行为低电平
	{
		case 0:key_out_1 = 0;key_out_4 = 1;break;
		case 1:key_out_2 = 0;key_out_1 = 1;break;
		case 2:key_out_3 = 0;key_out_2 = 1;break;
		case 3:key_out_4 = 0;key_out_3 = 1;break;
	}

	keybuff[keyout][0]=keybuff[keyout][0]<<1|key_in_1;//把读取到的行扫描的IO口电平移位到keybuff对应的数中
	keybuff[keyout][1]=keybuff[keyout][1]<<1|key_in_2;
	keybuff[keyout][2]=keybuff[keyout][2]<<1|key_in_3;
	keybuff[keyout][3]=keybuff[keyout][3]<<1|key_in_4;

	for(i=0;i<4;i++)
	{
		if((keybuff[keyout][i]&0x0f) == 0x00)//中断为1ms,此处为4ms消抖,判断按键是否按下
		{
			keysta[keyout][i] = 0;
		}

		else if((keybuff[keyout][i]&0x0f) == 0x0f)//中断为1ms,此处为4ms消抖,判断按键是否弹起
		{
			keysta[keyout][i] = 1;
		}
	}
   keyout++;
   keyout &=0x03;//对keyout进行清零
}

void keyfun(uchar key_val)//按键功能函数,可以用switch语句选择
{
	num = key_val;
}
void keydrive()//放在主函数不断的判断按键状态是否改变
{
	uchar i,j;
	static uchar keyback[4][4] = {{1, 1, 1, 1},//备用状态数组     
								  {1, 1, 1, 1},
								  {1, 1, 1, 1},
								  {1, 1, 1, 1}};
	for(i=0;i<4;i++)
		for(j=0;j<4;j++)
		{
			   if(keysta[i][j] != keyback[i][j])
			   {
			   		if(keysta[i][j] != 0)
					{
						keyfun(keymap[i][j]);//获取按键值传递给keyfun
					}
			   } keyback[i][j] = keysta[i][j]; //更新状态,方便下一次判断
		}
}


void closebuzz()
{
	P2 = 0xa0;
	buzz = 0;
	P2 = 0x00;
}


void shownum()//显示数字函数
{
	disbuff[0]=num/10;
	disbuff[1]=num%10;
	disbuff[2]=10;
	disbuff[3]=10;
	disbuff[4]=10;
	disbuff[5]=10;
	disbuff[6]=10;
	disbuff[7]=10;
}

void display()//数码管扫描函数
{
	P2 = 0xe0;
	P0 = 0xff;
	P2 = 0x00;

	P2 = 0xc0;
	P0 = 1<<index;
	P2 = 0x00;

	P2 = 0xe0;
	P0 = ~duan[disbuff[index]];
	P2 = 0x00;

	index++;
	index &= 0x07;

}

void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x9A;		//设置定时初值
	TH0 = 0xA9;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1 ; 
}

void time0() interrupt 1
{
	keyscan();
	display();		
}


void main()
{
	closebuzz();
	Timer0Init();
	while(1)
	{
		shownum();
		keydrive();
	}

}


公開された10元の記事 ウォン称賛11 ビュー3723

おすすめ

転載: blog.csdn.net/FuckerGod/article/details/104015816