|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
51单片机加法器的制作
$ B5 M) `6 q) C- j G2 Q
c: \ e0 K6 f7 r
& I% i2 k% s, \' P+ b完成数码管显示,按键相加的要求
0 |. h$ ]7 H! M$ {9 v9 [此程序的电路图下载:% @. w: t* N% ^* P% H
$ F" [4 f% M6 g, ]* {( T2 m& b
* n) j! K( u- K7 `5 q
4 {) X# t7 j# Y3 x6 c, m: o只需要看数码管部分即可,其他部分可忽略掉.
5 J4 z+ M& |. r, R* ~8 G! P1 X7 S/ d! r/ E
代码如下:#include<reg52.h>
# \; j! X0 }) |5 v6 |! T4 T4 [3 f. S' z* b$ p3 C6 ~3 j. e( K
) C$ q0 ~+ T5 v( X5 M7 l0 E% Bsbit ADDR0 = P1^0;. h5 I) `$ P7 v) ^! B* x* G% o* z
sbit ADDR1 = P1^1;5 A- v5 R9 A- T- J
sbit ADDR2 = P1^2;
7 \: m; j7 z' t% ssbit ADDR3 = P1^3;, R' @; v6 F0 c- s
sbit ENLED = P1^4;7 U6 k9 l/ G4 r, s+ \, O5 ~
Y$ e% m* I' s! n a
0 h7 h" f; K( {
sbit KEY_IN_1 = P2^4;
6 O" |" f- Q. {0 t0 W ]sbit KEY_IN_2 = P2^5;, j2 j" v. X8 k/ h; s# x
sbit KEY_IN_3 = P2^6;
: c; l6 a7 ?5 f/ s. X9 g( h9 [+ Y2 `sbit KEY_IN_4 = P2^7;7 K" h- J M. U. R, C4 ^1 J
sbit KEY_OUT_1 = P2^3;
! I% P$ w: E5 N+ msbit KEY_OUT_2 = P2^2;
; s3 e9 _& L; e5 X0 V0 Psbit KEY_OUT_3 = P2^1;" |' _! ?6 L/ ^5 g1 f6 C- ], \; g
sbit KEY_OUT_4 = P2^0; e! S1 W# Y* C3 ~) b
M( P- T' }$ y
1 \/ e! k0 a: ]: h0 H5 ?( u- |unsigned char code LedChar[]={
! }$ T1 d$ R0 w; t" {% p 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- l$ S! H- w+ A& p: ^( ]3 ^ 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
/ A/ L0 I" r5 _( x. T* [8 F };
2 \3 d% F4 @* \unsigned char KeySta[4][4] = { ) a% f$ b2 s1 z# [: R) B6 k. r% C
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
" }5 s; n/ g8 J9 e };
% K- j' x2 j' \0 Munsigned char LedBuff[6] = {8 h/ d8 `& T; R% i' c& X, {; i8 h. m
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF @/ c; M. {* F$ U4 Z4 Z, ?
};8 m0 Y* V; e& @( O/ O2 R; G
unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表
" P1 G4 u6 @, u& w$ i; C& S { 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
8 [# I1 W! j$ X3 F" A$ N4 J { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键
5 q" h% u2 o% G" @: m; _ { 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键
) s$ e2 s& [1 P* X6 _9 ?9 ]! }* j { 0x30, 0x1B, 0x0D, 0x27 } //数字键0、ESC键、 回车键、 向右键5 y. A% ?% a) \% u/ T2 M
};; W. T6 B, D* d* E' d
void KeyDriver();( B4 a# f$ P2 A# J& c. S& c1 A2 y
void main()
- e& Q: F* _& ?* h3 N4 |. @5 {4 x; T{
3 V. V8 e! ]: }* O0 C+ R- a& j EA = 1; //使能总中断
# Q; w- W+ ^7 q- x: r ENLED = 0; //选择数码管进行显示7 i1 m6 ~- W8 N' `, @. Z
ADDR3 = 1;$ ?6 y* e2 ]# ^" J
TMOD = 0x01; //设置T0为模式16 B# `0 n. z1 P' e$ A( V# K7 M
TH0 = 0xFC; //为T0赋初值0xFC67,定时1ms
9 z) b4 f' i6 e6 C! ]3 R TL0 = 0x67;- S- ~8 N+ F F
ET0 = 1; //使能T0中断
* l7 k+ e2 G7 L9 k% Q& r TR0 = 1; //启动T0, Y. B8 C: |2 ^: J2 N
LedBuff[0] = LedChar[0]; //上电显示0! Q4 v8 p, U. t5 I6 y! j
$ D3 h2 f* ]( s- G% N7 \ while (1)
5 W$ O. l% R) c1 L {
7 |8 ^( }* t% c8 P- I. ` KeyDriver(); //调用按键驱动函数, m8 m. q, P' m. |) c
}
1 Q( ~& T: k. X) k1 D% I}
* T( N% W- g3 c2 |" m, M( ^7 A% T+ s" s1 w6 a: ^9 }* a- B
& p* Y" e. W9 z- x5 E/ H' T) R
void ShowNumber(unsigned long num)
$ J8 @4 l7 A* M4 A+ s{$ z: @9 g. J! y
signed char i;
f4 }5 o7 u( s unsigned char buf[6];
1 G, c0 X2 o1 A" G1 c* L
% a1 J- `) \1 N
4 P, i+ @9 u3 C# }1 q4 W; J) T for(i=0; i<6; i++)% k! Z9 u: e9 B) x( K+ @" A( D
{$ E, }# ?; M& x* V+ v+ C
buf = num % 10;
6 y3 d! b, P- M3 T; J; _/ c0 F num = num / 10;
; A& O5 |9 L' {- w }
$ R5 v: s& }" E* m% {# k% S
" s) a9 q( t) N
: ]! X) @) C s for(i=5; i>=1; i--) \\gaoweibuxianshi ! N1 @# t5 S) } d7 S y O
{
9 x9 A6 w; M' r& Z# j8 F# I u if(buf == 0)0 I- R3 P- X) W
{2 j$ x/ Z3 `+ U& ]9 F* r' t
LedBuff = 0xFF;: G: h2 S' V0 j; T
} B) |% m9 }, u! q2 n2 \( H2 a
else3 p- x; @& O; h, ~; H W; x" j
break;
& g; {! X! m0 k u+ z+ R }
. r# H& f+ Y3 W V) T; j6 d ) a1 E; e# V1 j- g( D9 e
for(; i>=0; i--) \\
- O. q% I6 I0 D5 |3 x {. `$ l: M7 a6 N& s% b
LedBuff = LedChar[buf];
5 p! _; }9 X/ o2 G+ ^ H) Z% Z6 [ }; i0 M. ]9 w$ _: _; I5 ], `
% i& k& |! e$ m1 l" Q
8 r5 E- G4 g- P/ Y* W& U: j}* K% Y0 I# Z" _
void KeyAction(unsigned char keycode)
" l; v) f8 |/ F" K0 p- {{
7 U9 I& m2 Y, ~( F& a/ R3 }, \ static unsigned long result = 0;9 m& C- z8 V8 a
static unsigned long addend = 0;1 n: |% ]0 e" [, A0 J- l* J
0 h8 }/ t9 J3 X, ^; N r# d) [ if((keycode >= 0x30) &&(keycode <= 0x39))5 C& ?$ e$ R1 O
{6 {. i V: Q% ?; X, [
addend = (addend *10) + (keycode - 0x30);
3 }! D$ O6 i! {1 w7 i% D7 s2 r ShowNumber(addend);
7 F% E# U. U5 D: H% _9 J) ]1 g }
/ W9 g) d4 o4 b# H% { ; G3 {, Q6 a0 s% D
else if(keycode == 0x26)
' b. Z: s, n" A3 e' \ {
, K: G; v1 ^: k) [2 t3 K% c: j3 B7 ~ result += addend;' [# J5 E( t1 j! y' k7 y
addend = 0;
) ]2 b: n. R! s6 |9 w" S ShowNumber(result);
/ R* G" z* O! L, a }/ f* B# s; _8 e1 E2 |0 A1 P) p
else if(keycode == 0x0D)
* F) U5 q$ p) f: S: B {
1 l! {) V4 w5 ?# L4 | result += addend;
) _5 R+ E! S! j. N ]* e addend = 0;
8 m6 [2 k9 e4 c$ j! h2 K7 A ShowNumber(result);
* c1 Q: M% L! T3 J3 @ }
/ K5 N7 E2 ^5 U8 \ A else if(keycode == 0x1B)
; s' k, I. I, F& t$ u: p {
7 `0 ^6 u" ^3 w- D; e addend = 0;
! ?3 L3 o. C/ R# `, O result = 0;
" e& `2 e8 L3 j" S i2 Z: t# I ShowNumber(addend); 6 T7 \0 Z0 h6 m7 `
} ! x8 U5 M1 S* V( B8 |! I* r8 T8 k8 n
6 i, d- e3 C3 t3 N
}* M+ r# N( p" {2 y+ U3 v+ s
void KeyDriver()( F( a+ D' s1 N) F3 x0 d! f& J
{
" t: y3 j, u" p+ d4 i! {! q2 \ unsigned char i, j;5 R2 M, e# z/ y" a) Y1 D/ Y
static unsigned char backup [4][4] = {
% g6 v" x O, H% t- p i: O9 Q {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}- U, |3 K" @/ j5 }- C
};
" s0 S# m" k1 L3 M
* I2 L% A% W. Q* S4 @
; H2 ]) n, @0 b" W1 F for(i=0; i<4; i++)
4 C! K9 u3 V8 `( Z% J( ^ {
% D0 |- a2 {2 _* X) o3 T1 r- q for(j=0; j<4; j++)( j7 \! V! r6 s: h2 G6 }9 |" L: Q
{ e' i: f3 {8 s5 L
if(backup[j] != KeySta[j])6 D7 r2 g$ W; b/ _& s
{1 i" o( Q* m$ W3 U9 W
if(backup[j] == 0): [1 O. h% h7 ~# I) ^. N1 G7 A
{2 w- q; a* G1 t) h! {8 N$ h
KeyAction(KeyCodeMap[j]);8 Q+ Y J( |, a; C
}
9 \9 a# m# p4 j; q- O' @+ Z backup[j] = KeySta[j];1 R+ s% V1 A L5 F+ ?/ i1 Z2 f
}
* F5 ^- A" O/ D* ]* z6 C9 J- ^8 ?$ }+ B }
& ^$ z2 T, y+ U& T# ^3 O }2 x& Q9 z& o% }4 ~* }
% R# t; `* q; z- }% V: x, k) G1 T z2 N) D. }
! M* w5 p o% z/ `4 T}
9 O$ x5 L$ T3 t' C
3 R4 E1 J& k1 V: j; T# L+ S8 [6 \ j7 c2 p3 a' G! k8 k# c4 @
/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
8 ]5 _! c. e4 ~; Evoid KeyScan()0 Y0 T& V# z7 p/ U1 P0 A9 ]
{1 ]% d3 v4 |; `# f; ]" }
unsigned char i;: }, P% b% T# t& T9 i
static unsigned char keyout = 0; //矩阵按键扫描输出索引% @+ u/ y* q+ F5 r( U8 Z
static unsigned char keybuf[4][4] = { //矩阵按键扫描缓冲区
) x0 g0 A- D9 M, C {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
2 ^$ k- [) ^& H, n* N, F% e {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}) \* }# O, y. l8 X' D3 M& H
};
5 r. d. i8 A( g( z+ e1 B
! j N8 _ N W3 s7 P3 W3 g3 o1 f' i% z% w% ~$ M/ U
//将一行的4个按键值移入缓冲区
5 h# S- T' q( F/ G1 l keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
1 F8 w# i4 \. R3 p( k$ w keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
; x" s# J* r! H7 o5 ?$ M keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
6 m- E# k$ d3 m. ^8 G' D8 h keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;* e8 l1 g! {3 V3 a& k6 {9 w* J% ~7 `
//消抖后更新按键状态
+ e5 t( t& v' ^& h9 G6 [ for (i=0; i<4; i++) //每行4个按键,所以循环4次* {3 f$ u* |2 Y
{
2 I- G @ [$ K* `" ` if ((keybuf[keyout] & 0x0F) == 0x00)
7 H* X" M% I# @+ ~; t { //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下8 u, [1 T0 ^; y3 X
KeySta[keyout] = 0;( a- ]& t# ^* R( A, w$ b" h2 {7 U
}1 K0 o- s5 E- n
else if ((keybuf[keyout] & 0x0F) == 0x0F)
$ h) }. }6 O7 x" K3 v3 t! H( U { //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起8 M9 l' ?/ w- `+ g0 O8 [
KeySta[keyout] = 1;+ |* b$ A9 q- N4 Y
}2 Z4 }; D* ^+ z0 _# O+ Z9 R
}% [; n' X' X: O: J" b4 \
//执行下一次的扫描输出
: {# s9 p: @! E+ L keyout++; //输出索引递增
! e& Y0 P7 V! o) l keyout = keyout & 0x03; //索引值加到4即归零, i3 O* Z8 o, m, h M
switch (keyout) //根据索引,释放当前输出引脚,拉低下次的输出引脚
9 [# P1 P" |$ u k {8 f5 d) u. R. Q" c
case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
* {+ o* y r! h3 s case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
- I$ m, N6 P1 O% Q" t case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
5 C7 h/ l4 m: D w& ]- ~/ T case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;4 C& R) H" ^5 _/ ?! J: ]
default: break;, W7 i! H; M' U+ Z/ W# l
}4 o4 p9 D- k: |
}
6 L. n: b1 F/ n' O& @+ @+ b5 o% s/* 数码管动态扫描刷新函数,需在定时中断中调用 */
: e' }) X9 X8 N1 _void LedScan()
+ s* m1 R$ J( Z2 W* b! o; U) l{( m) _9 n$ k) L0 Z5 _' b
static unsigned char i = 0; //动态扫描的索引/ p) X+ F+ N# n6 Y/ Z3 S' E+ K
+ v# [; W+ D" y/ |9 p
6 N- j' t8 R2 X4 {' B( m P0 = 0xFF; //显示消隐
2 P$ B8 A7 @! n- D6 t9 i switch (i)
0 I) o% s, R0 r/ \" W5 K {
% c, |' ~0 V+ l" p! W8 u0 ~ case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;9 {% o! w8 @& A0 q2 A1 S8 Q
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;
- w( n" i% s2 g case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;' W2 Y7 D; [" M: j4 m9 I% M! d
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
' n- U3 W7 B3 H: }/ `! N case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;/ a {; H$ t& V, H3 {$ [ ?
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;
+ ` u% v5 u% b# h2 J, \" V: q default: break;8 G. m+ d3 D4 S
}
; \ v- Y0 z/ s}
+ ^( Z. C0 V& t0 |" y9 c& P1 W5 t+ F5 j% f. E
; m0 b* T. p8 m2 {7 G9 h/* T0中断服务函数,用于数码管显示扫描与按键扫描 */3 l$ M# ?2 G5 D! c
void InterruptTimer0() interrupt 1
6 q* x) W' K$ t( X0 E3 C{
) J8 X: N2 Y3 s7 e8 G TH0 = 0xFC;! i8 S6 l6 h- q( s" {* X" M+ m* l
TL0 = 0x67;3 c; D0 B0 y; b2 C* q
LedScan();6 }" i3 g* q) }) x- y. y: N
KeyScan();, g+ Z* {- Y- x
}* M6 Y4 h4 m# @. u( `$ F4 M
: B, }, a! l6 W- O6 K6 K: {
3 Y d/ ? U6 y" ^
|
|