找回密码
 注册
关于网站域名变更的通知
查看: 172|回复: 2
打印 上一主题 下一主题

单片机教程25单片机键盘接口程序设计

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-8-11 10:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
   键盘是由若干按钮组成的开关矩阵,它是单片机系统中最常用的输入设备,用户能通过键盘向计算机输入指令、地址和数据。一般单片机系统中采和非编码键盘,非编码键盘是由软件来识别键盘上的闭合键,它具有结构简单,使用灵活等特点,因此被广泛应用于单片机系统。按钮开关的抖动问题
1 W: l  [/ b" Y8 k7 z' f组成键盘的按钮有触点式和非触点式两种,单片机中应用的一般是由机械触点组成的。在下图中,当开/ A( o. }' P( @( B& |& P
<键盘结构图>
0 g. @/ N, v7 ~9 O( a' D* G$ \

4 o; q* S% I" f            图13 V' w" C! b4 Q

. m% `' {( ^0 u+ [  @            图2
0 q$ n/ Q$ k( ~2 n# h
关S未被按下时,P1。0输入为高电平,S闭合后,P1。0输入为低电平。由于按钮是机械触点,当机械触点断开、闭合时,会有抖动动,P1。0输入端的波形如图2所示。这种抖动对于人来说是感觉不到的,但对计算机来说,则是完全能感应到的,因为计算机处理的速度是在微秒级,而机械抖动的时间至少是毫秒级,对计算机而言,这已是一个“漫长”的时间了。前面我们讲到中断时曾有个问题,就是说按钮有时灵,有时不灵,其实就是这个原因,你只按了一次按钮,可是计算机却已执行了多次中断的过程,如果执行的次数正好是奇数次,那么结果正如你所料,如果执行的次数是偶数次,那就不对了。; v* L& @! a% Z7 c4 t7 u
为使CPU能正确地读出P1口的状态,对每一次按钮只作一次响应,就必须考虑如何去除抖动,常用的去抖动的办法有两种:硬件办法和软件办法。单片机中常用软件法,因此,对于硬件办法我们不介绍。软件法其实很简单,就是在单片机获得P1。0口为低的信息后,不是立即认定S1已被按下,而是延时10毫秒或更长一些时间后再次检测P1。0口,如果仍为低,说明S1的确按下了,这实际上是避开了按钮按下时的抖动时间。而在检测到按钮释放后(P1。0为高)再延时5-10个毫秒,消除后沿的抖动,然后再对键值处理。不过一般情况下,我们常常不对按钮释放的后沿进行处理,实践证明,也能满足一定的要求。当然,实际应用中,对按钮的要求也是千差万别,要根据不一样的需要来编制处理程序,但以上是消除键抖动的原则。2 C* I# W8 Q: m& q- j8 G0 \4 x0 Q
键盘与单片机的连接
4 B3 O: x, C/ Z; ~8 L( R, y( c
1 [! ^) n9 E& p/ x3 B- l4 A
            <键盘连接>
0 K# }( r- Z" b8 E$ Z            图3& R! R1 ^( ^# N& Q- u; @, N$ L& U

2 a6 C4 J% b1 t" u+ l            <单片机与键盘接口图># {# I* Y0 Y" o9 g( T7 ?! ?, n
            图4
  R! N8 k& E  }! l) D0 f- Q4 p
1、通过1/0口连接。将每个按钮的一端接到单片机的I/O口,另一端接地,这是最简单的办法,如图3所示是实验板上按钮的接法,四个按钮分别接到P3.2 、P3.3、P3.4和P3.5。对于这种键各程序能采用持续查询的办法,功能就是:检测是否有键闭合,如有键闭合,则去除键抖动,判断键号并转入对应的键处理。下面给出一个例程。其功能很简单,四个键定义如下:0 p+ A7 H/ L: \$ I
P3.2:开始,按此键则灯开始流动(由上而下)
5 p% y. ^. R( X; _$ XP3.3:停止,按此键则停止流动,所有灯为暗
  y6 m2 a0 g$ [; v$ WP3.4:上,按此键则灯由上向下流动2 l  c2 S' m& n' _4 c! U+ v
P3.5:下,按此键则灯由下向上流动
5 m. |6 \/ y. \6 s! F3 |UpDown EQU 00H ;上下行标志
: o8 K' {' R( c' U, ]3 bStartEnd EQU 01H ;起动及停止标志# x. ~& x7 E1 y; f: J' h0 w
LAMPCODE EQU 21H ;存放流动的数据代码
) {8 a$ x6 s, H3 Q9 DORG 0000H- A, k6 q0 V( i& x
AJMP MAIN
* D! y2 E+ u6 {6 C4 ]! t: VORG 30H
  g; B4 y- J8 g5 w+ Q* AMAIN:
3 a. f4 [( j8 p: n5 P) X6 BMOV SP,#5FH3 x) f% \# r7 u0 G' s2 u7 m
MOV P1,#0FFH0 i* I  h/ x  N8 Z. X. S  R- K
CLR UpDown ;启动时处于向上的状态
1 |3 l; E: [$ W7 Q3 z9 JCLR StartEnd ;启动时处于停止状态
, i  @% T( g* Y$ e/ S& N" QMOV LAMPCODE,#0FEH ;单灯流动的代码
9 d+ Y4 y( v* pLOOP:
# Z7 P1 P' @/ \' F4 c, ?; n, AACALL KEY ;调用键盘程序
3 _* B2 P& I5 l0 mJNB F0,LNEXT ;如果无键按下,则继续
6 l1 g/ L. ]+ Q; v( U1 u* UACALL KEYPROC ;不然调用键盘处理程序! Y5 M' q- O/ E1 j$ b
LNEXT:4 F; u' S. K* u1 }; k7 ?
ACALL LAMP ;调用灯显示程序
6 O) w. X2 o# `) n: BAJMP LOOP ;反复循环,主程序到此结束
! u6 G: p5 k8 E' j7 S; w( h: xDELAY:
  d- q" {& T! b' U/ k' NMOV R7,#100$ a" H0 ^8 i& `0 [
D1: MOV R6,#100  ]6 m. R& u* V
DJNZ R6,$
* s; C" i2 g1 [; g- N+ f, eDJNZ R7,D1' _* z2 D; T+ R
RET
$ s; b- c, [! |# p7 O0 K& D;----------------------------------------延时程序,键盘处理中调用
. b& _, U. f/ {* lKEYPROC:+ k/ N: h! q9 ~) }8 n
MOV A,B ;从B寄存器中获取键值
5 }$ }6 D% p2 l4 U+ I2 Y0 S2 ]# I6 wJB ACC.2,KeyStart ;分析键的代码,某位被按下,则该位为1(因为在键盘程序中已取反)0 z# f- Z( ?5 S! z3 _& Z# f2 ~
JB ACC.3,KeyOver# N: p' z7 h7 H
JB ACC.4,KeyUp2 w* D: [: u% y2 D6 E3 e6 \
JB ACC.5,KeyDown" G, ~3 ]2 A# Y- c/ _
AJMP KEY_RET
: D) U. J( m) C, j' `8 ]KeyStart:
0 ?" V+ P1 b+ L" X1 z- ^: a5 |SETB StartEnd ;第一个键按下后的处理
3 f6 n* ^3 T6 C" E$ d: ?' J* mAJMP KEY_RET
* Q7 Y4 a8 j" U$ m6 t9 m/ PKeyOver:
1 h! Z5 @1 J$ y* p6 g7 H7 cCLR StartEnd ;第二个键按下后的处理3 C9 i" E- r& u3 M5 Y1 D6 @
AJMP KEY_RET- |& B: B' M! R7 Q3 S! j, Y
KeyUp: SETB UpDown ;第三个键按下后的处理
2 A. s; J* R7 B9 B3 qAJMP KEY_RET
% X4 {- c$ |- {7 a, t- }. HKeyDown:
4 e6 j. }: D: g" J7 wCLR UpDown ;第四个键按下后的处理! A6 |! H' R  `8 O
KEY_RET:RET
% X# q7 U6 A5 D' i' }KEY:, q4 d, ?. L/ A% I' k/ H8 m5 l
CLR F0 ;清F0,表示无键按下。" I& B2 g1 _6 }; H+ L0 l2 y
ORL P3,#00111100B ;将P3口的接有键的四位置16 m/ F+ X2 K4 K2 v: O1 G
MOV A,P3 ;取P3的值
$ s0 w- S  O5 M, `. m, BORL A,#11000011B ;将其余4位置1
: q% R6 U3 P+ F. d7 W2 GCPL A ;取反" X5 @2 c# m5 d# ]  }7 a/ l* d
JZ K_RET ;如果为0则一定无键按下' F, @# V; A  ^- @8 S$ `
ACALL DELAY ;不然延时去键抖& [) U2 R4 W1 P. {% o9 b) \
ORL P3,#00111100B9 `# _' b- O3 p  e
MOV A,P34 S) x8 p6 I7 u/ G' ^; _
ORL A,#11000011B' |% B! t7 C: c
CPL A
# R9 L, @1 V% A2 c( X2 XJZ K_RET& ~$ V8 E+ i4 d
MOV B,A ;确实有键按下,将键值存入B中
: t6 n! i" k$ jSETB F0 ;设置有键按下的标志
1 C0 A$ r! _; }" xK_RET:
/ B7 q6 Y0 \2 V$ J3 X: A6 PORL P3,#00111100B ;此处循环等待键的释放
; H) ?6 d% A+ oMOV A,P37 A4 F( }/ W, y" _- X
ORL A,#11000011B5 T; K+ u5 X' D9 u( `7 b
CPL A* k* i3 q8 m" b+ V* h+ k* Z' ^7 ?# S8 d
JZ K_RET1 ;直到读取的数据取反后为0说明键释放了,才从键盘处理程序中返回7 U+ G' _/ r- h  \
AJMP K_RET; j9 b+ y! k. o" V- L! f; J  e
K_RET1:7 M% n/ h" r) d; I
RET% r8 u: a$ o+ y# j
D500MS: ;流水灯的延迟时间
9 c% u( r6 I8 h3 d5 L" V. lPUSH PSW
- S) t( O0 E" _5 o2 dSETB RS0
& c! o* ^, _/ x) JMOV R7,#200
' ]& Y$ c" _( n8 c% Q( l. kD51: MOV R6,#250
9 e5 _4 R! G/ @4 }' w3 T+ hD52: NOP
0 m7 p* }5 i# oNOP: c( o$ {: W' Q5 I: ]8 B, K6 A8 c3 b5 U
NOP
  o5 I- H. K( t1 z' ~( lNOP
4 ]) ?* W( a# H+ ZDJNZ R6,D52
4 t0 m4 k  |8 x+ `DJNZ R7,D51
2 j( r; T, L) U8 i/ d; O; q( w  u1 HPOP PSW, ^: }8 r. O& T' w4 x
RET
: r9 j8 _' h0 ?/ H8 t: ZLAMP:
5 m" p: F" [/ Q/ @+ xJB StartEnd,LampStart ;如果StartEnd=1,则启动" m5 J5 [) v0 [7 b% }2 s* P$ Q& @
MOV P1,#0FFH
' p2 o, _  a) O$ w. \& `: @AJMP LAMPRET ;不然关闭所有显示,返回
' h, `2 c0 m. M* e+ @. oLampStart:9 B! {& n) v% u+ F  w: X) g
JB UpDown,LAMPUP ;如果UpDown=1,则向上流动- G$ S: w  |1 ?6 i+ b
MOV A,LAMPCODE" C6 s7 E) C3 V1 I9 R9 [
RL A ;实际就是左移位而已$ x% d; I1 x: f) D
MOV LAMPCODE,A
3 |0 F: m' o4 W; T% S+ r5 UMOV P1,A2 M# q  h# L) f7 _+ }
LCALL D500MS
4 J0 n; s6 \1 h- T% A2 {AJMP LAMPRET
! L1 L* ~% r& q( X/ m) y7 zLAMPUP:
9 ?  y! V+ x5 N3 s! O: PMOV A,LAMPCODE$ m% G8 g; e! s( y
RR A ;向下流动实际就是右移
9 x$ D  o& k- S) X( Q3 y5 l$ WMOV LAMPCODE,A& e; z6 |2 [& k) O* v% B
MOV P1,A
9 R0 t7 g* v+ |0 D- o+ _" D/ eLCALL D500MS9 m# W5 _3 C( l2 m2 |# ?9 h
LAMPRET:
9 M0 y" y* L& e, s# JRET  u: i% @9 ]+ b0 t/ f, T7 \
END8 ?! K; m0 n8 o
以上程序功能很简单,但它演示了一个单片机键盘处理程序的基本思路,程序本身很简单,也不很实用,实际工作中还会有好多要考虑的因素,比如主循环每次都调用灯的循环程序,会造成按钮反应“迟钝”,而如果一直按着键不放,则灯不会再流动,一直要到松开手为止,等等,大家能仔细考虑一下这些问题,再想想有什么好的解决办法。! z% [! ~: e$ S  f" e
2、采用中断方式:如图4所示。各个按钮都接到一个与非上,当有任何一个按钮按下时,都会使与门输出为低电平,从而引起单片机的中断,它的好处是不用在主程序中持续地循环查询,如果有键按下,单片机再去做对应的处理# {  z( p* R" _0 P

该用户从未签到

2#
发表于 2022-8-11 11:25 | 只看该作者
谢谢楼主,很不错的东西

该用户从未签到

3#
发表于 2022-8-11 14:21 | 只看该作者
谢谢,看到了很不错
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-3 15:21 , Processed in 0.109375 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表