51单片机:独立按键

按键简介

51上的按键又名“轻触按键”、“轻触开关”(实际上按着挺费劲的,还有点费手),一种电子开关,在电路中按下导通、松开断开。

原理是通过按压柱塞,使按键内部的金属簧片(反作用弹簧)形变,使接点相接触,以此导通电路。

按键结构

按键拆解结构如图:(拆了两个,经费爆炸啊同伙们!)

 

 

 ps:注意端子与接点的连接状态;1和4初始导通、2和4初始导通,1和2初始不导通、3和4初始不导通;按下的时候,簧片被压扁,3个接点全部被连接在一起,4个端子也就都连接在一起、互相导通了(很巧妙的设计,有没有?)。

使用and消抖处理

“得益”于按键的设计,当断开、闭合时,由于簧片的弹性作用,在闭合时不会马上稳定地接通,在断开时也不会一下子断开,而在闭合及断开的瞬间均伴随有一连串的抖动,为了消除抖动所带来的不良影响,所做的措施就是按键消抖。

 下图是按下时电平的波形图(字丑勿喷,狗头保命):

 

抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键稳定闭合时间的长短则由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引起按键被误读多次。为了确保 CPU对按键的一次闭合仅作一次处理,必须进行消抖。

按键消抖有两种方式,一种是硬件消抖,另一种是软件消抖。为了使电路更加简单(为了更便宜),通常采用软件消抖。51开发板也是采用软件消抖,一般来说按键消抖就是先检测按键的状态(电平高低),如果得到按键状态(电平)改变之后,延时一段时间(我是11ms,保险一点),再次读取按键的状态(电平),如果按键状态(电平)是改变后的,那么说明按键已经按下或者松开。

各种简单应用及代码

肯定有更加牛(简单、稳定、高效)的消抖代码,我也懒得去求大佬要源码了,各位同伙有兴趣的话就自己研究去吧。

下图是普中51单片机的按键电路图:

注意P3^1和P3^0的位置,啧啧,这么多年了,这俩的位置还是这么令人迷惑,谜之设计啊。

1、按一次按键,就改变led一次状态:

以led的状态反映消抖成功,自己其实可以试下不消抖是什么现象的,更能直观的感受到消抖的好处。

#include <reg52.h>
#include <intrins.h>         //有nop

sbit led=P2^7;
sbit k1=P3^1;

void Delay11ms()		//@11.0592MHz,11毫秒
{
	unsigned char i, j;
	_nop_();
	_nop_();
	_nop_();
	i = 119;
	j = 82;
	do
	{
		while (--j);
	} while (--i);
}

void indpendent_key()
{
	if(k1==0)
	{
		Delay11ms;
		if(k1==0)
			led=!led;
		 while(!k1);      //检测按键是否松开
	}
}


void main()
{
	while(1)
	{
		independent_key();
	}
}	

2、用不同的独立按键对led进行不同的操作

K1左移led灯,K2右移led灯。

#include <reg52.h>

sbit k1=P3^1;
sbit k2=P3^0;

void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 108;
	j = 145;
	do
	{
		while (--j);
	} while (--i);
}

unsigned char n;

void main()
{
	P2=~0x01;				//上电D1点亮
	while(1)
	{
		if(k1==0)
		{
 			Delay10ms;
			while(k1==0);
			Delay10ms;
			n++;		       //n自增
			if(n>=8)	//限制n自增范围
				n=0;
			P2=~(0x01<<n);	//led的第n+1位亮
		}
		if(k2==0)
		{
			Delay10ms;
			while(k2==0);
			Delay10ms;
			if(n==0)	//n减到0后变为7
				n=7;
			else			//n未减到0,自减
				n--;
			P2=~(0x01<<n);	//led的第n+1位点亮
		}
	}
}

K1增加一个led亮,K2减少一个led

#include <reg52.h>

sbit k1=P3^1;
sbit k2=P3^0;

void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 108;
	j = 145;
	do
	{
		while (--j);
	} while (--i);
}

unsigned char n;

void main()
{
	P2=0xfe;				//上电D1点亮
	while(1)
	{
		if(k1==0)
		{
 			Delay10ms;
			while(k1==0);
			Delay10ms;
			n++;		       //n自增
			if(n>=8)	//限制n自增范围
				n=0;
			P2=0xfe<<n;	//led增加1位亮
		}
		if(k2==0)
		{
			Delay10ms;
			while(k2==0);
			Delay10ms;
			if(n==0)	//n减到0后变为7
				n=7;
			else			//n未减到0,自减
				n--;
			P2=0xfe<<n;	//led减少1位点亮
		}
	}
}

