分享

51入门系列教程| 第一次被控制

 Zmflc 2016-04-28

前面一贴简单讨论了一下51单片机的IO输出功能

既然是IO,有output肯定就有input

今次咱聊聊input,输入功能

有了input,51就能够根据输入的信号

去做出下一步工作的决定

其实单片机的输入不外乎就是两种

一是数字输入,由单片机去判断输入的高低电平

再就是模拟输入,最典型的就是内置ADC外设的单片机

可以把外部输入的电压值与基准电压进行比较

从而得到一定数值的二进制编码

譬如基准电压3.3v,12位的线性ADC外设

就可以将外部输入的0-3.3v电压按比例用0-4096的十进制数去表示

换成二进制便是000000000000-111111111111

限于手头上51片子没有AD这个外设

咱今天聊的输入,就从数字输入下手

一、按键基本原理

先上电路

51入门系列教程| 第一次被控制--按键

先看上面一个图

P0.1口,连接到一个10k的电阻,上拉到电源Vcc(这里Vcc=5.0v)

同时连接到按键的一端

按键的另一端则直接连到地

简单分析一下这个电路

当按键没有按下的时候

10k电阻和P0.1口没有连接到地

由于P0端口是开漏输出,可以看做是悬空

那么经过10k电阻的电流为0,即10k电阻的压降为0

这个时候,可以认为P0.1口的电位是5.0v,一个高电平

So,按键没有按下,单片机可以认为P0.1口输入了一个逻辑“1”,也就是高电平

当按键按下时

P0.1口和10k电阻均被连接到了地

这个时候,P0.1口的电位直接被拉到0v,也就是地

So,单片机可以认为P0.1口输入了一个逻辑“0”,也就是低电平

这里尤其注意一下这个10K电阻的作用

名曰上拉电阻

它的存在是非常有必要的

没有这个电阻,P0.1口直接连接到按键一端或者电源,都会产生不好的后果

如果直接连至电源,按键按下的时候,Vcc和地……,后果你懂的……

如果直接连接到按键的一端,在按键按下前

P0.1都是悬空的,外界的干扰(EMI之类),非常容易引起单片机的误判

它的作用主要是按下前稳定电平、按下后限流

在按键按下的时候,电源—10k电阻—地 这个回路中

会产生5/100000=5mA电流,产生一定的功耗

有朋友会想,加大电阻就可以解决这个问题了呀

但是电阻太大的话,可能会出现开路情况

So,几k到几十k是比较合适的

再看下面一个图

嗯,简单的发光二极管回路

这里就不多解释了

顺道拿电木板焊了个电路

51入门系列教程| 第一次被控制--按键电源、地和2个IO口用排针等插

51入门系列教程| 第一次被控制--按键

菊花面,10k上拉电阻和220欧LED限流电阻

这个电木板质量真次,焊盘掉了好几个

51读端口的代码特别简单

只要直接按位或者按port来逐位读取即可

譬如要把P01口的逻辑值赋给变量temp

直接temp = P01即可

P01输入一个低电平,temp=0x00

P01输入一个高电平,temp=0x01

上个测试代码

#include

sbit P11 = P1^1;//按位定义

sbit P01 = P0^1;

int main()

{

while(1)

{

if(P01==0)//判断P01口的值,0为按下

{P11 = ~P11;}//按下后的操作,P11口取反

else (P11 = P11;)

}

return 0;

}

简单阅读一下代码

大概的功能就是判断P01口电平是否为0

为0的话,P11口电平取反,也就是LED点亮或者熄灭

编译下载,看看结果

51入门系列教程| 第一次被控制--按键

不难发现

按键虽然能够控制51去点亮或者熄灭LED

但是似乎并不是那么顺手

不能非常准确地操作LED的亮或者灭

为嘛?

二、去抖

在解决上面问题之前

必须意识到,按键其实是一个机械弹性开关结构

在按下或者松开的瞬间,也就是机械触点断开、闭合时

不会稳定地接通或者断开,存在一连串的抖动

这种抖动时间与按键的机械特性有关,几个ms到几十个ms都有可能

由于51执行代码的速度是us级

So,自己感觉只按下了一次按键

其实51已经反复多次执行了按键按下的操作

所以造成上面gif中的现象

所以,按键去抖,是无论哪种单片机都需要面临的问题

当然,有些比较有特点的单片机会有按键相关的外设,无需过多关注去抖,这个在此不讨论

有关去抖,有硬件和软件两种办法

硬件上去抖的办法

第一种是使用RS触发器/锁存器

51入门系列教程| 第一次被控制--按键

锁存器的工作特点就决定了,即使有按键抖动,也不会影响上如两个与非门构成的RS锁存器的输出

