单片机与键盘接口程序

发布者:码字奇思最新更新时间:2014-12-18 来源: laogu关键字:单片机  键盘接口程序 手机看文章 扫描二维码
随时随地手机看文章

单片机与键盘接口程序

void int1proc() interrupt IE1_VECTOR using 1
{
unsigned char i, key;
code unsigned char PS2TAB[] = {//20键PS2小键盘键码表
  0x70,//0
  0x69,//1
  0x72,//2
  0x7a,//3
  0x6b,//4
  0x73,//5
  0x74,//6
  0x6c,//7
  0x75,//8
  0x7d,//9
  0x05,//F1
  0x06,//F2
  0x04,//F3
  0x0c,//F4
  0x03,//F5
  0x0b,//F6
  0x5a,//Enter
  0x76,//Esc
  0x66,//Bksp
  0x71//KP.
  };
  if (PS2Buffers.PS2KeyCount == 0){//PS2起始位测试
    if (!PS2CLOCK && !PS2DATA){//低电平是起始位
      if (PS2Buffers.PS2KeyExtFlage != 0xf0){
        PS2Buffers.PS2KeyTemp = 0;
        PS2Buffers.PS2KeyExtFlage = 0;
        PS2Buffers.PS2KeyPopError = 0;
      }
      PS2Buffers.PS2KeyCount ++;//脉冲计数
    }
    else PS2Buffers.PS2KeyPopError = 0xeb;//置键起始位错误号0xeb
  }
  else if (PS2Buffers.PS2KeyCount < 9){//PS2数据位
    key = PS2Buffers.PS2KeyTemp;//取键盘缓冲区移位数据
    key >>= 1;
    if (PS2DATA) key = 0x80;
    PS2Buffers.PS2KeyTemp = key;
    PS2Buffers.PS2KeyCount++;//脉冲计数
  }
  else if (PS2Buffers.PS2KeyCount == 9){//PS2数据奇校验
    ACC = PS2Buffers.PS2KeyTemp;//取键盘缓冲区移位数据(C51取偶校验位)
    if (P != PS2DATA) PS2Buffers.PS2KeyCount ++;//脉冲计数
    else{
      PS2Buffers.PS2KeyPopError = 0xec;////置键奇校验位错误号0xec
      PS2Buffers.PS2KeyCount = 0;//脉冲计数归零
    }
  }
  else if (PS2Buffers.PS2KeyCount == 10){//停止位
    key = PS2Buffers.PS2KeyTemp;//取键盘缓冲区移位数据
    PS2Buffers.PS2KeyCount = 0;//脉冲计数归零
    if (PS2DATA){//高电平是停止位
      if (key == 0xe0){//本次是扩展键
        PS2Buffers.PS2KeyExtFlage = 0xe0;//置扩展键标志(小键盘只有回车键)
      }
      else if (key == 0xf0){//本次是键断码,键释放
        PS2Buffers.PS2KeyExtFlage = 0xf0;//置键释放标志
      }
      else{//本次必为键值
        if ((key == 0xaa) (key == 0xfa)) PS2Buffers.PS2KeyPushCount = 0;//长
压键计数器清零
        else{
            PS2CLOCK = 0;//阻止PS2键盘立即回送数据
          PS2Buffers.PS2KeyPopError = 0xaa;//出错码
          for (i = 0; i < 20; i++){
            if (key == (PS2TAB[i])){//搜索
              key = i + 1;
              if (PS2Buffers.PS2KeyExtFlage == 0xf0){
                key = 0x80;//键释放
                PS2Buffers.PS2KeyPushCount = 0;//长压键计数器清零
                PS2Buffers.PS2KeyMessage = key;//存入当前键值并执行命令
              }
              else{
                if (key != PS2Buffers.PS2KeyVal){//换了一个键
                  PS2Buffers.PS2KeyPushCount = 0;//长压键计数器清零
                  PS2Buffers.PS2KeyMessage = key;//存入当前键值并执行命令
                }
                else{//未换键
                  PS2Buffers.PS2KeyPushCount ++;//长压键计数器计数
                  if (PS2Buffers.PS2KeyPushCount > DEFPS2PUSHCOUNT){//长压时间到
                    PS2Buffers.PS2KeyMessage = key 0x40;//存入当前键值并执行命

                    PS2Buffers.PS2KeyPushCount = 0;//长压键计数器清零
                  }
                }
              }
              PS2Buffers.PS2KeyVal = key;//存入当前键值值1~20或0x80+(1~20)
              PS2Buffers.PS2KeyTemp = 0;//键码移位记录器
              PS2Buffers.PS2KeyExtFlage = 0;//扩展键标志
              PS2Buffers.PS2KeyPopError = 0;//键释放标志或出错码
              break;
            }
          }
          if (PS2Buffers.PS2KeyPopError) PS2Buffers.PS2KeyPushCount = 0;//长压键
计数器清零
          PS2CLOCK = 1;//释放PS2时钟总线
        }
      }
    }
    else PS2Buffers.PS2KeyPopError = 0xed;//置停止位错误号0xed
  }
  else PS2Buffers.PS2KeyCount = 0;//PS2键盘出错
}
/*------------------------------------------------------------------
         利用函数指针数组运行PS2键盘散转命令
-------------------------------------------------------------------*/
void PS2CommandExec(unsigned char key)
{
unsigned int i;
code void *funcpushbuffers[] = {//命令散转表(汇编中的16个DW)
/*------------------------------------------------------------------
         15个压键、放键及长压键事件处理函数指针地址
-------------------------------------------------------------------*/
  (void *)ClrWdt            + 0x0000,
/*---------------------------------------------
           10个功能键压键事件处理(独立管理)
----------------------------------------------*/
  (void *)PS2F1KeyPush      + 0x5b7d,      //功能键F1压键事件处理
  (void *)PS2F2KeyPush      + 0xa6ea,      //功能键F2压键事件处理
  (void *)PS2F3KeyPush      + 0xf157,      //功能键F3压键事件处理
  (void *)PS2F4KeyPush      + 0x4cc4,      //功能键F4压键事件处理
  (void *)PS2F5KeyPush      + 0x9731,      //功能键F5压键事件处理
  (void *)PS2F6KeyPush      + 0xe2ae,      //功能键F6压键事件处理
  (void *)PS2EnterKeyPush   + 0x3d1b,      //功能键Enter压键事件处理
  (void *)PS2EscKeyPush     + 0x8888,      //功能键Esc压键事件处理
  (void *)PS2BkspKeyPush    + 0xd3f5,      //功能键Bksp压键事件处理
  (void *)PS2KpKeyPush      + 0x2e62,      //功能键Kp压键事件处理
/*---------------------------------------------
           2个放键事件处理(集中管理)
----------------------------------------------*/
  (void *)PS2NumberKeyPop   + 0x79df,      //数字键放键事件处理
  (void *)PS2FuncKeyPop     + 0xc44c,      //功能键放键事件处理
/*---------------------------------------------
           2个长压键事件处理(集中管理)
----------------------------------------------*/
  (void *)PS2NumberKeyPushL + 0x1fb9,      //数字键长压键事件处理
  (void *)PS2FuncKeyPushL   + 0x6a26,      //功能键长压键事件处理
/*---------------------------------------------
           1个数字键压键事件处理(集中管理)
----------------------------------------------*/
  (void *)PS2NumberKeyPush  + 0xb593       //数字键0~9压键事件处理
  };
/*--------------------------------------------*/
  i = key;
  key &= 0x3f;//去掉键释放及长压键标志,取真键码
  key --;
  if (key < 20){//只有20个键
    if (key < 10){//数字键0~9
      if (i <= 10) key = 15;//(散转号0)压数字键0~9
      else{
        if (i & 0x80) key = 11;//(散转号11)放数字键0~9
        else key = 13;//(散转号13)长压数字键0~9
      }
    }
    else{//压功能键F1~F6,Enter..KP
      if ((i & 0xc0) == 0) key -= 9;//(散转号1~10)压功能键F1~F6,Enter..KP
      else{
        if (i & 0x80) key = 12;//(散转号12)放功能键
        else key = 14;//(散转号14)长压功能键
      }
    }
    ClrWdt();//喂狗(鬼知道键盘程序要运行多久,就替它先喂一次吧)
    i = ((key * 53 & 0xf) * 0x1000)+ ((key * 43 & 0xf) * 0x100) + ((key * 23 &
0xf) * 0x10) + (key * 13 & 0xf);
    _icall_((void *)funcpushbuffers[key] - i);//取键盘散转表并执行键盘命令
  }
}
这个程序与一般网上的有很大区别,它充分利用了外部中断(0字)hotpower[1次]

