论坛风格切换切换到宽版
  • 3718阅读
  • 3回复

有人能帮我解释下单片机键盘扫面程序吗?? [复制链接]

上一主题 下一主题
离线forrest7507
 
只看楼主 倒序阅读 0楼 发表于: 2006-12-08
有高手能给下面的键盘程序注释下吗,本人看的不是很懂,按键的值什么时候能给单片机p1啊?谢谢了
#include <reg51.h>
#include <intrins.h>
#include <absacc.h>

#define uchar unsigned char



uchar rr;
uchar k;
uchar keydata;




void key_scan(void);       //键盘函数定义段;
uchar key_tab(uchar k);
void delay(void);
void key_in(uchar k);

//---------------------------------------------------------------
void main(void)
{
  while(1)
{
  key_scan();
}
}//---------------------------------------------------------------------------------------------

void key_scan(void)
{ uchar sccode,recode,i;
    p1=0xf0;
        if((p1&0xf0)!=0xf0)
      {
          delay();
          if((p1&0xf0) !=0xf0)
        {
                sccode=0xfe;
            for(i=0;i <4;i++)
            {
                p1=sccode;
              if((p1&0xf0) !=0xf0)
                {
                    recode=(p1&0xf0)|0x0f;
                    k=(~recode)+(~sccode);
                    rr=p1;

                  key_in(k);
                  break;
                }
              else
                sccode=(sccode < <1)|0x01;
            }
        }

}
//do {ta=p2;}while(ta==rr);
}
void delay()     //去抖动
{int a=2500;
while(--a);
}

void key_in(uchar k)
{   uchar ta;
  //uchar keydata;

  do {ta=p1;}while(ta==rr);
  keydata=key_tab(k);
}
离线ljchip
发帖
456
只看该作者 1楼 发表于: 2006-12-11
这样的解释是否满意?

void key_scan(void)
{
     uchar sccode,recode,i;
     p1=0xf0;      // 设置p1口为0xf0,这个键盘是4乘4的,p1口高4位是输入,低4位是输出.
     if((p1&0xf0)!=0xf0)      // 如果读入p1口的高4位为高电平,则没有按键信息,程序退出键盘扫描.
     {
           delay();      // 有按键,作按键延时,这里不知道晶振频率,一般是延时20-100ms时间.
           if((p1&0xf0) !=0xf0)      // 如果此时读入p1口的高4位为高电平,则认为按键抖动,程序退出键盘扫描.
           {
                 sccode=0xfe;            // 设置初始最低键盘扫描行线为低电平,列线是4位输入.
                 for(i=0;i <4;i++)      // 分别扫描每行按键,查找对应的列输入位为低电平,以确定具体按键.
                 {
                       p1=sccode;            // 将行线的值设置到p1口.
                       if((p1&0xf0) !=0xf0)      // 如果当前高4位线有低电平,则表明有按键按下,否则当前行线所对应的按键没有按下.
                       {
                             recode=(p1&0xf0)|0x0f;            // 读取高4位的列线值送入寄存器recode.
                             k=(~recode)+(~sccode);            // 当前行线与列线的数值取反送入k寄存器.
                             rr=p1;            // rr应是个全局变量,它保存当前p1口数据.
                             key_in(k);      // 确定按键的键值,即确定是键盘的哪个按键被按下.
                             break;            // 退出键盘扫描程序.
                       }
                       else      sccode=(sccode < <1)|0x01;      // 当前行没有按键按下,变换下一个行线为低电平检测.
                 }
           }

     }
//do {ta=p2;}while(ta==rr);
}
void delay() //去抖动
{
     int a=2500;
     while(--a);
}

void key_in(uchar k)
{
     uchar ta;
     //uchar keydata;
     do
     {
           ta=p1;      // 读入当前p1口数据到ta
     }
     while(ta==rr);      // 循环比对按键,直到相等则退出循环.
     keydata=key_tab(k);      // key_tab()是个外部函数,确定键值的函数,键值附给keydata供对应的按键处理,keydata是个全局变量.
}
离线ljchip
发帖
456
只看该作者 2楼 发表于: 2006-12-16
按键的值什么时候能给单片机p1啊?
这个问题很简单啊,只要单片机空闲时候调用:key_scan();函数名改成:
void key_scan(void) 改成: bit key_scan(void)
函数体内:
key_in(k); // 确定按键的键值,即确定是键盘的哪个按键被按下.
break; // 退出键盘扫描程序.
改成:
key_in(k); // 确定按键的键值,即确定是键盘的哪个按键被按下.
return ture; // 退出键盘扫描程序.
函数其他出口全部添加:
return felse; // 退出键盘扫描程序.
只要函数返回ture则按键有效,键值在keydata变量中取出应用!
离线天涯1212
只看该作者 3楼 发表于: 2006-12-27
其实这个问题很简单,主要是你对单片机查询扫描方式读判别键的方法理解不透造成的,我在第一次学的时候也遇到了同样的问题,后来我花了半个小时把扫描的文字说明(任何书都有也就那么两页纸)一个一个字的看了一遍,然后逐条分析程序,这样不到2小时就弄懂了的,我想学单片机不能浮躁,最好是能自己搞懂技术上的问题!