注意两端代码是有差别的哦,第二个代码搞不好还有的小BUG,不过上机能运行就是好代码!(手动滑稽,狗头保命)

萌新上路,制作不易,如有错误还请评论区指正。各位帅气逼人、美若天仙、颜值爆表的看官老爷点个赞吧,求求了。(在线卑微求赞)

  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
当然可以!下面是一段利用普中51单片机矩阵键盘控制lcd1602的程序: ```c #include <reg51.h> #define LCD_PRT P0 sbit RS = P1^0; sbit EN = P1^1; void LCD_Init(); void LCD_DisplayChar(unsigned char); void LCD_DisplayString(char*); void Delay(unsigned int); void MatrixKeypad_Init(); unsigned char MatrixKeypad_Scan(); void main() { MatrixKeypad_Init(); LCD_Init(); while(1) { unsigned char key = MatrixKeypad_Scan(); switch(key) { case '1': LCD_DisplayString("你按下了1"); break; case '2': LCD_DisplayString("你按下了2"); break; case '3': LCD_DisplayString("你按下了3"); break; case '4': LCD_DisplayString("你按下了4"); break; case '5': LCD_DisplayString("你按下了5"); break; case '6': LCD_DisplayString("你按下了6"); break; case '7': LCD_DisplayString("你按下了7"); break; case '8': LCD_DisplayString("你按下了8"); break; case '9': LCD_DisplayString("你按下了9"); break; case '*': LCD_DisplayString("你按下了*"); break; case '0': LCD_DisplayString("你按下了0"); break; case '#': LCD_DisplayString("你按下了#"); break; default: break; } } } void MatrixKeypad_Init() { // 设置矩阵键盘的行为输入引脚 // 设置矩阵键盘的列为输出引脚 // 初始值为高电平(输出1) // 内部上拉电阻使得行默认是高电平状态 P2 = 0xFF; P3 = 0x0F; } unsigned char MatrixKeypad_Scan() { unsigned char col = 0, row = 0; // 扫描列 P3 = 0x0F; do { Delay(5); // 延时,为了稳定扫描结果 col = P3 & 0x0F; }while(col == 0x0F); // 确定列,对应的位会是0 P3 = 0xF0; do { Delay(5); row = P3 & 0xF0; }while(row == 0xF0); row = row >> 4; // 右移四位,得到行号 // 返回按键值 if(col == 0x0E) return row*3+1; // 列1 if(col == 0x0D) return row*3+2; // 列2 if(col == 0x0B) return row*3+3; // 列3 return 0; // 如果没有按键按下,返回0 } void LCD_Init() { Delay(50); LCD_PRT = 0x30; // 发送函数设置指令 RS = 0; EN = 1; Delay(5); EN = 0; Delay(5); LCD_PRT = 0x30; RS = 0; EN = 1; Delay(5); EN = 0; Delay(5); LCD_PRT = 0x30; RS = 0; EN = 1; Delay(5); EN = 0; Delay(5); LCD_PRT = 0x38; // 设置数据总线宽度和显示行数 RS = 0; EN = 1; Delay(5); EN = 0; Delay(5); LCD_PRT = 0x0C; // 开启显示,无光标,不闪烁 RS = 0; EN = 1; Delay(5); EN = 0; Delay(5); LCD_PRT = 0x06; // 光标右移,不移动显示 RS = 0; EN = 1; Delay(5); EN = 0; Delay(5); } void LCD_DisplayChar(unsigned char ch) { LCD_PRT = ch; RS = 1; EN = 1; Delay(5); EN = 0; } void LCD_DisplayString(char* str) { while(*str) // 遍历字符串 { LCD_DisplayChar(*str++); } } void Delay(unsigned int n) { unsigned int i, j; for(i = 0; i < n; i++) { for(j = 0; j < 10; j++); } } ``` 本程序通过MatrixKeypad_Init()函数和MatrixKeypad_Scan()函数来初始化和扫描矩阵键盘,通过LCD_Init()函数、LCD_DisplayChar()函数和LCD_DisplayString()函数来初始化和显示LCD1602。程序中,MatrixKeypad_Scan()函数返回按键对应的ASCII码,然后根据不同的键进行不同的处理,最后将处理结果显示在LCD1602上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值