单片机键盘输入的程序

电子说

1.3w人已加入

描述

  这是读取键盘的子程序

  主要内容为:如何定义位,如何得到按键状态,防止键盘干扰的方法

  以及如何处理读入的键值

  思路:首先在某一引脚输出一个电平,然后读入引脚的电平,如果刚好相反

  那么可能有按键发生,但是不排除干扰,为了防止干扰,需要软件延时20ms

  消除干扰,然后,等待用户释放,否则,可能重复的到某种结果,发生意外情况

  应该说键盘输入是单片机外部指令输入的重要途径,因此如何设计键盘以及键盘的工作原理、读键盘的方法、键盘的抗干扰设计等在单电能机系统设计中占有重要地位。这个例子在系统硬件的基础上设计了软件查询程序、软件延时程序(防止干扰),大致讲述了一种查询式键盘的工作原理与读取方式。

  下面是汇编语言写的单片机键盘输入程序

  **************************************************

  led1 bit p1.0       ;LED 显示位定义

  led2 bit p1.1

  led3 bit p1.2

  led4 bit p1.3

  led5 bit p1.4

  led6 bit p1.5

  led7 bit p1.6

  led8 bit p1.7

  s1 bit p0.0        ;数码管位定义

  s2 bit p0.1

  s3 bit p0.2

  s4 bit p0.3

  s5 bit p0.4

  s6 bit p0.5

  s7 bit p0.6

  s8 bit p0.7

  led_data equ p2      ;数码管显示数据定义

  key1 bit p3.5       ;按键引脚定义

  key2 bit p3.6       ;

  key3 bit p3.7       ;

  key equ 46h        ;按键寄存单元

  org 00h

  jmp main

  org 030h

  main:mov sp,#30h        ;首先定义

  lcall REST        ;初始化子程序

  lp:lcall pro_key       ;调用键盘查询子程序

  lcall KEYPR        ;用来显示所查询到的键值

  jmp lp          ;反复调用,不断查询

  REST:

  mov a,#00h

  mov b,#00h

  mov p0,#0

  mov p1,0ffh        ;

  mov p2,#0

  mov key,#00h

  mov p2,#255

  clr beep

  RET

  KEYPR:

  mov a,key         ;键值在累加器KEY中

  jz PROEND         ;如果 A= 0,表示没有按键,返回

  cjne a,#1,k1       ;A= 1 ,用户按了第一个键

  mov a,#1          ;处理 A = 1的情况

  mov dptr,#tab_nu      ;查表

  movc a,@a+dptr

  mov led_data,a       ;显示 “1”

  setb s1          ;在第一位

  clr s2          ;其余两位不显示

  clr s3

  jmp PROEND        ;处理完成,子程序返回

  ;以下分别处理KEY = 2,3 的情况

  k1:cjne a,#2,k2

  mov a,#2

  mov dptr,#tab_nu

  movc a,@a+dptr

  mov led_data,a

  clr s1

  setb s2

  clr s3

  jmp PROEND

  k2:cjne a,#3, PROEND

  mov a,#3

  mov dptr,#tab_nu

  movc a,@a+dptr

  mov led_data,a

  clr s1

  clr s2

  setb s3

  PROEND:ret

  **** 本内容跟帖回复才可浏览 *****

  ;************ 定时20 ms *************

  delay20ms: push psw         ;保存原来的寄存器单元

  clr psw.3        ;设置新的寄存器

  clr psw.4        ;

  mov r0,#2        ;延时参数1

  mov r1,#250       ;延时参数2

  mov r2,#2        ;延时参数3

  dl1:djnz r0,dl1        ;延时循环1

  mov r0,#250        ;重新设置循环数据

  dl2:djnz r1,dl1        ;开始第二道循环

  mov r0,#240       ;

  mov r1,#248       ;

  dl3:djnz r2,dl1       ;第三道循环

  nop           ;修正定时精度

  pop psw          ;恢复原来的寄存器组

  ret            ;返回

  ;*********** end *******************

  ;这是数字显示表格,其中 带小数点的数字比不带小数点的数字大16

  ; 比如 0 的显示代码为 0;那么 0.的显示代码为 16;如此类推

  tab_nu:

  db 0c0h, 0f9h, 0a4h, 0b0h, 99h , 92h , 82h, 0f8h     ;数字0-7 不带小数点代码

  db 80h , 90h, 88h , 83h , 0c6h, 0a1h, 86h, 8eh      ;数字8-f 不带小数点代码

  db 40h , 79h, 24h , 30h , 19h , 12h , 02h, 78h      ;数字0-7 带小数点代码

  db 00h , 10h, 08h , 03h , 46h , 21h , 06h, 0eh      ;数字8-f 带小数点代码

  end             ;告诉编译器本程序到此结束,一定需要加上,否则编译通不过。

  ;c语言

  **************************************************

  //按不同的按键,会显示不同的结果

  #include 《8051.h》

  #define uchar unsigned char

  #define key1 P3_4 //键盘定义

  #define key2 P3_5

  #define key3 P3_6

  //****************************************************************************

  void delay(uchar times);

  void display(uchar disseg,uchar disdata);

  uchar keyb();

  // 这里定义的是数码管对应的字符字根

  code uchar disbuf_u[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,

  0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,

  0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,

  0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e};

  // ***************************************************************************

  uchar keybuf;

  void main()

  {

  uchar keym = 0; //键盘返回结果的缓冲区

  keybuf = 0;

  P1 = 255; //关闭LED显示

  P0 = 0; //关闭数码显示

  P2 = 255; //

  while(1) //设置一个无限制循环

  {

  keym = keyb(); //得到按键结果

  if(keym) keybuf = keym; //如果返回有效的按键结果才保存

  display(keybuf-1,keybuf); //在相应的位置显示返回的结果

  }

  }

  //*****************************************************************************

  //下面是延时程序。具体的延时时间不能通过表面程序看出,(为什么?)

  //如果我们需要一个精密的延时程序,那么我们可以采用内嵌汇编代码的方式

  void delay(uchar times)

  {

  int t=100; //延时倍数

  uchar i=times;

  for(;i!=0;i--)

  {for(;t!=0;t--){}}

  }

  //这里是显示子程序,入口参数为

  // disseg -》 位选 可选范围 0-7 一共8个数码管

  // disdata -》 段选 可选范围 0-31 一个32个字符

  // 段选 0-15 16个字符 为 “0”-》“F”

  // 段选 16-31 16个字符 为 “0.”-》“F.”

  void display(uchar disseg,uchar disdata)

  {

  uchar dataf;

  if(disseg 《 8) //只有当要显示的位数有效,才显示。否则,不显示

  {

  dataf = 1;

  while(disseg)

  {

  dataf 《《= 1;

  disseg--;

  }

  P0 = dataf;

  P2 = disbuf_u[disdata];

  }

  else{P0=0,P2=255;} //关闭数码管显示

  }

  uchar keyb()

  {

  uchar key,keytmp;

  key1 = 1; //将输出线拉高

  key2 = 1;

  key3 = 1;

  key = P3 ; //读回来

  key = key & 0xf0; //获得键盘结果

  if(key == 112 ) return 0; //如果用户没有按键返回 0

  else

  {

  keytmp = key;

  delay(1); //判断是不是干扰

  key = P3 & 0xf0;

  if (key != keytmp ) return 0; //是干扰,返回 0

  else //不是干扰,等待用户释放按键

  {

  do{

  key1 = 1; //输出拉高

  key2 = 1;

  key3 = 1;

  key = P3 & 0xf0; //读回来

  P1_0 = ~P1_0; //如果用户不释放,闪烁 p1.0

  }while(key != 112 ); //等待用户释放

  P1_0 = 1; //用户释放以后,清除p1.0指示灯

  switch(keytmp)

  {

  case 96: return 3;//返回用户按键结果

  case 80: return 2;

  case 48: return 1;

  }

  }

  }

  }

  //

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分