|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
51单片机加法器的制作" `3 i: P+ H' b+ }/ r" |9 t
% y. A1 U3 e+ k6 }6 M% r
. {5 Q6 ?/ ~# F完成数码管显示,按键相加的要求" S; x$ B J' i, A- ^, [, W
此程序的电路图下载:
. L5 g. w5 X* y8 q w; c5 X9 u
0 c) c5 R, W6 _: t: T' ]# k# p! H ]9 d- D' f: G6 V" [
' n6 @* p" ?: E; _8 T6 _
只需要看数码管部分即可,其他部分可忽略掉. 2 C7 w5 t# e/ c8 c
! m' ~* Y' E( _# S, K- P
代码如下:#include<reg52.h>
6 B" p" y1 D7 o, h, F# H' w. b
. q+ t( B! z- E& V
- U) K8 N- U# q! r' T3 J. Y1 Z1 Qsbit ADDR0 = P1^0;
) F. c, _- v9 i, v' J# L# nsbit ADDR1 = P1^1;
4 _2 D7 G6 o6 `8 Y7 S& csbit ADDR2 = P1^2;2 h( I: d a, ~( i5 A
sbit ADDR3 = P1^3;
3 U0 W6 f# O2 R- T/ ?sbit ENLED = P1^4;
5 R. U1 k. \/ I, R4 u* E
) l* e! `3 |$ s
& v: A9 P+ @' n) bsbit KEY_IN_1 = P2^4;
+ l6 O( I5 M' v7 r; Z, [sbit KEY_IN_2 = P2^5;
1 e {% G" e8 Z0 g7 G. zsbit KEY_IN_3 = P2^6;; B) o/ Z; [* j8 E- w2 @" M) C& @) {- S
sbit KEY_IN_4 = P2^7;' y% L. O: S- W( |
sbit KEY_OUT_1 = P2^3;1 ~0 ]2 }6 i0 Q; N) {
sbit KEY_OUT_2 = P2^2;+ v" x, X7 u* m+ t' ^
sbit KEY_OUT_3 = P2^1;
* h# e {( V+ w$ Fsbit KEY_OUT_4 = P2^0;
+ o6 M. V$ V# b L" e! v' [' p& q
3 B# A! ^- b `* b8 d( Z
8 c6 F l) p- T" n; m! ]unsigned char code LedChar[]={
- a" ]3 w% ^- `3 T2 e7 s2 @# t 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
: d# i0 @! V% {/ q) M& H2 [1 | 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E0 Y# K% E1 {( N; K. Q1 Y V
};3 t {& m8 E; B* O) S$ T! I
unsigned char KeySta[4][4] = {
$ w7 S! B0 o6 T: y, k7 T# t {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}5 q+ l P2 P9 }4 h7 }: M2 }
};
* W) T8 ^( v3 C& \unsigned char LedBuff[6] = {
# X$ S) p: X# l: R5 [4 E: s 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
! s" E+ q+ D( _) F };) ?) A6 z6 o5 V5 a {0 L! s& X
unsigned char code KeyCodeMap[4][4] = { //矩阵按键编号到标准键盘键码的映射表4 A0 J( j; K) _8 y* M# n1 x; n! P
{ 0x31, 0x32, 0x33, 0x26 }, //数字键1、数字键2、数字键3、向上键
8 E5 c) u. j( L# n+ X ` { 0x34, 0x35, 0x36, 0x25 }, //数字键4、数字键5、数字键6、向左键$ g1 ?2 R* H: `# t
{ 0x37, 0x38, 0x39, 0x28 }, //数字键7、数字键8、数字键9、向下键5 b" P; P: r0 L- @7 N
{ 0x30, 0x1B, 0x0D, 0x27 } //数字键0、ESC键、 回车键、 向右键' E) M8 G- D5 _" K5 S% e9 S
};
1 J* Q# ]4 X( G' Evoid KeyDriver();/ A; C+ v; D% F( H% b) [
void main()
) t& L' i: C8 t7 E( v( m( S- g( X6 O{
7 L3 ?; Q. L$ q+ G, c EA = 1; //使能总中断7 U) m P; k; y5 ^& y
ENLED = 0; //选择数码管进行显示3 L: s6 M9 e5 j! g; l
ADDR3 = 1;4 E) |! d' D6 B) t# d
TMOD = 0x01; //设置T0为模式1) N; }0 M y; @8 D. t6 c
TH0 = 0xFC; //为T0赋初值0xFC67,定时1ms: ~/ {+ x5 ]( w0 j' Q
TL0 = 0x67;. p9 R2 L/ i2 K. @: N
ET0 = 1; //使能T0中断
+ n) I6 z& q( L7 M TR0 = 1; //启动T0# `1 M6 D, @; H t& T+ |5 x& I: c3 c
LedBuff[0] = LedChar[0]; //上电显示0
3 S }6 ^+ C2 V. c$ E! t ) d c( ^# x( A3 t0 Y. J! |1 N6 i
while (1)" t! u6 Y3 Z! k9 i7 G
{
5 ^0 c7 B4 t# h6 D& g6 l( V KeyDriver(); //调用按键驱动函数2 W/ B. l' {: [' \! D5 W7 v
}! Q' d7 ~# p! T: Q+ p6 ?7 T
}4 b& K; `8 t9 v! L8 y8 U- L
) }" g+ E; F4 F6 \- ?) A- e
1 r# O( L6 f( S2 ~: V5 @- Evoid ShowNumber(unsigned long num)
( g; ]! n; ?0 R" W8 r3 W{
9 y% F# e$ u$ ]9 t signed char i;* ?$ ^7 ~( Y# e1 t# r. n
unsigned char buf[6];) c" R/ `+ L9 E' H: U6 S
$ G9 l4 I' v0 E* R6 C" {! p" N7 L7 a, R# S) b9 A O9 J9 d- i
for(i=0; i<6; i++)+ S8 ~8 _8 b+ q* g# S0 W7 M
{
' O9 ]! q" f2 h buf = num % 10;3 @5 M7 F$ f: y Y% a
num = num / 10;
9 G. A& i& y& d6 Q6 L: B* p }+ v! _5 W9 B. `8 m: u
3 x1 r! A; t* \2 g6 e* K
0 b5 W4 h- a& J! u3 y* L# T for(i=5; i>=1; i--) \\gaoweibuxianshi 0 \4 Y* f( X! w0 P( A' i1 @4 c
{
/ \6 O: [; ?6 A7 f4 E5 Z9 ? if(buf == 0)9 u; O2 m9 a" s1 u1 h
{' v! M3 f3 t; o* z' q
LedBuff = 0xFF;
. w `( I0 q1 `; _" w }
$ r* d& K2 D8 K; i else
4 N2 k: t1 h, o9 N break;
) Z. H3 v) [) e8 i6 A }- A" X0 p0 e) d. K/ @& r/ f7 j
& x8 S0 w$ ^6 R8 j' g for(; i>=0; i--) \\
% Y! Z2 J$ Y8 ? S6 m3 F {- B/ \2 A0 D: L( W# v$ F7 D3 g1 e9 q( A
LedBuff = LedChar[buf];
0 a1 Y8 g9 S. E. n5 e% `* o }3 ]1 o! F0 o5 B* {4 m. B- B
5 R: ~& j/ y/ `
1 ~! d. m3 e/ k7 q6 X}3 s' ]4 b% m5 \- I8 b0 L+ e1 ?* D9 A
void KeyAction(unsigned char keycode)
' I" b/ S8 ]6 D* s{
( u# t1 q& g$ l" P8 o- V, M static unsigned long result = 0;
6 }" |- Y$ x' p% M* v, x. W static unsigned long addend = 0;
& [2 K3 h" n+ i+ Z8 @4 b
6 y" B% q* E( l2 K2 `8 I if((keycode >= 0x30) &&(keycode <= 0x39))( k1 |# S; x$ z1 v$ U; s( j9 U: Z0 D
{/ u4 y, C' K& @6 k% R3 x) q
addend = (addend *10) + (keycode - 0x30); 7 u |' t" @9 ~8 v) u2 O
ShowNumber(addend); - f5 Y/ }2 g; ~1 o+ I
}( o; a; C8 c- o7 G1 \0 A
8 {4 Y+ E7 H$ G. q else if(keycode == 0x26)" l: O$ r( o& h1 o+ }
{# e! U: ^2 R. W% }, c/ ?
result += addend;* L0 f; |" @! t+ C) B! o- q- s/ [* O
addend = 0;" R Z" E; N# w7 E. o1 a& j0 t4 l
ShowNumber(result);
, u7 W; r9 u. W6 v' Z }
( }: v7 v, O0 o9 m& N( B+ f else if(keycode == 0x0D)% i5 a: C& d2 Y4 O) w* F% W5 c
{
* I2 L, ]5 c& a1 N& m6 J result += addend;; [2 K7 U9 s! f+ d0 I
addend = 0;8 l2 [7 u( ~+ K7 J) _ {( w* S- b
ShowNumber(result);
' [7 h7 ^" g) t3 i! A" z7 w5 a }4 `. m( q% U6 {+ m4 b+ A, h1 m: F
else if(keycode == 0x1B)8 v7 r7 l% T+ k+ E" _! c/ K4 ?! T
{' Y& E% @! j4 K2 _" ^/ L" H8 E
addend = 0; w* }: s( m; ~% K% q
result = 0;
1 b! h7 u) G# j ShowNumber(addend);
5 X' @2 a5 F! ~3 {* \3 m& g }
3 A& n$ p% E* ?* d2 B# f- n ; q2 Q* R9 H H$ v/ _* \
}
# \5 C& y# Z. `2 Avoid KeyDriver()1 Y# R) D7 E4 j
{
: ?% J! k9 Q; u: b8 T+ b6 i unsigned char i, j;9 M- _' ^+ l2 D& _' }: ]
static unsigned char backup [4][4] = {. q- x, l" K5 a# q! |: c
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}; R e' ]+ T" W- E4 Z, ?
};
% d+ }# Z# l8 s# |( [
5 S& s+ E, g( G. l# ^* j; K! t+ _" U- v e0 p, r
for(i=0; i<4; i++)( s; g4 {. _! k. _0 N
{( Y. \, G: B- k2 d
for(j=0; j<4; j++)* b. S. y5 h. j( L) G O
{
3 p* ~) h# E5 n+ U if(backup[j] != KeySta[j])8 y6 ]: A ?) I1 @5 O3 X5 A, a' V
{
, m$ A4 X6 H5 ^6 _2 T- F/ f: ~ if(backup[j] == 0)
' C# t' `# r6 \, A9 w( p {
- j& N; s g* u5 V1 g KeyAction(KeyCodeMap[j]);
- @5 y2 y; ]8 q7 B }) S f3 l/ F( p" ?
backup[j] = KeySta[j];
5 C0 a, N- O; n' d }! m: Q% y; `7 R0 Q& P
} 8 w. p: ^0 r* o2 P2 }1 t4 x0 P, j
} `* u# \1 @# N9 e
. `3 s$ s) Y& E& e
1 O. ]6 S v" G3 {6 W : g8 P! i7 c9 j" p
}
! L U6 O( C3 K8 W9 `) W. m# e0 t
; X9 D" d3 a8 k. X9 x- L) Q. ]6 }: B
/* 按键扫描函数,需在定时中断中调用,推荐调用间隔1ms */
! l- Z8 a, V3 R* \- Jvoid KeyScan()! x. [1 y; E1 l: a+ r
{
5 I- l+ W: ^ B6 `& z9 S J unsigned char i;( o0 N1 F6 C2 z3 a8 Q# H4 q" m
static unsigned char keyout = 0; //矩阵按键扫描输出索引
* ]& j5 f$ ]0 u7 F! q static unsigned char keybuf[4][4] = { //矩阵按键扫描缓冲区6 F. V1 P: p1 z: I! J, }( e8 U8 B
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},! B0 W* ?7 ?4 j4 |# G0 X
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
' P9 p" ]2 M" o };7 z5 c6 z) d% }' C* b" H
% n1 @2 ~: ?3 j7 l
) W- s& \$ [0 R2 d //将一行的4个按键值移入缓冲区
. s, S- @0 O8 Q& B# |9 E2 |5 s$ ^: K keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
f4 G' n6 U, g9 U) B keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;0 x8 w7 ? C' H7 s! t6 s9 f; F& C
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
; A2 ? d3 @+ S9 B/ F keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
# ]) B* r) P4 _5 ~, R1 S8 n; L //消抖后更新按键状态0 b) Y7 w* }/ @" [
for (i=0; i<4; i++) //每行4个按键,所以循环4次2 D: }+ N- a% A( }* [3 r! ^ [
{
0 P/ U) J; z1 U) K& r" f K if ((keybuf[keyout] & 0x0F) == 0x00)2 s4 U5 D5 P. ~7 Z5 w; u9 b
{ //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下 e' E) P; X, r, v* ?8 B6 W, ~
KeySta[keyout] = 0;
, I% O, x& q5 Z4 G* ~9 d) |- r }- F: y/ B0 z3 z
else if ((keybuf[keyout] & 0x0F) == 0x0F)4 ?: R) F, U9 d3 p: e% F
{ //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
+ K1 ?5 W5 O2 R1 s9 W4 ^1 t KeySta[keyout] = 1;
9 \6 P" y2 J% M7 W: w }
, F: k0 k u/ } }9 H0 k' B7 d5 _* h. Y
//执行下一次的扫描输出* B2 }- \" \' I
keyout++; //输出索引递增 f9 `3 Q3 ?8 ?8 ^. \" v: Z6 y
keyout = keyout & 0x03; //索引值加到4即归零
% `& Y; N& p- x. g* w switch (keyout) //根据索引,释放当前输出引脚,拉低下次的输出引脚
Z' c6 W7 [# d2 W$ L {- h2 o. K) w/ `! A; q) f3 r9 `
case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
/ |3 F4 [5 u! D5 j8 o7 ` case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;1 S3 V6 N7 e& I
case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
, i8 y2 M8 `) P; s ^3 q6 q case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
" o+ N- l: Q( X* M default: break;4 u) M8 U) T" U/ L- R7 u
}
9 v, K) B7 ]+ y* e1 Z' u; p# B5 o8 F}! Q# @6 o& j" @
/* 数码管动态扫描刷新函数,需在定时中断中调用 */
5 s* B# p* n9 ^) @/ s: W& evoid LedScan()
4 U W( g- ~5 G6 ]{( j' m! k: d3 C5 I
static unsigned char i = 0; //动态扫描的索引
, |5 F2 H& u7 Y' }! _4 J
% Q$ j5 t) C r) @ s {0 z! F/ d" |
P0 = 0xFF; //显示消隐
6 X% H% v/ K3 e+ z& J switch (i)
$ \4 a8 [! J& [" z3 ]% Z X {# D( I7 c# e. t o
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[0]; break;, L9 F4 d: l2 f4 ~
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[1]; break;( i/ O/ u# ?6 L/ i1 x6 s/ [
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[2]; break;
) I7 M" M/ f3 r% F case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[3]; break;
! O( t6 e& n6 I* w4 j! m3 n# Y case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[4]; break;3 W9 F! f4 Q2 h2 \9 E# C- {* W
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[5]; break;3 I) B* l4 Q3 [/ {* ?+ C3 W
default: break;
2 O# R! Q4 s. ]2 d2 G# m }5 P# ` u/ ?- b P& J" r
}
: n5 B* l% \7 l* l- W# e; F5 S9 s1 _5 ]. ~3 x, {
6 |6 l- t) b; N+ Y! a2 Y
/* T0中断服务函数,用于数码管显示扫描与按键扫描 */
: [2 J9 N# v) [# k# q6 xvoid InterruptTimer0() interrupt 1
/ c) p( L6 n2 u$ \$ W{6 K; m$ g' J% y1 ~
TH0 = 0xFC;* o5 C# k3 ]7 b- f- }
TL0 = 0x67;
! P' A D+ {% I4 J LedScan();
+ g( P4 x1 `( F KeyScan();
! H% N0 H4 Q" p: S4 C- X3 ]1 ^}# F; O" i7 ^6 R0 J
& B- a3 C S- e! E, b6 w
7 q8 L/ W; m! d, ^. B |
|