查看: 1777|回复: 0

Atmega 128学习笔记第七站---独立按键

[复制链接]

该用户从未签到

发表于 2015-4-30 08:48:22 | 显示全部楼层 |阅读模式
分享到:
学友们今天来学习下怎样使用ATmega128单片机来控制独立按键,在单片机的使用中,有时需要用户输入一些参数或者输入某一个动作来实现某些功能,比如启动或选择某一个设备、设定设备的运行方式等等,这时我们就需要借助于键盘或者外围按键。
     按键或者按钮的原理其实很简单,运用在电路中无非是当按键或按钮按下时,按键就接通两个点,实现线路的导通,按键放开时,就断开两个点,实现线路的断开。运用到ATmega128单片机中,一般就是将按键的一个点连接到高电平(也就是数字逻辑1),另一个点连接到低电平或地上(也就是数字逻辑0),然后将其中一个点通过限流电阻连接到ATmega128单片机的IO引脚上面,当按键被按下或者释放时候,所连接的单片机IO引脚的电平就会随之改变,从而使单片机判断按键是否被按下。
     我们在测量按键被按下时的电压时候发现,按键两端的电平的变化会有一个抖动的过程,见下图1:

                    图1.按键被按下时电平变化过程
      这是由于按键本身机械方面的特性加上操作它的人为的因素所决定的,所有的按键在按下或释放过程中都不可避免的会有抖动过程的发生,一般抖动的时间在10ms左右,加上人为的因素,有的按键在按下时候可能会有多次抖动,如果ATmega128单片机在读取IO引脚的电平时候,直接根据电平的变化来判断按键的状态,而不对按键的抖动做任何处理的话,那么由于按键的多次抖动导致的电平变化也被ATmega128单片机人为发生了动作而被多次读取,这样就会把每次的抖动动作而看成是一次按键操作,这样无疑就会产生很多错误,所以我们在单片机判断时候必须对抖动动作进行处理,消除抖动动作对按键操作的影响,一般消除抖动动作分硬件电路实现和软件程序实现,硬件电路就是增加消抖电路,一般使用一个电容或者使用一个低通滤波器,依靠积分原理来消除抖动,软件方面实现就是增加消抖函数,一般都是采用增加读取的延时,延时之后IO引脚再进行读取,两次读取的结果进行比较,看读取的电平是否相同,增加这种消抖函数无疑浪费了一些时间,会影响单片机的效率,但是可以有效的避免误动作的判断,而且相对于整体而言,造成的时间非常短,在很多场合,这种方法给工程师们采用。
     给大家介绍一下典型的ATmega128单片机连接外围按键的应用电路,如下图2:

                    图2. ATmega128单片机控制8个独立按键的典型电路图
     在上图2中,8个按键的一端连接到了地,另一端和ATmega128单片机的PA端口相连,并且通过上拉电阻连接到了VCC,当按键被按下时,线路导通,PA引脚上面获得低电平,当按键不被按下时,按键没有导通,PA引脚上面获得高电平,我们可以使用查询端口状态的方式来获取按键的状态,也可以通过外部中断的方式来获取,这个后面我们学习到外部中断时候再给大家说。
     介绍完典型的按键电路,我们就要开始我们今天的例程,今天的例子是采用4个独立按键来控制两组LED的变化,使用PA0---PA3这四个IO引脚来控制4个按键,这4个按键用来控制16个LED的闪烁的顺序,如下图3:

                    图3. 例程电路设计图

     当按下PA0引脚的按键时候,左边的8个LED从下往上移动,当按下PA1引脚的按键时候,左边8个LED从上往下移动。同理当按下PA2引脚的按键时候,右边的8个LED从下往上移动,当按下PA3引脚的按键时候,右边8个LED从上往下移动。
     下面就是编代码:
#include<iom128v.h>
unsigned char Recent_Key=0xFF;
void delayms(uint ms) //声明延时函数           
void Port_init(void)   //IO端口初始化函数
{
DDRA=0xF0;     // PA端口的连接按键的口设置为输入口,用来读取按键的电平值。
PORTA=0xFF;
DDRD=0xFF;
PORTD=0xFF;   //PD端口设置为输出,用来取按键的值。
DDRE=0xFF;
PORTE=0xFF;     //PE端口同PD端口都设置为输出,用来取按键的值。
}
void keyDeal(void)
{
if(Recent_Key!=PINA)
    {
   delayms(10); //延时,用来消除抖动
   if(Recent_Key!=PINA)
     {
       Recent_Key=PINA; // 再次读取按键的状态
       switch(Recent_Key)    //状态语句,用来根据按键的状态判断对应的动作。
          {
         case 0xFE:       // 动作是第一组从上往下移动
           {
             if(PORTD==0)
               {
                PORTD=0xFF;
                }
             PORTD<<=1;
             }
         break;
         case 0xFD:        // 动作是第一组从下往上移动
           {
             if(PORTD==0)
               {
                PORTD=0xFF;
                }
             PORTD>>=1;
             }
         break;
         case 0xFB:       // 动作是第二组从上往下移动
           {
             if(PORTE==0)
               {
                PORTE=0xFF;
                }
             PORTE<<=1;
             }
         break;
         case 0xF7:          // 动作是第二组从下往上移动
           {
             if(PORTE==0)
               {
                PORTE=0xFF;
                }
             PORTE>>=1;
             }
         break;
         default:break;
           }
       }
   }
}
void main(void)
{
Port_init();
while(1)
   {
    keyDeal();   //调用控制函数
    }
}

void Delayms(uint ms)            
{
   uint i,j;
   for( i=0;i<ms;i++)
   for(j=0;j<1141;j++);     
}
     代码编译好了之后,下载到板子上面看看效果吧。。。。。
     其实这只是举了个例子用按键来实现LED灯,我们可以随意的用按键来实现我们想实现的功能,比如之前学习的数码管,我们也可以通过按键来实现我们想显示的特点的数字或者字符,或者数码管的显示方式按照按键的设定等等。。。。大家可以下面开动脑筋通过按键实现各种功能,也欢迎大家分享你们的小发明。。。。
     感谢大家观看,我们下期再见
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /2 下一条

手机版|小黑屋|与非网

GMT+8, 2024-4-27 01:25 , Processed in 0.126167 second(s), 18 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.