|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
本帖最后由 nuiga 于 2021-11-30 13:48 编辑 + T7 d0 P/ X+ W
+ I, o' h3 R/ P5 G& h/ E
什么叫动态扫描显示 ; l+ u: F0 x" ?2 u1 L* ^
在单片机系统中动态扫描显示接口是单片机中应用最为广泛的一种显示方式之一。其接口电路是把所有显示器的8个笔划段a-h同名端连在一起,而每一个显示器的公共极COM是各自独立地受I/O线控制。CPU向字段输出口送出字形码时,所有显示器接收到相同的字形码,但究竟是那个显示器亮,则取决于COM端,而这一端是由I/O控制的,所以我们就能自行决定何时显示哪一位了。而所谓动态扫描就是指我们采用分时的办法,轮流控制各个显示器的COM端,使各个显示器轮流点亮。/ U; A6 Z9 z9 U' ~' z+ f* a
在轮流点亮扫描过程中,每位显示器的点亮时间是极为短暂的(约1ms),但由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位显示器并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感。
( n* c" V$ Z8 G2 z$ p 由89c51的P0口能灌入较大的电流,所以我们采用共阳的数码管,并且不用限流电阻,而只是用两只1N4004进行降压后给数码管供电,这里仅用了两只,实际上还能扩充。它们的公共端则由PNP型三极管8550控制,显然,如果8550导通,则对应的数码管就能亮,而如果8550截止,则对应的数码管就不可能亮,8550是由P2.7,P2.6控制的。这样我们就能通过控制P27、P26达到控制某个数码管亮或灭的目的。# n2 k) T* P1 u( v% c
下面的这个单片机程序,就是用实验板上的数码管显示0和1。1 N# A9 a2 }" O* F# e4 P
FIRST EQU P2.7 ;第一位数码管的位控制
5 t3 I) v" ~( R; U) `7 o9 C6 g; ~ SECOND EQU P2.6 ;第二位数码管的位控制. ^9 Y, {" e2 _
DISPBUFF EQU 5AH ;显示缓冲区为5AH和5BH. P6 C9 w3 w0 {7 _' a* w4 U
ORG 0000H
( q! C/ f- E- {# D$ K AJMP START- G4 @: q/ ^% h" [
ORG 30H! y: @- ~. y6 s
START:% R1 Z2 e, R2 w
MOV SP,#5FH ;设置堆栈 Y( a1 o$ L" n
MOV P1,#0FFH
6 }: b5 L# G" P6 U" T: W- K) J MOV P0,#0FFH
0 ^5 r/ V% S7 b' r: U MOV P2,#0FFH ;初始化,所显示器,LED灭
5 @1 @- V5 z3 I6 J1 ? MOV DISPBUFF,#0 ;第一位显示0
, j/ C7 E. n/ y4 S MOV DISPBUFF+1,#1 ;第二握显示12 I1 r! ^* _& x* }5 x, X% H
LOOP:
1 [% O. e( R x! o$ T7 l LCALL DISP ;调用显示程序! z& H6 \; F1 @$ i; {1 |6 ^
AJMP LOOP
; [' Z- x* B4 t$ o8 Y; j ;主程序到此结束
* m: S4 f' _" |) Q y/ _( u$ s DISP:
0 F7 d( U! H& t3 ]+ T PUSH ACC ;ACC入栈1 r% r# _, \7 q' D/ M5 t
PUSH PSW pSW入栈7 W4 Z9 O8 n+ b$ ?
MOV A,DISPBUFF ;取第一个待显示数
. `( D! r6 G2 o P8 _3 t MOV DPTR,#DISPTAB ;字形表首地址8 ?6 w- I2 L6 S* \
MOVC A,@A+DPTR ;取字形码0 h6 l/ x) `( d+ E" k* O W$ g1 M1 e
MOV P0,A ;将字形码送P0位(段口)
) p& S2 f5 Y/ g) g8 E% h CLR FIRST ;开第一位显示器位口0 ?+ C0 G) X! b+ n
LCALL DELAY ;延时1毫秒
/ F4 m) l6 X. l1 x, f0 Z! T1 @ SETB FIRST ;关闭第一位显示器(开始准备第二位的数据)+ X; {% \ W, a4 I5 p
MOV A,DISPBUFF+1 ;取显示缓冲区的第二位
' j- K. _ B# h6 j5 i$ V) z* P MOV DPTR,#DISPTAB
$ g6 E( j% E3 _3 ^# q/ h; u MOVC A,@A+DPTR
1 N7 R( @6 z6 n; C0 _ MOV P0,A ;将第二个字形码送P0口. d( u7 e. s8 U& B; e2 v# Y: x
CLR SECOND ;开第二位显示器
" w; }. C7 S& d9 a s+ y1 _ LCALL DELAY ;延时
+ q& c2 J, |$ m$ f$ V SETB SECOND ;关第二位显示
& ^( |) t' p+ } POP PSW
4 d( C& b2 ?2 O6 v POP ACC+ I, r+ I0 i3 F
RET
% o x- X3 e- `" {* p; v3 t DELAY: ;延时1毫秒
, r6 S6 k, Z. \0 t& D PUSH PSW C& A! m& @" m2 j: a
SETB RS0
# ^. {' b/ _: ?8 g$ n MOV R7,#50
% o4 ?: z* }) d% d D1: MOV R6,#10
" ^2 F' _9 L6 ]: ~% N3 Q D2: DJNZ R6,$: p* ~7 t# D5 |1 i3 o! X( b* c* R/ B$ _
DJNZ R7,D1
! N$ @ ]) ~5 ]% [' c( g1 _5 _ POP PSW: }, P0 ^0 c P& H3 e2 i Z# s6 c
RET5 v$ c- `) [' Y: F
DISPTAB 28H,7EH,0a4H,64H,72H,61H,21H,7CH,20H,60H2 V9 v. d! n- m! O
END
, g) D' x- i3 V0 \0 A' G 从上面的单片机例程中能看出,动态扫描显示必须由CPU持续地调用显示程序,才能保证持续持续的显示。, e) o) c( @, t' [8 y1 P
上面的这个程序能实现数字的显示,但不太实用,为什么呢?这里仅是显示两个数字,并没有做其他的工作,因此,两个数码管轮流显示1毫秒,没有问题,实际的工作中,当然不可能只显示两个数字,还是要做其他的事情的,这样在二次调用显示程序之间的时间间隔就不一不定了,如果时间间隔比较长,就会使显示不连续。而实际工作中是很难保证所有工作都能在很短时间内完成的。况且这个显示程序也有点“浪费”,每个数码管显示都要占用1个毫秒的时间,这在很多合是不允许的,怎么办呢?我们能借助于定时器,定时时间一到,产生中断,点亮一个数码管,然后马上返回,这个数码管就会一直亮到下一次定时时间到,而不用调用延时程序了,这段时间能留给主程序干其他的事。到下一次定时时间到则显示下一个数码管,这样就很少浪费了。
: {) y) |$ b! v' M; f6 f7 \ Counter EQU 59H ;计数器,显示程序通过它得知现正显示哪个数码管
9 U5 @+ u/ j& n9 A) r4 s6 x FIRST EQU P2.7 ;第一位数码管的位控制
1 ^% t T) O9 g; L' U SECOND EQU P2.6 ;第二位数码管的位控制1 L0 E# @- [$ k7 t# P. t! | _
DISPBUFF EQU 5AH ;显示缓冲区为5AH和5BH
/ g8 r8 H4 ]6 x# g; a3 H ORG 0000H2 o9 y3 K$ j! Z* h( O
AJMP START. T% B% e8 m) z+ v) l# z
ORG 000BH ;定时器T0的入口! V$ D9 b3 F+ @4 _" ^
AJMP DISP ;显示程序
: w- R6 A& f9 t4 P% i1 m ORG 30H( |6 D% P( `3 r, y5 z1 \+ B3 h+ _
START:2 v# a) a) d$ K
MOV SP,#5FH ;设置堆栈
( n: r% v) _7 u4 }+ j4 S3 D MOV P1,#0FFH
8 _4 [9 X; P8 B8 _! |% L! F' U MOV P0,#0FFH
3 o/ f1 X# a/ J" Q5 n MOV P2,#0FFH ;初始化,所显示器,LED灭5 h6 J) K$ i; P. @9 G* ]
MOV TMOD,#00000001B ;定时器T0工作于模式1(16位定时/计数模式)
~1 \9 d' m: H5 m* N4 F MOV TH0,#HIGH(65536-2000)
* Q5 H! G" R, s- d+ U, p MOV TL0,#LOW(65536-2000) e/ g. V) K2 [9 u u
SETB TR0
" q: v: t+ G$ ^5 Y% X SETB EA; ?9 ` r) J6 ]4 u4 h5 N
SETB ET07 Y- K0 E$ ]. u5 y4 h' p) T
MOV Counter,#0 ;计数器初始化$ r6 p4 @! r% X( i
MOV DISPBUFF,#0 ;第一位始终显示06 o* \- w X$ O3 Y2 j
MOV A,#0$ a) z0 F+ D- U) {/ h2 _0 d! s9 _% `
LOOP:. l. M. A M2 C) n: E+ [9 z
MOV DISPBUFF+1,A ;第二位轮流显示0-9
& p7 P7 h4 N& k* q INC A; }, t t2 t q& o! k
LCALL DELAY
9 f2 g% X& F$ m e) q3 l# G CJNE A,#10,LOOP) C3 [: D4 f+ {7 Y# }/ z( O& e( Y) ~
MOV A,#0: m% X8 q) N1 r; `. w' Q( m0 T0 M
AJMP LOOP ;在此中间能按排任意程序,这里仅作示范。
. R& K. j- V) H! ? ;主程序到此结束
6 v3 j% |- r" b9 w! ~1 D* g DISP: ;定时器T0的中断响应程序3 z6 o" r f9 N2 G: c
PUSH ACC ;ACC入栈
, v+ I% k+ z7 x3 y PUSH PSW pSW入栈5 \: L- e8 ^ T' f
MOV TH0,#HIGH(65536-2000) ;定时时间为2000个周期,约2170微秒(11.0592M)6 f C. \" K# @
MOV TL0,#LOW(65536-2000), n3 {6 u9 Y; {+ i! \0 w
SETB FIRST/ U/ P/ l/ W4 \2 G% i
SETB SECOND ;关显示
% y4 m4 l6 V. Z6 N) @& h4 V MOV A,#DISPBUFF ;显示缓冲区首地址
+ o) m2 Y3 a' D/ n ADD A,Counter
+ m7 I3 p; s6 |; O6 h5 b8 _ MOV R0,A- ]/ M# I+ x! p
MOV A,@R0 ;根据计数器的值取对应的显示缓冲区的值3 U/ M4 L9 v; X( Y! X& u
MOV DPTR,#DISPTAB ;字形表首地址
- U7 o5 m a# ]9 K% B9 G: g: o MOVC A,@A+DPTR ;取字形码
% R( w# X: q9 J4 j* x MOV P0,A ;将字形码送P0位(段口) x9 Y% J9 X* x) p
MOV A,Counter ;取计数器的值; |; f/ J$ O$ I% z( R4 a7 M, }) R
JZ DISPFIRST ;如果是0则显示第一位
/ e$ h! g8 f% e' Q( J0 d! Z) w CLR SECOND ;不然显示第二位) @/ T+ C5 U' E2 p, [/ {8 v* v X
AJMP DISPNEXT; J# N9 O0 n( t& ]( Q6 J
DISPFIRST:; ^+ V3 Y4 R9 ]2 T+ f. v& v- f1 [2 E
CLR FIRST ;显示第一位; g' a2 T' _) P$ n, r& q0 x- f
DISPNEXT:( b6 j( w6 D M% W4 a0 C
INC Counter ;计数器加1) c' b4 j% m9 y4 f: a7 D
MOV A,Counter: p) d I& N. N5 W( e- Q
DEC A ;如果计数器计到2,则让它回0$ f7 R1 ]: R0 i2 k) P2 O% }5 k) {
DEC A
8 I! a; g" j, i t$ Q( a: w JZ RSTCOUNT
! e7 g2 Y$ X/ P: T# w* T1 H) ?9 f3 r# C AJMP DISPEXIT
0 k! c- E; U, p5 n n7 e) A+ W' u RSTCOUNT:/ A0 `9 Z( }! O7 w. f- g& O) K
MOV Counter,#0 ;计数器的值只能是0或1) a* U7 {3 Q# Q4 m
DISPEXIT:/ P. P' l: R0 `! V" J- y
POP PSW$ g; s, P3 p. j
POP ACC* y" I* W8 a0 j$ D: F
REti8 ^) w6 j8 [2 `9 l( T, I g
DELAY: ;延时130毫秒' {2 ^8 g0 L6 Z% Y
PUSH PSW
7 \. K% ?- k' M8 b, |/ ? SETB RS0
3 f) G' o/ u- z; [: N MOV R7,#255
0 J4 m- j! j& Y2 f- o7 N D1: MOV R6,#255* V, y* m5 h3 o; {, T- d! e+ h
D2: NOP( d1 E" F0 P$ L8 D. S8 z5 U2 u
NOP% s% x$ T* ^/ S1 M1 o
NOP
* Z3 \- J j% k- @' _1 F8 N NOP
8 x4 C j$ S2 t$ w- M- ?/ Z# ? DJNZ R6,D21 c6 z% l7 X5 h5 D/ x6 b- V) K
DJNZ R7,D1
" f6 o$ K( p0 @' S POP PSW! C$ f; p/ i' O, U C$ Y e
RET! H0 `9 P7 ?8 s5 f$ F/ i! h4 K; r" A2 s
DISPTAB 28H,7EH,0a4H,64H,72H,61H,21H,7CH,20H,60H
2 U5 q; [9 O/ d" V" i END
8 J4 {2 k6 T7 m( U( W; u% E" Q 从上面的单片机程序能看出,动态显示和静态显示相比,程序稍有点复杂,不过,这是值得的。这个程序有一定的通用性,只要改变端口的值及计数器的值就能显示更多位数了。( h; v) k( o2 ^/ q8 |3 ?
|
|