我爱嵌入式系统

当前位置:首页 > 软件天地 > 业内资讯 > 详细内容
用51单片机的中断来扫描键盘
发布时间:2009/11/7  阅读次数:2847  字体大小: 【】 【】【

/*
程序效果:用51单片机的中断来扫描键盘,按下按键,蜂鸣器响,数码管有相应的键值
         显示,按下E键继电器关,按下C键继电器开。
         这与上一程序的功能相同,比上一程序简洁
         但理解相对困难些。

*/

#include<reg52.h> //头文件
#include<intrins.h>
#define uchar unsigned char //宏定义
#define uint   unsigned int
sbit jdq=P3^5; //位声明,驱动继电器管脚
sbit   fmq=P3^4; //位声明,驱动蜂鸣器管脚
code uchar table[]={0x3f,0x06,0x5b,//数码管显示的数值
0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};
code uchar key_tab[17]={     //此数组为键盘编码
0xed,0x7e,0x7d,0x7b,     // 0,1,2,3,
0xbe,0xbd,0xbb,0xde,   // 4,5,6,7,
0xdd,0xdb,0x77,0xb7,         // 8,9,a, b,
0xee,0xeb,0xd7,0xe7,0xff}; //   c,d,e,f,
uchar l_key=0x00; //定义变量,存放键值
uchar l_keyold=0xff; //作为按键放开否的凭证
void readkey();       //扫描键盘,获取键值
void display(uchar *lp,uchar lc); //显示子函数
void delay();   //延时子函数
void main()   //主函数
{
    EA=1;   //打开总中断
    EX0=1; //打开外部中断
    P0=0xf0; //键值高4位为高电平,低4位为低电平
     while(1)
     {
       display(&l_key,1); //调用显示子函数
       if(l_key==14)   //是否按下E键,是则关闭继电器
        jdq=1;    
       if(l_key==12)   //是否按下C键,是则打开继电器
         jdq=0;
     }  
}
void key_scan() interrupt 0//外部中断0,0的优先级最高
{
    EX0=0;   //在读键盘时,关闭外部中断,防止干扰带来的多次中断
    TMOD&=0xf1; //设置定时器为工作方式1                    
    TH0=0x2e;   //设置初值,为12毫秒,十进制值为11776
    TL0=0x00;
    ET0=1;   //开启定时器中断0
    TR0=1;   //启动定时器计数
}
void time0() interrupt 1     //定时器0的中断函数
{
    TR0=0;         //关闭定时器0
    readkey(); //定时12ms后产生中断,调用此函数,读取键值
}
void readkey()       //扫描键盘子函数
{
    uchar i,j,key; //定义局部变量
    j=0xfe;     //设定初值
    key=0xff;
    for(i=0;i<4;i++) // 逐列扫描键盘
    {
       P0=j;
       if((P0&0xf0)!=0xf0) //有按键按下,高4位不可能全为1
       {
           key=P0; //读取P0口的值,推出循环,否则循环下次
           break;
       }
       j=_crol_(j,1); //此函数的功能是:左移循环
    }
    if(key==0xff)     //如果读取不到P0口的值,如干扰,则返回
    {
       l_keyold=0xff;
       P0=0xf0;       // 恢复P0口的值,等待按键按下
       fmq=1;
       EX0=1;       //在返回前,打开外部中断
       return;
    }
    fmq=0;     //有按键按下,打开蜂鸣器
    if(l_keyold==key) // 检查按键放开否,如果相等表明没有放开
    {
       TH0=0x2e; //设置初值
       TL0=0x00;
       TR0=1; //继续启动定时器,检查按键放开否
       return;
    }
    TH0=0x2e;  
    TL0=0;
    TR0=1;   //启动定时器
    l_keyold=key; //获取键值,作为放开否的凭证
    for(i=0;i<17;i++)     //查表获得相应的16进制值存放到l_key中
    {
       if(key==key_tab[i])
       {
           l_key=i;
           break;
       }
  }
  //程序运行到此,就表明有键值存放到l_key中,主程序
  //就可以检测键盘值并作相应的处理
}
void display(uchar *lp,uchar lc) //显示子函数
{
    uchar i;     //定义局部变量
    P1=0xf8; //点亮第一个数码管
    P2=0;       //P2口为输出值
    for(i=0;i<lc;i++)   //循环显示
   {
       P2=table[lp[i]]; //查表获得相应的要显示的数字的数码段
       delay();   //延时
       P2=0;   //清零,准备显示下一个数值
    }
}
void delay() //延时子函数
{
    _nop_();_nop_();_nop_();_nop_();_nop_();
}
如果程序无法编译,请删除所有前导空白.

我要评论
  • 匿名发表
  • [添加到收藏夹]
  • 发表评论:(匿名发表无需登录,已登录用户可直接发表。) 登录状态:未登录
最新评论
所有评论[2]
  • 评论人:[匿名] 时间: [2019/11/2 15:31:10] IP:[5.188.84.12*]
  • Ciprofloxacine Teva 500 Mg Achat Furosemide isotretinoin 10mg skin health a href=http//avdrug.comlevitra prix maroc/a Nebenwirkungen Viagra Ohne Rezept
  • 评论人:[匿名] 时间: [2018/6/15 6:06:41] IP:[146.185.223.15*]
  • Lioresal En Ligne France Cialis Viagra Efficacite a href=http//cialviag.comcialis/a Viagra Kaufen Dusseldorf Ou Acheter Du Cialis Pas Cher Cephalexin Online With Next Day Shipping

51RTOS.com 版权所有  

Copyright 20006-2009 我爱嵌入式 ( 51RTOS.com ) All rights reserved 沪ICP备09080633号