再一种是在按键上并联一个合适大小的电容

51入门系列教程| 第一次被控制--按键

其实就是利用电容充放电的特性,无它

硬件去抖,基本上不占用单片机的资源

致命的缺陷是需要额外的器件

会使PCB面积、BOM、成本有所增加

在成本为王的时代,基本上这种办法很少有人使用了

但是非常可靠

再来看看软件去抖

第一种是使用延时去抖,是目前用得比较多的

上个代码

#include

sbit P11 = P1^1;

sbit P01 = P0^1;

unsigned char flag;

void delay_ms(unsigned int xms)//定义一个ms级的延时函数

{

unsigned int i,j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--);

}

}

unsigned char keyscan()//扫描按键

{

unsigned char key_value;

if(P01 == 0)//P01被拉低,也就是有按键按下

{

delay_ms(100);//延时100ms

if(P01 == 0) //延时后再判断P01口是不是被拉低(按下)

{key_value = 1;}//如果是,键值位置1

else {key_value = 0;}//否则置0

}

return key_value;//返回键值

}

void key_op()

{

if(flag) //判断标志位,然后进行操作

{

P11 = ~P11;

flag = 0;

}

else {;}

}

int main()

{

while(1)

{

flag = keyscan();//把扫描的键值赋给标志位

key_op();//根据标志位进行操作

}

return 0;

}

简单分析一下上面的代码

最最核心的就是

如果发现P01的按键被按下

就延时100ms后再读一下P01的值

注意一下,这里的100ms其实和按键的机械特性有关

根据实际情况调整

如果还是被按下的状态,则认为按键确实被按下

单片机再进行下一步操作

上个GIF

51入门系列教程| 第一次被控制--按键

可以发现

按键已经可以很准确地控制LED的亮灭了

但是,单片在执行delay_ms(100)的时候

其它任何事情都不能做呀

所以很多时候,这个延时会采用定时器中断来完成

这个后面再讨论

其实还有一种不需要延时的去抖方法

可以理解成一个状态机

上代码

#include

sbit P11 = P1^1;

sbit P01 = P0^1;

unsigned char flag;

void delay_ms(unsigned int xms)

{

unsigned int i,j;

for(i=xms;i>0;i--)

{

for(j=124;j>0;j--);

}

}

unsigned char keyscan()

{

static unsigned char key_state = 0;

static unsigned char key_value = 0;

unsigned char key_press,key_return = 0;

key_press = P01; //读按键

switch(key_state)

{

case 0 ://按键初始态

if(key_press == 0){key_state = 1;}//按键被按下,但需要确认

break;

case 1://按键进行确认

if(key_press == 0)//如果还是被按下,则开始决定键值

{

key_value = 1;

key_state = 2;//确定被按下,转到按键被按下状态

}

else { key_value = 0;}//否则认为是抖动

break;

case 2://按键释放状态

if(key_press == 1)

{

key_return = key_value; //按键释放后输出键值

key_value = 0;

key_state = 0; //按键释放,进入按键初始态

}

break;

}

return key_return; //返回键值

}

void key_op()

{

if(flag)

{

P11 = ~P11;

flag = 0;

}

else {;}

}

int main()

{

while(1)

{

flag = keyscan();

key_op();

}

return 0;

}

利用状态机的编程思想

代码上有解释了,这里不过多深入讨论

上GIF

51入门系列教程| 第一次被控制--按键

可以看得出来

其实效果也还不错

三、矩阵键盘

到这里,一个基本键盘需要考虑的东西

大概就是这么多了

还有一种针对比较多按键的电路组态

叫做是矩阵键盘

简单介绍一下吧

上个结构图

51入门系列教程| 第一次被控制--按键

上图是个4x4键盘,16个按键

按照前面的方法,得需要16个IO口才能完成接入

这里其实只需要P1口的8个端口即可

这种矩阵键盘判断按键的方法有好几种

用的比较多的有2种

一是行/列扫描法,分两步

1、判断键盘中有无键按丿将全部行线Y0-Y3置低电平,然后检测列线的状态。只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线丿根行线相交叉皿个按键之中。若所有列线均为高电平,则键盘中无键按下

2、判断闭合键所在的位置 在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键

再一个是翻转法,三步

1、行线输出全为0,读出列线值。

2、列线输出上次读入的列线值。

3、读入行线值,并与前次列线值组合,生成组合码值。根据这个组合码来确定被按下的按键。

没来得及做个矩阵键盘

如有疑问,可把问题发送给“云汉电子社区”微信公众号平台,我们会及时回复,关注公众号可阅读更多51系列教程!我们欢迎您的沟通!

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多