|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
51单片机加法器的制作, i$ X4 Y2 N5 I# @
; D7 e$ r$ M$ U; `$ Q5 W, w: Q
9 E) p1 M5 I2 Q# z完成数码管显示,按键相加的要求/ ^8 E; g; O7 J
此程序的电路图下载:
( J7 v" X: c! d$ ? U5 _4 _+ Z: p8 Y/ [. w7 L- Z
) M# }! R7 Z8 g. s) r, F' E& a" p: c
8 @* g$ o$ O; x/ ^& Z只需要看数码管部分即可,其他部分可忽略掉. ) w2 D0 W8 D0 D2 i+ ^4 X) ~9 v
P* ~5 `, s9 h$ F
代码如下:#include<reg52.h>
9 X; z% y' l5 ?+ e/ y$ Q3 T- f- z O- q" b _: [. R, Q
2 l+ N7 Q- G* n; n, Esbit ADDR0 = P1^0;
% ], A: P) b% u* Q4 t7 c+ vsbit ADDR1 = P1^1;3 y7 p0 P$ P+ y* z, M' p( l' H
sbit ADDR2 = P1^2;
. u6 U3 L, u. c$ _4 ? qsbit ADDR3 = P1^3;
: A7 a4 y: U7 Q" N: Lsbit ENLED = P1^4;
2 g0 W3 K: f7 E/ w- U$ X! Q8 {2 v2 v
/ W# P) p! W. t8 b( r& _4 d/ P/ U. N' b0 d% C W" N
sbit KEY_IN_1 = P2^4;
9 ]6 J8 J# B9 q5 r# b) m0 ]' v$ Xsbit KEY_IN_2 = P2^5;
F' z+ c3 P) A9 Y0 gsbit KEY_IN_3 = P2^6;
; }' i; P2 O& N0 l% L* dsbit KEY_IN_4 = P2^7;
5 ]: J# F R* y+ g8 S. d- C% ksbit KEY_OUT_1 = P2^3;
/ Q2 a; ~! D7 m5 s; csbit KEY_OUT_2 = P2^2;+ _: s2 m- j# O2 S9 H% M; }
sbit KEY_OUT_3 = P2^1;
) i) M# |/ D2 d$ ^sbit KEY_OUT_4 = P2^0;5 E! T; _$ r6 }( l! \
9 X, p& C! X- u; z0 \
: ~$ {8 R8 ]/ A
unsigned char code LedChar[]={
& f5 a) B+ U- s' o1 s 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, N! f8 m5 u" I+ Q* X
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E! x* o" T1 @) a0 P
};
6 _0 D& R5 C" Y6 \7 ]& I: ]+ K% Yunsigned char KeySta[4][4] = { # S- o! R, B; T/ T
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
! I$ C2 E( R9 ]! Y };5 C5 f2 l9 P' r# _
unsigned char LedBuff[6] = {+ V5 n( R: v# o0 |. M/ K
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF2 [; d |' S3 O( k+ f f, y
};5 b. M1 ~) x3 h9 _4 a+ j& [5 ~, l M% i
unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表' u1 ]: ~" Y. H
{ 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
; k6 [+ P) {. a1 D( [ { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键
$ _( W$ D4 y, g# x3 n" P* ?, } { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键# ?$ Q' A4 A" ^' A8 i. Y4 G
{ 0x30, 0x1B, 0x0D, 0x27 } //数字键0、ESC键、 回车键、 向右键
, x0 k& h9 t; K' z% [" O; Q };
( X$ k8 h! H9 C3 V+ X+ `6 W8 |. tvoid KeyDriver();4 C' b$ h8 b+ f0 o2 t
void main()
, R9 ]+ Q1 b8 z p2 {{
1 Y2 b% J, w4 `: W" R9 k EA = 1; //使能总中断& }* p: b' k5 r1 H. x+ D
ENLED = 0; //选择数码管进行显示# e7 J/ L. I9 C5 a
ADDR3 = 1;
8 I( o% U' O( _3 @2 u- U* } N9 A1 z TMOD = 0x01; //设置T0为模式1
+ y1 M1 {5 N* d7 [* q3 c TH0 = 0xFC; //为T0赋初值0xFC67,定时1ms( i% H8 S% Q8 {: `
TL0 = 0x67;
_ M& E; _; u9 V. o' h3 |6 d ET0 = 1; //使能T0中断
9 H2 `- e# O f& Y1 e( _. b2 _ TR0 = 1; //启动T0- \& V% N) B7 P7 K
LedBuff[0] = LedChar[0]; //上电显示0; z7 m, [' ~- c
. J; x. d# \. B; m2 ?
while (1)6 D) W5 |7 k+ p5 p7 L; M8 n. @
{# y$ v6 N4 g; G2 C) H; `/ K
KeyDriver(); //调用按键驱动函数 O" H# r1 h' b @. ~1 y& x/ G
}4 g. b( T/ P% ]5 E1 x4 ?
}
3 K8 Y4 T' {7 {2 G) h9 J* d; Y# x# L* ?
; M) K- x2 n4 L0 svoid ShowNumber(unsigned long num)( e7 I/ H9 c7 D- l( W7 R6 m
{$ ~. @& n0 ~* t- ~) S
signed char i;
/ L3 E" y, u2 y$ e7 r& W7 L3 V& ~ unsigned char buf[6];
' Y2 E3 B/ Q! l5 ]
3 Q6 |9 o) v% r0 l' T- U+ x. E& M
' C; F% _( c4 H for(i=0; i<6; i++)
0 m4 |' s" R' e. u* v( Q- n' W {5 c6 I- Q2 I' u" m
buf = num % 10;, b. }; t7 ~* x6 c0 C% \
num = num / 10;: [$ o5 D/ V0 E$ g; Y# r6 K
}
4 Q/ f' J$ f0 {! ]* X8 v, v+ X# i3 u
3 n+ [+ U$ I: e5 l" D
for(i=5; i>=1; i--) \\gaoweibuxianshi
9 X6 F1 ` U2 v% U" I5 E6 i {
0 C, v) j7 t( }" M- ], _ if(buf == 0)
2 O2 J' q9 T; p {
6 B0 g% A& V* v" Q m, I LedBuff = 0xFF;4 b/ I* B8 m# b$ _$ U
}
; X! [' a- x5 _ d5 `5 ]% h else
) f6 J# h0 ?; i break;' l t( b; ]# n6 }
}1 V# k D' O1 f. P S* L! f6 n" K
$ h. j8 w7 |$ Z
for(; i>=0; i--) \\1 Z" d9 f6 q E2 a9 O, F8 z
{( I4 w0 D f5 Y* Y, a
LedBuff = LedChar[buf]; % ]. H+ Y2 Y, m
}
/ I# K) N7 B4 r/ y Q2 h X* y# S& t* z ]9 _, c( q0 |, }
0 r6 J9 ]1 j i4 g2 l2 A& L
}- x0 C& Z: M# J
void KeyAction(unsigned char keycode)
( E) D' g( m. i8 b) s3 `{ }2 n! |* V; g9 F7 b% A
static unsigned long result = 0;7 M: Y8 Z% n* S/ E5 ^4 S
static unsigned long addend = 0;
5 K- P- _ @0 t* C 9 P) x* c. }* U8 N4 i6 w
if((keycode >= 0x30) &&(keycode <= 0x39))
0 W& j" [2 v. v0 X) D/ Y j: p; _ {& d- O0 r1 F$ V( S7 S2 G$ Y! K: m
addend = (addend *10) + (keycode - 0x30);
) X4 J" k& @1 d9 Z+ p* b: r# \ ShowNumber(addend);
$ ^: i6 D) ~* n% S$ m0 z2 W }
. b% U5 s0 G/ r$ m% d5 e9 E( ? 2 X! Q; z/ p) b8 t
else if(keycode == 0x26)" X7 e& }# H0 v0 Q; E( P8 ^
{
2 F( Z5 a' ]/ q Q* y: i8 X7 l result += addend;3 b0 y7 [, m! b0 Z
addend = 0;
( f# S1 D0 a$ Y# s: x$ J7 V ShowNumber(result);
$ ?- Y0 r2 m# u4 U k' p1 ` }2 e$ M; P9 c( R! z3 l0 I
else if(keycode == 0x0D)
4 O8 @6 G9 Q! D O3 o {) L, J" _* d3 Q5 k8 l
result += addend;2 F- [9 |% C- M) o' I
addend = 0;
2 b+ Z6 r+ B' v) D0 k& ] ShowNumber(result);
( N" Q+ ]0 I, O: O, k$ r' [+ x }
; W8 |- I* k8 I else if(keycode == 0x1B)
# W9 P, L5 a# E. g! @+ q. e" C) f {
' m% l; e% o& j addend = 0;
2 k$ m. m$ ?! H# X& c result = 0;
0 Q# P. { W& L ShowNumber(addend); 3 a+ }/ k" d3 a8 r$ r
}
) i8 @3 C3 C% ?' ~* I" I
( c# ]6 j# [! f7 u1 I3 \}$ C# x! A- |1 W+ `" F
void KeyDriver()
0 V) Y4 k+ ?1 v, v/ Q{( Q& _3 H2 v1 L; ]5 c d/ \9 ^
unsigned char i, j;* D+ S' l' o6 I! q) E; M2 B
static unsigned char backup [4][4] = {& v) }. g2 V$ r7 Z6 S# p2 K
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}2 _) j+ Z* i* l, f9 M3 f% Y6 _
};4 M1 o/ d* [+ `3 Z; h& ^ f
8 r) \! g. ^. P0 I4 O$ Z
# ?8 N. u2 l, Y8 w A$ Z
for(i=0; i<4; i++)
' B8 i& ?7 u" j- R6 L0 C/ R# @" m {
- ?2 i) E) _* P- E" y% L for(j=0; j<4; j++)
1 s) {! a, G0 \ {
, ?7 {. r; t7 r if(backup[j] != KeySta[j])( [# \- | F$ O! o; N
{! \9 L6 ~; m5 e# X" g2 Z6 L
if(backup[j] == 0)
. p8 `, f3 F6 I0 M7 k/ N) T {
) M: W& z: m4 P* k7 @4 i4 \* Q KeyAction(KeyCodeMap[j]);. v8 N6 b z$ L( v& {; }- I
}
) ]- K9 k9 z( f% Z! s+ R backup[j] = KeySta[j];$ M( U1 \1 F9 d4 V( x' d! X% L
}0 U% a) R% g( _/ f4 n3 i. i$ i+ V
} 6 l& a F! q6 _' F" \
}
0 X- [: B- r' U- d' `
# A/ b/ ?6 G0 u3 G2 X# B7 |- \2 f/ ?- {. J# Z* }! R! V4 M, `
0 J# X8 [4 Z: z2 J# C; S+ ]- A}
: t; x3 _+ N, U& r4 _$ d- v' i2 P6 t4 R' B
9 D# [8 T9 ` x% t* g9 ~
/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */$ [/ ] N+ d4 `" u; B0 j; t
void KeyScan()
2 ^' a! B1 l/ _' m0 r{
$ A" h' c- ~* A1 ]+ \ unsigned char i;) o' S3 T* g8 L7 S C' U4 }+ d- r( U- m+ B
static unsigned char keyout = 0; //矩阵按键扫描输出索引/ I: q6 [: o( `3 h
static unsigned char keybuf[4][4] = { //矩阵按键扫描缓冲区4 p7 J5 ~; P$ `2 _
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
* J! v" d; c# A {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}) h/ M- v5 g6 z. r
};
! L! y& A0 D; {4 I: K" D/ y4 H w. {$ B6 d1 _' l! J( D) Y
; k! N. X7 C) ]+ O8 h) ~- z* L
//将一行的4个按键值移入缓冲区: ?+ ~3 y8 F- [2 z. E* `; o8 ^* G
keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
- i, \& u9 Q6 O m4 v: O keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;, u0 c7 `( U) Y/ K5 o) U
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
6 Q" i8 B7 c4 p keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;$ W6 E5 T c% a9 G7 s% O
//消抖后更新按键状态
- W" t8 O- D a1 s2 r0 y for (i=0; i<4; i++) //每行4个按键,所以循环4次7 H) I1 n+ X& i9 E. \
{
5 e+ O# U" l: A R7 P3 M: |; ] \ if ((keybuf[keyout] & 0x0F) == 0x00)7 D) W7 R {) J4 d
{ //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下/ k8 z. H h5 V& a8 i6 k
KeySta[keyout] = 0;$ Q( U7 u+ `4 T9 g$ j" s3 `
}. n: n- E# ~# s, R. B( q$ `
else if ((keybuf[keyout] & 0x0F) == 0x0F)
; E% K& [+ v9 K2 Z# U8 N0 O6 K/ D { //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起/ a4 e% b, \. ?: c
KeySta[keyout] = 1;4 |0 M) I6 P$ c, U
}2 n, |: q1 f$ d% X& p) i N3 a% i/ v
}% T, s5 c/ [9 f# P/ H
//执行下一次的扫描输出7 ~/ }, M% y* c3 t: ?) U; N
keyout++; //输出索引递增
- c+ T, E& y% \1 B; M1 \ keyout = keyout & 0x03; //索引值加到4即归零
) F8 G; b2 I8 F& F; E switch (keyout) //根据索引,释放当前输出引脚,拉低下次的输出引脚
: t! D; |) q( X8 c h5 N' P! t/ r {
& S7 G$ p, S" y V case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;* I# @/ ]( r: U( v$ F2 q
case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
) h* W& ]' G" ]+ S( s3 H1 u/ o: ] case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
8 p; g; Q# d. ?0 [1 i case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
$ ]) D* E' Y( H5 Q$ m% x default: break; B9 B, K4 j' `$ j* t# Q; ?
}. Y# q# u1 q4 f. E
}4 A! C( j4 Y4 e! z3 K) }6 y
/* 数码管动态扫描刷新函数,需在定时中断中调用 */% [; @. D* q( U+ q/ Q2 \
void LedScan()
% d, Q/ ] d) D% o" Q{
9 D$ \0 G1 `# _: A( M static unsigned char i = 0; //动态扫描的索引- S* k1 G' u$ A+ f9 I& B% Z
9 j5 S U) P- u4 H6 ?+ P
7 G/ y6 }1 o, F% ]5 _3 l q
P0 = 0xFF; //显示消隐
) s3 i: w2 P4 I' p& x1 W5 S3 S7 H4 | switch (i)
{( X) [6 X: H; L. N {$ [ q' y; v& ]! |* T& L1 Y
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;
) O+ F. f8 B' P: R5 E case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;0 s2 A9 c$ {) ~
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;5 i2 V- U7 S, B3 M) ~
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
0 X l4 N7 T6 d) V2 y: k6 {# w. s case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;" A Y' r6 _- E7 b& b6 _* K- M
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;
6 n4 K: X$ J$ t* d' ^5 N; c: a default: break;1 I2 J- c0 H& K; e2 J! O
}6 g! P+ o) O4 _# R
}9 ]% H3 |! H2 c, v9 ^* y& [6 z
& W9 N5 K# u$ z y, G+ P
: A' p" e: r, Q/* T0中断服务函数,用于数码管显示扫描与按键扫描 */6 { p# E! U3 O+ L! h# u
void InterruptTimer0() interrupt 1
) E4 f0 _$ z; R. l{7 l; I( M2 {: v* Q& I4 ?9 @8 z: [
TH0 = 0xFC;
+ j; a# r# U- [( K4 u: ?; k1 J TL0 = 0x67;
) z* c/ J% P9 ?! J, P. N- k LedScan();6 |4 g+ n, n% K
KeyScan(); ]" U$ J9 T' t! X( d3 c
}* N9 i+ J }6 c* s6 T4 {
9 Q; g# L, n& T" Q8 r
: K1 o! O$ M q% r
|
|