天天看點

【單片機學習筆記】(四)———獨立按鍵(狀态機消抖、三行代碼)

一、原理圖

【單片機學習筆記】(四)———獨立按鍵(狀态機消抖、三行代碼)

二、獨立按鍵電路分析

J5跳帽接23,即BTN,實作獨立按鍵功能。

當獨立按鍵中有鍵按下時,P30~P33中對應的IO口變為低電平0,即可确認是哪個按鍵按下。

三、代碼實作

狀态機消抖

每隔10ms調用該函數,配合定時器使用。

#define KEY P3
#define key_state_0 0 //判斷按鍵是否按下
#define key_state_1 1 //判斷按鍵是否抖動
#define key_state_2 2 //判斷按鍵是否釋放

狀态機消抖
unsigned char scan_key()
{
	static char key_state=0;//狀态值
	unsigned char key_return=0;//傳回值
	unsigned char key_press;//鍵值
	
	key_press=KEY&0x0f;//屏蔽高四位
	
	switch (key_state)
	{
		case key_state_0:
			if (key_press!=0x0f)
				key_state=key_state_1;
			break;
			
		case key_state_1:
			if (key_press!=0x0f)
			{
				switch (key_press)
				{
					case 0x07:
						key_return=4;break;//S4
					case 0x0b:
						key_return=5;break;//S5
					case 0x0d:
						key_return=6;break;//S6
					case 0x0e:
						key_return=7;break;//S7
				}
				key_state=key_state_2;
			}
			else
				key_state=key_state_0;
			break;
			
		case key_state_2:
			if (key_press==0x0f)
				key_state=key_state_0;
			break;
	}
	return key_return;
}
           

三行代碼

每隔10ms調用該函數,配合定時器使用。

#define KEY P3
unsigned char Trg;//判斷哪個按鍵按下
unsigned char Cont;//判斷按鍵是否釋放

//三行代碼
void scan_key()
{
	unsigned char ReadData=KEY^0xff;//^異或 相同為0 不同為1
	Trg=ReadData&(ReadData^Cont);
	Cont=ReadData;
}
           

四個獨立按鍵按鍵數字顯示在數位管上 狀态機消抖 定時器中斷實作

#include <STC15F2K60S2.h>

#define KEY P3
#define key_state_0 0 //判斷按鍵是否按下
#define key_state_1 1 //判斷按鍵是否抖動
#define key_state_2 2 //判斷按鍵是否釋放

unsigned char scan_key();//按鍵掃描函數
void display();//顯示函數
void Timer0Init(void);//定時器

code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共陽數位管段碼
unsigned char dspbuf[8]={11,11,11,11,11,11,11,0};//顯示緩沖區
unsigned char dspcom=0;
unsigned char key_flag;//消抖标志

//主函數
void main()
{
	unsigned char x;
	Timer0Init();
	EA=1;
	ET0=1;

	while(1)
	{
		if (key_flag==1)
		{
			key_flag=0;
			x=scan_key();
			if (x==4)
				dspbuf[7]=x;
			if (x==5)
				dspbuf[7]=x;
			if (x==6)
				dspbuf[7]=x;
			if (x==7)
				dspbuf[7]=x;
		}
	}
}

//定時器
void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定時器時鐘1T模式
	TMOD &= 0xF0;		//設定定時器模式
	TL0 = 0xCD;		//設定定時初值
	TH0 = 0xD4;		//設定定時初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定時器0開始計時
}

//中斷服務函數
void isr_timer_0() interrupt 1
{
	static unsigned char count=0;
	count++;
	if (count==10)//10ms
	{
		count=0;
		key_flag=1;
	}
		
	display();
}

//按鍵掃描函數
unsigned char scan_key()
{
	static char key_state=0;//狀态值
	unsigned char key_return=0;//傳回值
	unsigned char key_press;//鍵值
	
	key_press=KEY&0x0f;//屏蔽高四位
	
	switch (key_state)
	{
		case key_state_0:
			if (key_press!=0x0f)
				key_state=key_state_1;
			break;
			
		case key_state_1:
			if (key_press!=0x0f)
			{
				switch (key_press)
				{
					case 0x07:
						key_return=4;break;//S4
					case 0x0b:
						key_return=5;break;//S5
					case 0x0d:
						key_return=6;break;//S6
					case 0x0e:
						key_return=7;break;//S7
				}
				key_state=key_state_2;
			}
			else
				key_state=key_state_0;
			break;
			
		case key_state_2:
			if (key_press==0x0f)
				key_state=key_state_0;
			break;
	}
	return key_return;
}

//顯示函數
void display()
{
	//消隐
	P2=((P2&0x1f)|0xe0);
	P0=0xff;
	P2&=0x1f;
	
	//位選
	P2=((P2&0x1f)|0xc0);
	P0=(1<<dspcom);
	P2&=0x1f;
	
	//段選
	P2=((P2&0x1f)|0xe0);
	P0=tab[dspbuf[dspcom]];
	P2&=0x1f;
	
	if (++dspcom==8)
		dspcom=0;
}
           

四個獨立按鍵按鍵數字顯示在數位管上 三行代碼法 定時器中斷實作

#include <STC15F2K60S2.h>
#define KEY P3

void scan_key();//按鍵掃描函數
void display();//顯示函數
void Timer0Init(void);//定時器

code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共陽數位管段碼
unsigned char dspbuf[8]={11,11,11,11,11,11,11,0};//顯示緩沖區
unsigned char dspcom=0;
unsigned char key_flag;//消抖标志
unsigned char Trg;//判斷哪個按鍵按下
unsigned char Cont;//判斷按鍵是否釋放

//主函數
void main()
{
	Timer0Init();
	EA=1;
	ET0=1;

	while(1)
	{
		if (key_flag==1)
		{
			key_flag=0;
			scan_key();
			if (Trg&0x08)
				dspbuf[7]=4;//S4
			if (Trg&0x04)
				dspbuf[7]=5;//S5
			if (Trg&0x02)
				dspbuf[7]=6;//S6
			if (Trg&0x01)
				dspbuf[7]=7;//S7
		}
	}
}

//定時器
void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定時器時鐘1T模式
	TMOD &= 0xF0;		//設定定時器模式
	TL0 = 0xCD;		//設定定時初值
	TH0 = 0xD4;		//設定定時初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定時器0開始計時
}

//中斷服務函數
void isr_timer_0() interrupt 1
{
	static unsigned char count=0;
	count++;
	if (count==10)//10ms
	{
		count=0;
		key_flag=1;
	}
		
	display();
}

//三行代碼
void scan_key()
{
	unsigned char ReadData=KEY^0xff;
	Trg=ReadData&(ReadData^Cont);
	Cont=ReadData;
}

//顯示函數
void display()
{
	//消隐
	P2=((P2&0x1f)|0xe0);
	P0=0xff;
	P2&=0x1f;
	
	//位選
	P2=((P2&0x1f)|0xc0);
	P0=(1<<dspcom);
	P2&=0x1f;
	
	//段選
	P2=((P2&0x1f)|0xe0);
	P0=tab[dspbuf[dspcom]];
	P2&=0x1f;
	
	if (++dspcom==8)
		dspcom=0;
}
           

繼續閱讀