单片机
返回首页

用单片机中断来扫描键盘的程序

2012-11-24 来源:21IC

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

#include //头文件
#include
#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   {
      P2=table[lp[i]]; //查表获得相应的要显示的数字的数码段
      delay();  //延时
      P2=0;  //清零,准备显示下一个数值
   }
}
void delay() //延时子函数
{
   _nop_();_nop_();_nop_();_nop_();_nop_();
}
如果程序无法编译,请删除所有前导空白.

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 红外线探测报警器

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • RS-485基础知识:处理空闲总线条件的两种常见方法

  • 基于ICL296的大电流开关稳压器电源电路

    相关电子头条文章