|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
51单片机加法器的制作
, @$ b; t9 E9 I6 n; M0 l- E% I; d$ @2 h5 E% W6 [1 W
2 z: v2 i- M$ c+ M
完成数码管显示,按键相加的要求
( R- J& T' {& h4 w F: ?此程序的电路图下载:
d) ]6 V0 V3 J% u
0 e% R) S0 r6 c, C
! a# \& X' N2 x" Z; f, H9 D4 w2 F: N" @: i
只需要看数码管部分即可,其他部分可忽略掉. 1 P# p% ^8 f8 v
# A3 x" V4 r5 n8 N" D代码如下:#include<reg52.h>
" u" I- ^- n% h& I0 f, f) I8 l n6 S0 a9 t! h$ Y0 d' g3 _
) Z8 o' T6 E( T
sbit ADDR0 = P1^0; o' P6 j, L/ c( E' B
sbit ADDR1 = P1^1;
; V/ h* L3 P8 a' {sbit ADDR2 = P1^2;
8 R' C+ B/ d( q3 b6 Csbit ADDR3 = P1^3;
* D5 ^9 x! S/ }7 |+ \) ysbit ENLED = P1^4;$ c* ~ w9 f6 v7 q# X: t
& p* h# L. i# Z- Q% Z; q+ }
) B/ Q9 L" @ g! osbit KEY_IN_1 = P2^4;6 U9 ]7 ^4 Y$ f2 h* N5 O) }- Y S" \/ w
sbit KEY_IN_2 = P2^5;
) ~* Y6 m5 ^7 p) csbit KEY_IN_3 = P2^6;1 ~# B. ]8 E3 J5 b h2 P( U/ X) v8 \5 S# \% n
sbit KEY_IN_4 = P2^7;; {" I* W. p4 O! V9 j3 c) {
sbit KEY_OUT_1 = P2^3;$ S+ A. R+ t+ \8 }- J) ]9 J
sbit KEY_OUT_2 = P2^2;
. Z, F( U" f1 ~9 v+ |' rsbit KEY_OUT_3 = P2^1;" E' y2 _& `4 d0 f) m; t- X: z8 t
sbit KEY_OUT_4 = P2^0;* y2 b3 ]% O2 Z! n% ]
2 Z4 R% c) f4 L5 `
8 Y" ?/ b9 t& a! [4 B* ~: k
unsigned char code LedChar[]={
* Z& B+ \0 `: L8 P$ G 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,. U" U: Y/ n; T! ]
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
7 P9 z! J$ p+ e! w3 } };
! r. L# Z9 x" B6 N5 k( f dunsigned char KeySta[4][4] = { 9 F! i) _# f; k" c" m
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
# [6 n v6 T- o1 q* ^ };
- O, K! j9 W" |' [3 ^/ H! ?. }1 Gunsigned char LedBuff[6] = {
/ A+ f9 D9 r3 a" q, A' w1 A6 \ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF; y) u2 Q& s# d& h! S2 S' a }1 }+ I
};( l- R. t% P6 @
unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表: W/ o. c" F, |4 [
{ 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
`7 a/ q2 S2 c# I* G { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键
& e; N# Y( V! K, \: \0 x { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键& V. ?; A9 ~* {+ J% }& @1 G1 g
{ 0x30, 0x1B, 0x0D, 0x27 } //数字键0、ESC键、 回车键、 向右键1 f/ N4 X) G- z3 x: B
};
5 a E0 d8 @7 F& Lvoid KeyDriver();9 }3 J0 K0 P2 x' a5 m% D7 A
void main()
; X6 l: r& `9 Z+ n* F" B( F, _{2 q: z8 w: f P4 l. r" H
EA = 1; //使能总中断3 c& o7 n# c9 z+ b/ q& _% V5 m
ENLED = 0; //选择数码管进行显示
! B/ h* }' Q0 b& B ADDR3 = 1;4 q' d+ y+ `# W
TMOD = 0x01; //设置T0为模式1
5 D/ h' l6 g5 p J" C TH0 = 0xFC; //为T0赋初值0xFC67,定时1ms
) C7 R* s. P% S. g3 X7 g TL0 = 0x67;
$ C3 q0 w& Y" H ET0 = 1; //使能T0中断9 Y& i6 G: y( k0 O. q* q$ e
TR0 = 1; //启动T0
. X3 `0 M1 _, I6 m1 \/ M( A LedBuff[0] = LedChar[0]; //上电显示08 i5 F- f5 S+ \( _$ L
9 I) ^ |$ V( H; I) g# C- x6 A
while (1)
* r0 a; W( ?* x' P {
2 e" s- |+ ?: R8 \, j6 W KeyDriver(); //调用按键驱动函数
$ `2 @5 ]4 O7 @( p: k+ } }
: @( G V& b' C$ n! }6 H8 `+ J}
8 [0 q4 h* b2 U8 O) u2 Q+ n2 I/ O+ W, q2 v7 b! U- ^0 @
v& E$ X# z5 U# t. J" xvoid ShowNumber(unsigned long num). S% Q( d$ ]3 X6 `8 g3 X
{; S5 C/ j) h" { ~: ~+ M" d
signed char i;
, t0 O7 u' d7 ~ unsigned char buf[6];
! v: j P1 M# m1 F- J% Y7 R+ f% P0 @6 C! u8 V, T; p
& ~/ b7 Q0 j) u% f
for(i=0; i<6; i++) J! p* E$ _9 O
{ e) N; U: z W8 e1 J) H
buf = num % 10;; L: q. r8 W6 f; z; C1 k1 P
num = num / 10;2 D0 c+ x% X1 N' o* N1 J
}
' S8 r- \! i" Y- ^3 K% m- B# G$ S% o# k% y; O: M5 F, w
7 }5 J5 g$ m# a2 P6 U3 H
for(i=5; i>=1; i--) \\gaoweibuxianshi . e9 @5 x% C+ D8 ~$ ?# B
{( n* J6 I# {4 U) {- W
if(buf == 0)4 q, | N3 K% O8 M. l6 G
{" q! _3 g9 ~, C
LedBuff = 0xFF;
+ k( b8 T1 V$ h }
' } T% j3 ~. Z1 k; W else' ] i+ _) \ P; }- P
break;
* D- O& |$ h8 P }- n9 n; a1 S/ M
9 a1 B9 n7 i% Y7 {! ?- J. w for(; i>=0; i--) \\
( B# c+ g8 P4 |+ f: F1 M- j {
5 B9 }' g8 L( |( c1 x( | LedBuff = LedChar[buf];
/ M, }4 E4 Q1 }* k* ? }2 ]7 k3 H8 b5 p4 ?* |
) }8 d; _/ Q! d% l2 A: o6 c
' R' |& j0 H3 V( G; ^- b# U}. h8 v9 n: G. t. f& p! I4 r
void KeyAction(unsigned char keycode)
! A: M6 l, g" K' s) N: {{5 y0 f L0 J. P' k6 \; j
static unsigned long result = 0;
2 P3 Z" D% \2 ?! p- ~ static unsigned long addend = 0;
+ @( |: Q/ _# o5 I: f3 @" S$ f
, D7 x2 h' n+ |# m if((keycode >= 0x30) &&(keycode <= 0x39))
1 g2 {+ @8 J2 G2 ^5 o8 |/ h" N {0 D N. ~+ X) w# r0 H' @0 t% M
addend = (addend *10) + (keycode - 0x30); ; O1 M% ` j& p) f
ShowNumber(addend);
, c5 B( D, P h }5 h8 H( _9 y3 \/ a+ {
# V" x, C a& |# E# Z) \1 }- L4 U else if(keycode == 0x26)1 u; A7 ]' |) _# k
{4 H/ `# U( k" P& L9 h# g
result += addend;
8 E7 @/ E3 o* |1 z7 ?, F% G% J1 g addend = 0;
6 m" O* L2 f) L' a ShowNumber(result);
1 x( O" K2 [" K$ z% ~" k }
3 t" b, j+ ?6 J" w! J# I. v else if(keycode == 0x0D)- V! g% X4 M7 \
{
5 q: c" H" M, H1 d( Z8 i result += addend;' c2 b- r1 E3 c, W: J
addend = 0;
4 Q' b* h- D" u* X% y ShowNumber(result);2 m! ^2 y0 W9 N ^/ @4 x
}
& X+ g/ v4 y" {; |& O. ^8 m: c$ c else if(keycode == 0x1B)
9 C% Q) M* N, F$ ?4 g8 ~% B {
+ U" F/ O. _9 R) {* x' T+ U9 v addend = 0;. @* I6 G4 m9 D8 G
result = 0;( R" A. s' h& @2 Y
ShowNumber(addend);
2 k& ? d. M. ?1 w' | } * k8 i- i; n& f. l' v
6 c% F- @2 @! {2 P- ~8 a( v+ w# g
}
+ r, ~. A% E, V. \; g [4 Gvoid KeyDriver()
# q" U- b! D) P+ \3 t- e& E{- c2 j8 y2 ?9 h0 d
unsigned char i, j;" K; d. c9 L; `- e5 k
static unsigned char backup [4][4] = {
) M. I( o, r4 [* f+ S; K8 Y {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
. T* Q. U/ G$ k4 [$ l3 @% {* }! t };
; c. z$ l: H+ l8 l4 s0 L0 ]5 Z: g
5 L5 o- v# E3 j& d& M8 N$ f5 \( R2 [3 e7 V: K/ O
for(i=0; i<4; i++)
: G& M* A; a3 \ {& H2 T3 ?+ t. n2 R; Q
for(j=0; j<4; j++)
) [, u, `4 H5 i$ ^ {* m3 V8 z$ b; o- `
if(backup[j] != KeySta[j])8 R) y/ J3 c' J+ B
{: p5 L6 x* h' Z
if(backup[j] == 0)
5 t, S7 l& ~( K. K$ ^% U" {/ a {. B: V* ~$ D* \
KeyAction(KeyCodeMap[j]);
" k* S" @. c8 c8 K2 b }
6 p* V) {' \ ~5 |5 I# F2 [ backup[j] = KeySta[j];& d0 _. C7 e- M7 j# ?( B3 M. y, ^
}
/ ~. T; _8 l6 K3 d; Z } 3 k* L3 }9 R' B+ n" O' E* m
}2 M6 k* e6 {+ E' Z* g- F U
" s' b8 b# P& q9 T
8 S9 }; Z, e- n6 R2 h. ` / V( M. d9 }$ [# L
}
* {) f2 `* |1 b, h1 }+ K" n( R- f) C! |/ U% m
+ \$ _+ F R# i! i
/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
7 X1 V0 F* Q% ~void KeyScan()! r$ A! d8 d j# r" @' P4 u, f
{# B: i! r' H: e5 e) x# P, H
unsigned char i;
! [/ _! V% A! Q* ?3 W* o$ X static unsigned char keyout = 0; //矩阵按键扫描输出索引; G7 j/ d1 B& Y- K- Y
static unsigned char keybuf[4][4] = { //矩阵按键扫描缓冲区" W* e* q( r/ S; l- T) b
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},! v8 U2 h4 \/ }# e1 b8 S o
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
% M3 r) p8 F, n };
# {; ?* O, E3 P5 N' Z
" Z& {1 d, |! U1 @9 t
* C; A& D0 a9 F/ _; O2 \) j2 m //将一行的4个按键值移入缓冲区
$ k/ m. O* a8 t$ H3 n keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
- ~# X+ G3 P4 _# ]; a keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
/ A* X2 _7 M2 E! N2 w0 \1 f keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;2 ^1 |! W: d! _6 _9 b' k
keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4; I* Q4 a0 [( f; h# G
//消抖后更新按键状态0 A; h6 y# Z6 G+ u
for (i=0; i<4; i++) //每行4个按键,所以循环4次: y z3 V& y4 S: E" ^/ w
{
+ o7 w# S* A- l0 Q% Z if ((keybuf[keyout] & 0x0F) == 0x00)8 ?( P- V2 H; C" E. o
{ //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
, ~7 _; S! T0 R2 e: H( g KeySta[keyout] = 0;; S- v5 Q) n/ ^( b/ U6 ~+ s
}
# j& m! s5 P3 l7 } else if ((keybuf[keyout] & 0x0F) == 0x0F). ?4 G9 U, w: a Y/ e' Z' R4 g
{ //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
r, z9 I1 Q& }4 s KeySta[keyout] = 1;
* ~7 E. O) O7 |* |' b }6 D* a3 I4 y( ^. }
}
- B8 w6 ], h4 {! ? n //执行下一次的扫描输出4 |. I3 S9 L5 M( m
keyout++; //输出索引递增( N7 E8 e1 }! K5 s1 B: c
keyout = keyout & 0x03; //索引值加到4即归零1 |/ s0 z0 w. L9 V2 W8 K! S5 i
switch (keyout) //根据索引,释放当前输出引脚,拉低下次的输出引脚
1 g- N' B( n7 Z/ v; X {
: @$ T: d2 q3 A6 v$ X" B" p) { case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
8 j7 Q$ e6 w2 B: `& x6 @0 y case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
0 |; J# X$ c J7 z1 g- L+ @7 S" ~- | case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;( E' I4 |$ X0 l
case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;# I. c$ S$ H2 k% e# h/ D% [/ L
default: break;
5 m4 T/ |/ x! z1 H6 T( k# f- _, G }
! q' I4 c* r0 {9 G8 E}4 w3 X9 T5 k" _, N
/* 数码管动态扫描刷新函数,需在定时中断中调用 */1 i6 M% ~& i- I+ G4 D
void LedScan()
$ D9 X) V1 L% j{
$ K1 |* T5 y% m5 p% E5 }7 n static unsigned char i = 0; //动态扫描的索引
& Z+ _/ C2 E' ?+ f, h: w& j/ C7 \% C' j# f5 J* C+ u3 Z
3 {2 r) d4 \; n. N1 D
P0 = 0xFF; //显示消隐% H0 h8 f; q- ?
switch (i), i* S4 k, Y* J3 `1 X
{0 ?( |1 I: o2 U2 B' C3 m+ m: F
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;8 K* U9 g! _# ?( y/ F( v* d
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
- S3 A" G n- I. H( C2 Z case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
2 T/ E$ [. E4 A8 a1 u; ?$ ]$ N i case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
0 t6 u9 t3 v. { W. D case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;
: B6 b1 K! S- X case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;4 f0 o7 w: O- Y; I# W
default: break;
, k. C- S6 d) J+ i" } }* w$ l+ @/ {4 i- _
}
, I' V# G3 R# K5 t' E* \9 e4 h0 }1 t: E. b/ F' |& ]
0 z- y: y/ a8 t& U5 x( D4 m: F! u
/* T0中断服务函数,用于数码管显示扫描与按键扫描 */1 s6 T5 e7 {$ n/ U* r. P' V
void InterruptTimer0() interrupt 1
! l- Z. c# c& q; x( z# L3 a{
l) b% N4 O" `. j6 Y9 q6 P. I TH0 = 0xFC;
4 o& }) u& @' f3 T TL0 = 0x67; W; [3 g1 L) p$ r2 h$ c4 w" F
LedScan();
! I1 ]! m' \" V KeyScan();
3 y5 z3 I5 a* E6 n} _% a7 h5 O9 H" n
3 s0 Q" G# i7 T% D; x& {- b+ U6 Z: e. A7 O* u, a' W
|
|