关键字:单片机  键盘接口程序 引用地址:单片机与键盘接口程序

上一篇:单片机的概述
下一篇:基于单片机的高精度测温装置的设计

推荐阅读最新更新时间:2024-03-16 13:49

发挥ARM Cortex-M3和M4微控制器最大作用的要诀
引言 许多嵌入式开发人员对ARMCortex处理器架构颇为熟悉,但很少有人能够对这种流行架构了如指掌,从而可以充分发挥它独特的特性和性能。新型ARM Cortex-M4处理器尤为如此,它拥有引以为豪的增强架构、天生的数字信号处理(DSP)能力和可选的浮点加速器,使精于此道的程序设计人员或硬件工程师可以充分发挥它的优势。本文接下来将就Cortex-M3/M4微控制器(MCU)的一些更有趣的(但经常遭到忽视的)特性展开详细的论述。 大部分采用Cortex-M3/M4 MCU的目标应用是便携式的,并且供电电源来自电池或能源收集系统,因此我们所探讨的大部分概念涉及如何减少系统整体能耗的技术。然而,在许多情况下,这些节能技术也是处理
[单片机]
发挥ARM Cortex-M3和M4<font color='red'>微控制器</font>最大作用的要诀
利用51单片机实现IO口模拟串口
有时需要双串口,转贴一篇 地址见下面 IO口模拟串口 1602显示数据位内容 程序可以实现一个51 单片机 有两个串口 #include regx52.h sbit BT_SND =P1^1; sbit BT_REC =P1^0; //1602部分引脚定义 sbit LCM_RW =P2^1 ;//定义引脚 sbit LCM_RS =P2^0; sbit LCM_E =P2^2; #define LCM_Data P0 #define Busy 0x80 //用于检测LCM状态字中的Busy标识 #define F_TM F0 #define TIMER0_ENABLE TL0=TH0; TR0=1; #define TIME
[单片机]
AT89S52单片机引脚功能介绍
AT89S52 引脚图 XTAL2: 系统时钟的反相放大器输出端,一般在设计上只要在XTAL1和XTA L2上接上一只石英振荡晶体系统就可以动作了,此外可以在两引脚与地之间加入一20PF的小电容,可以使系统更稳定,避免噪声干扰而死机。 RESET: AT89S52的重置引脚,高电平动作,当要对品片重置时,只要对此引脚电平提升至高电平并保持两个机器周期以上的时间,AT89S51便能完成系统重置的各项动作,使得内部特殊功能寄存器之内容均被设成已知状态,并且至地址0000H处开始读入程序代码而执行程序。 VCC: AT89S52电源正端输入,接+SVo EA/Vpp: EA ,为英文 External
[单片机]
对话 TI Sitara™︎ MCU总经理 Mike Pienovi:使实时处理变得简单且实惠的产品
随着对电子系统边缘实时控制、智能和通信需求的不断增长,高性能 现在提供了一种简单且经济高效的解决方案。 从智能工厂到智能城市,我们日益自动化的世界要求产品具有更高的速度、智能和精度。例如,与人类协同工作的自动化移动机器人需要精确的来安全地在物体周围导航,并且需要更快的处理速度以进行纳秒级决策 – 这些协同工作的实现都需要相互之间的通信。 为电子系统添加高级边缘分析和高实时性响应即将变得更容易、更实惠。 Sitara™ MCU 总经理 ke enovi向我们介绍了智能联网系统需求下,影响微控制器发展的主要因素。 问:在您看来,哪些趋势对微控制器提出了新的要求? 基于我们与工程师和行业专家的探讨,无论在制造业、数
[机器人]
意法半导体发布远距离无线微控制器,提高智能计量、智能建筑和工业监控的连接能效
新的STM32系统芯片低功耗,支持多种无线通信协议,简化各种用途的无线系统设计 中国,2023年11月24日 - 服务多重电子应用领域、全球排名前列的半导体公司意法半导体(STMicroelectronics,简称ST;) 发布了一款新的融合无线芯片设计专长与高性能、高能效STM32系统架构的微控制器(MCU)。全新的节能功能将这款无线MCU的电池续航时间延长到15年以上。 在远距离部署的应用领域,包括能源计量、监控设备、报警系统、执行器,以及智能建筑、智能工厂和智能城市的传感器,STM32WL3无线MCU的特别有用,有助于控制功耗,并给工作划分优先级。这些高能效MCU可以改善用户体验,提供服务,减少环境足迹。通过
[嵌入式]
意法半导体发布远距离无线<font color='red'>微控制器</font>,提高智能计量、智能建筑和工业监控的连接能效
单片机下串口(UART)协议包接收程序
代码编写在51单片机上,用于从接收缓冲区中提取有用数据(协议包)。基本逻辑亦可用于其他语言,其他情况下的接收程序。 数据的转移主要分了3步,接收缓冲区=》待处理数据=》有用数据。 接收缓冲区提取到待处理数据:由于可能下一个包马上就要过来,所以应把数据提取出来再做处理,以免直接处理的过程中收到新的数据造成混乱。 待处理数据提取到有用数据:例如在某些环境下,会收到其他协议的包(由其他程序处理),或者带有地址区分是否发给本机的包,所以需要设置一些条件来提取真正有用的数据。 单片机串口UART在接收中断程序中写入接收缓冲区,一定时间没有收到数据则标志为接收空闲(完成一个包的接收)。 本段代码先判断串口处于接收空闲状态,
[单片机]
基于S3C44B0X芯片和SPCE061A单片机实现移动机器人的设计
1、引言 移动机器人利用导航技术,获得机器人的目前所处的位置,结合技术对周围外界环境(障碍物等)作实时探测,并根据环境提供的信息规划一条可行路径完成达到目标点的任务。移动机器人技术涉及到传感器技术,导航技术,技术,人工智能等多个领域,因而对移动机器人的控制部分提出很高的要求,特别是视觉传感器的出现,要求控制系统不仅存储量大,而且处理速度快等。以往基于和控制的移动机器人就不能很好的满足实时性快速性的特点。 随着处理器的出现和发展以及嵌入式系统的发展,移动机器人的实时性快速性要求便能得到很好满足,现在该技术已经在多种领域得到有效的应用。本文是以SAMSUNG公司一款基于ARM7TD核的低功耗高性能的32位处理器芯片S3C44
[机器人]
C8051F单片机在远端测控装置中的应用
摘 要 :本文介绍了C8051F系列单片机在远端测控装置中的应用,给出了整个系统的结构,包括硬件配置和系统网络构成,对一些技术问题也做出了详尽的说明。 关键词: C8051F ;远端测控;硬件配置 C8051F单片机是完全集成的混合信号系统芯片(SoC),具有与8051指令集完全兼容的CIP-51内核和高速、高性能、高集成度等特点。在本文设计的一套远端测控装置中取得了较好的效果。 系统简介 远端测控装置是一种现场可编程的控制器,它能完成数据的采集控制,而通过远程通信的方式(如电台、CDMA、拨号等)将数据上传至中心站或接收中心站的遥控指令。它往往被安装在比较分散、环境比较恶劣、无电源保障(经常断电或使用太阳能)且无人值
[单片机]
C8051F<font color='red'>单片机</font>在远端测控装置中的应用
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
热门活动
换一批
更多
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多精选电路图
换一换 更多 相关热搜器件
更多每日新闻
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved