天天看点

【单片机学习笔记】(四)———独立按键(状态机消抖、三行代码)

一、原理图

【单片机学习笔记】(四)———独立按键(状态机消抖、三行代码)

二、独立按键电路分析

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;
}
           

继续阅读