找回密码
 注册
关于网站域名变更的通知
查看: 480|回复: 1
打印 上一主题 下一主题

基于1602液晶的简易计算器

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-1-22 06:30 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
基于1602液晶的简易计算器, K/ X7 r  C' R! c* P- @

5 R* f; {# n- t; W) b
! g+ f/ X) e% f- l4 I5 L3 j
#include <reg52.h>
3 m) x+ K) B. i
  l( j% r9 \; ]  N1 y& n4 bunsigned char step = 0;  //操作步骤
. B( X; X# ]$ Hunsigned char oprt = 0;  //运算类型0 I1 H2 ]* }6 s" Y: ?0 ]
signed long num1 = 0;    //操作数16 U7 V$ l; P+ N+ H
signed long num2 = 0;    //操作数20 t. K  W; v9 m( f
signed long result = 0;  //运算结果
. b; p$ @% P$ g$ m+ @5 p; Wunsigned char T0RH = 0;  //T0重载值的高字节
! G# f4 u! f  `8 h* d% Z6 B7 Xunsigned char T0RL = 0;  //T0重载值的低字节3 H; q; p7 {5 R$ t2 \; H
# H! y9 Q& o6 E' w# T
void ConfigTimer0(unsigned int ms);
1 P8 \9 g9 L! {0 b* Cextern void KeyScan();, w% c9 z, e, s" L9 q
extern void KeyDriver();5 R0 g3 ^$ F" m7 E6 y- `) V
extern void InitLcd1602();
' C1 t/ }! C+ b5 T) Fextern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);' D3 i6 P) @1 v- Y
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
5 `9 b' ]3 B: i% K7 hextern void LcdFullClear();
* m. ~9 v7 O1 l3 U3 L5 ]" p  o
1 a5 N" y3 f$ X) w5 s% d% Kvoid main()
# w$ t: q! |. l4 G( r{
: w3 I/ e/ E& O+ b0 ~, H. Y+ @    EA = 1;           //开总中断
$ C* F  u7 P- j+ W6 k2 b% W9 s, `; W    ConfigTimer0(1);  //配置T0定时1ms' m& n$ t) k* J2 `
        InitLcd1602();    //初始化液晶
% |2 S! ]% {- M& j/ X+ n6 v    LcdShowStr(15, 1, "0");  //初始显示一个数字0: B/ j9 R6 v7 @) u' K! h0 `' p/ C

6 N7 g7 Q# V* B$ _% F# `. P+ n    while (1)+ A9 [, H- k" t. t2 J4 b
    {+ f! P/ }. o& j; l  D
        KeyDriver();  //调用按键驱动! H9 O" B( _: r( R
    }' V" P+ ~) i& d
}- o0 V& @; ]! R' {$ U
/* 长整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */
/ d8 t2 b* `! N2 Yunsigned char LongToString(unsigned char *str, signed long dat)
5 J; a, p% Z7 i. g{" Q; Y& r8 U1 E  f, ?; y
    signed char i = 0;
' v9 j! O( V$ o3 Q( t1 b    unsigned char len = 0;
; [6 i! s- F! W3 E- P9 Q0 p    unsigned char buf[12];  C; D5 b/ i2 V" @1 d$ P# e

! ~/ f* z1 `4 Z    if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号
& v, f( A: a, [3 i' q' _    {
: c& P" u/ b, c  q        dat = -dat;
/ c) j, D! s5 K+ B        *str++ = '-';
+ E& L6 V. X7 A& f        len++;1 l: ~9 O' [# U( P
    }
9 T' B( A! R. X( |) Q& w' b' S. ]    do {          //先转换为低位在前的十进制数组. N1 K9 s; X" `1 v
        buf[i++] = dat % 10;
* U9 ~8 j9 o1 j9 R        dat /= 10;
0 O/ Q) R) s9 U' w, T% b    } while (dat > 0);
* H' b' a3 F8 [    len += i;     //i最后的值就是有效字符的个数
* F" Y- h6 `1 w2 A* \    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上$ n$ |( D* z" M2 `
    {
7 w& {5 x% c% ~' a4 C! y+ o9 d        *str++ = buf + '0';
" |" L% ^' E6 d" U0 _- @/ O+ Y    }; w1 c" B- [# {$ W" m
    *str = '\0';  //添加字符串结束符$ Q8 k/ D  n' h) v6 X, g
8 I3 U/ b3 \/ A
    return len;   //返回字符串长度+ u0 Q& m+ \" m% I7 h
}
5 C: K/ C' f0 j* X; `/* 显示运算符,显示位置y,运算符类型type */
" D: v7 v( R% q" n( U- B! x, mvoid ShowOprt(unsigned char y, unsigned char type)
4 T3 h+ g$ B! B" ?4 v' Q{
& }, S/ U; B* p3 ]- C% a) y    switch (type)) Z5 U+ ?2 u  ~8 Q6 I
    {
3 H# N: a. {- @( Q/ W        case 0: LcdShowStr(0, y, "+"); break;  //0代表+
( N/ y6 |* |1 r: E        case 1: LcdShowStr(0, y, "-"); break;  //1代表-
1 A  m8 m' M% @: I7 i        case 2: LcdShowStr(0, y, "*"); break;  //2代表*
8 S1 u' e3 p  u        case 3: LcdShowStr(0, y, "/"); break;  //3代表/
/ d9 C, |9 {: ], e7 J# k        default: break;
. P1 G8 B, I6 p9 I. r1 R' u6 |    }
0 e0 A; [: P& u: i/ R% d# r( P& r9 ^}1 u6 ]3 Q' b; a
/* 计算器复位,清零变量值,清除屏幕显示 */+ Z& H+ _" y" O" h3 U  V/ X) F
void Reset()
  P* o6 E% |9 n0 u{
. }6 C( V- j1 H  o. [6 f    num1 = 0;
# m( q/ g/ X/ N. [: g  t$ l    num2 = 0;6 S  V' F+ X3 m( N& Q, |
    step = 0;
& j/ U# \7 X" S5 n9 h    LcdFullClear();$ z: L+ E+ A: r
}
1 O  h( ^- E: z3 D0 v/* 数字键动作函数,n-按键输入的数值 */
; o! {) I9 ?6 L) Hvoid NumKeyAction(unsigned char n)
; {  B( a# E' E% H7 _* @0 Q: i{5 n4 T/ `; [( I( E8 x+ m/ _
    unsigned char len;
  q6 I7 ]0 ~* B; k' A    unsigned char str[12];
; j. A7 v2 B& p4 ?$ c- x) c2 p: I
1 l+ ~" Q. F8 @% P6 e  m- e& m    if (step > 1)  //如计算已完成,则重新开始新的计算' b7 p" D* ^! Y- c) d" P4 _0 k
    {
" S( N& e9 B% y8 h% F) Y        Reset();0 e$ n( k8 |- C0 R) I
    }7 n3 n7 b0 g  G( d
    if (step == 0)  //输入第一操作数
0 @, e7 s' ]2 F0 n4 t    {; c9 i" L1 T' i( M
        num1 = num1*10 + n;             //输入数值累加到原操作数上
1 I0 C( ?. `* c& \* I  J, W        len = LongToString(str, num1);  //新数值转换为字符串* Y6 W# T$ k- ]$ c, Y* l3 M. `
        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上
6 N- D% @0 N4 P' }* h, S( |    }# ~3 \8 U- W+ ~/ k) R$ b6 w
    else            //输入第二操作数  H: Q6 `, l+ M  M# K4 B3 q$ T4 J2 K
    {( J5 o( b3 l; _4 f6 Z$ q" K
        num2 = num2*10 + n;             //输入数值累加到原操作数上: r# T5 I1 |2 u- `7 E3 \
        len = LongToString(str, num2);  //新数值转换为字符串
# J4 s3 q$ w, b$ c& K1 N' T        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上; F3 Q/ a/ d! A: T7 N: J
    }
8 J/ _8 R. _: B1 c; o7 |) _  p* `1 I/ H}
# }# r6 }+ A( ?6 H8 m/* 运算符按键动作函数,运算符类型type */
. O/ L/ M! J1 ]2 n5 J8 Lvoid OprtKeyAction(unsigned char type)5 O$ Z% V: Q: I! M0 i) R1 ~
{
* T6 B7 e: ^! U# \! v    unsigned char len;0 j. i; j) d* h
    unsigned char str[12];6 }- g, V) j, r- e2 s+ X; \0 A

6 x2 l, M9 z- l; ^3 r1 y6 g/ `    if (step == 0)  //第二操作数尚未输入时响应,即不支持连续操作  l( x4 s2 C% h5 {' w& k+ `" D
    {% i7 Q( `! B1 G) L. O
        len = LongToString(str, num1); //第一操作数转换为字符串
7 ?: V9 @; s' j- }$ o6 E2 I        LcdAreaClear(0, 0, 16-len);    //清除第一行左边的字符位8 ^% w/ b) \- y  V6 x. \- C0 U
        LcdShowStr(16-len, 0, str);    //字符串靠右显示在第一行3 n9 f! @& u7 W' N) A- Z0 G
        ShowOprt(1, type);             //在第二行显示操作符7 B% E" T6 A, S/ g: A
        LcdAreaClear(1, 1, 14);        //清除第二行中间的字符位3 i2 g: z! }. H% N2 D; L
        LcdShowStr(15, 1, "0");        //在第二行最右端显示0: I7 Z: L" E# b) Z: f# b
        oprt = type;                   //记录操作类型9 o1 e" d  o5 G; N0 ~
        step = 1;
( H+ v% ]$ o1 j" W$ V5 Q6 s    }
' P9 R7 w) r! L0 M# U}
* R, f2 j: W+ Q; v9 }4 H/* 计算结果函数 */
: ]- z; c/ ?7 K' T; evoid GetResult()2 T8 k- I4 W" [
{' {" v+ `0 u/ x6 X
    unsigned char len;
( A: u' _' V% V. G6 D0 y    unsigned char str[12];2 b, z; k7 G4 F* ^7 D5 i& X
3 N% @( X! H0 I. e- v8 f% A1 C- ?
    if (step == 1) //第二操作数已输入时才执行计算+ D' l: h9 l8 Z  @: B+ o% D
    {- j4 E5 o3 d0 Y+ ^
        step = 2;0 x* y: S) ^: o$ R) F& s
        switch (oprt)  //根据运算符类型计算结果,未考虑溢出问题; x* L; _/ _/ c' n: q) K" X( e) g
        {
& x9 g0 A  E- f% h% ^) v" h            case 0: result = num1 + num2; break;
8 v) D6 q( l  q5 ?/ F            case 1: result = num1 - num2; break;
" M, l0 ?; z. S  V( C. ]% X            case 2: result = num1 * num2; break;
1 S8 t- j# z- \" t9 ?! ?; {, v" h3 G            case 3: result = num1 / num2; break;+ k1 Q8 k4 w' P
            default: break;
/ O. C/ i/ ]- l" H9 y+ \) N) g- O        }5 k: K( I% {6 ]" i8 D
        len = LongToString(str, num2);  //原第二操作数和运算符显示到第一行
5 H5 C( b+ {2 N7 b8 q5 [5 Q* M        ShowOprt(0, oprt);, O7 d% J6 N. E! t' `9 U* n: _
        LcdAreaClear(1, 0, 16-1-len);
. W) j- m. a& {5 k' t        LcdShowStr(16-len, 0, str);: t1 q5 O1 h7 i& Z3 e% K: z
        len = LongToString(str, result);  //计算结果和等号显示在第二行! r7 u' O1 Q2 W; F3 N0 L5 g  E; s
        LcdShowStr(0, 1, "=");" d7 Q3 D/ E+ y3 O6 x# O- x
        LcdAreaClear(1, 1, 16-1-len);- C6 o8 B( W. ?+ ], n  p# ]0 t
        LcdShowStr(16-len, 1, str);% N* n" e- h" X+ f
    }
! q( {  W' j/ {  c" \/ i}
, y( X7 w$ h8 _/* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */* g3 `# t0 Q, I- I/ R/ z
void KeyAction(unsigned char keycode)
; p$ s( P" z5 b2 j9 l{
7 P4 Z: W2 o; X% V) [) ~6 |    if  ((keycode>='0') && (keycode<='9'))  //输入字符$ ^  Q" G+ r& f
    {
- `5 N& W8 }' N) C2 x        NumKeyAction(keycode - '0');
8 h  i5 S4 Z3 f    }
, H1 W" Z2 f- j! @# N    else if (keycode == 0x26)  //向上键,+
' S6 G  p, z3 m+ j    {
4 U" x% i' }$ f' T! e  Q) M        OprtKeyAction(0);
7 ]% l! p) T+ Y    }
4 B# k* B: q+ P+ G; P! e  l    else if (keycode == 0x28)  //向下键,-
( D: B9 w, x. @% H- ?    {
* Y( f0 \3 h, F% T* f  y. S        OprtKeyAction(1);( u. V! a3 o6 G7 y5 p) j
    }
; Y2 g3 d( e& w; h# Y    else if (keycode == 0x25)  //向左键,*. B3 {+ ^- }  V& W/ |4 k
    {9 a$ Y6 _( P$ i) h
        OprtKeyAction(2);1 N- j5 [0 y- E
    }
& @  t3 }" j% }. F, p* y' D    else if (keycode == 0x27)  //向右键,÷; W6 J1 r* k$ o& `0 }% z6 i
    {% g- S; M3 F/ {' |
        OprtKeyAction(3);
: @/ F5 L8 S5 _1 W# |    }; l8 F$ p/ W: H. k3 ~) }% w
    else if (keycode == 0x0D)  //回车键,计算结果
- [; i; ~" P- a4 f    {
, Q) J+ [/ z8 H        GetResult();
4 j& S) a* C0 `: v# R# e    }
% x- I6 C6 V+ w* J    else if (keycode == 0x1B)  //Esc键,清除
, Z# h& M% w( j8 }0 ^  d! N/ K    {
5 }/ x, [1 ]9 p+ S" T8 i        Reset();
/ e$ l8 J3 _% M9 c2 X        LcdShowStr(15, 1, "0");
) \) R7 n$ W" P( A. D    }
0 e2 o9 r* \6 N- h- M}, \9 Z: l6 e' C, s8 c
/* 配置并启动T0,ms-T0定时时间 *// C5 \: @  B# Y9 q* t
void ConfigTimer0(unsigned int ms)0 D7 ~$ ]+ h+ Y* V' U2 I+ T! k
{
2 T  [. }5 l. a    unsigned long tmp;  //临时变量
7 W0 H, q/ h9 |9 J5 [  F$ Y0 [! H. {& N
    tmp = 11059200 / 12;      //定时器计数频率
4 t6 v# F2 c; g# {& N/ j    tmp = (tmp * ms) / 1000;  //计算所需的计数值9 {# {3 i$ f0 q) W
    tmp = 65536 - tmp;        //计算定时器重载值
% t/ v' X! X) Z+ A( V3 O2 r2 T    tmp = tmp + 28;           //补偿中断响应延时造成的误差
# n& g) H$ e* n9 r    T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节, o. K: B  A/ `% P+ z
    T0RL = (unsigned char)tmp;$ S; K- N" M* c5 F
    TMOD &= 0xF0;   //清零T0的控制位
) p5 D" R% `3 N% g9 s    TMOD |= 0x01;   //配置T0为模式1
" I9 C. P$ I# K' T: y7 j    TH0 = T0RH;     //加载T0重载值4 S/ }8 @$ y3 \" y( r
    TL0 = T0RL;
% x' h2 J$ y8 v3 m; K4 R    ET0 = 1;        //使能T0中断
) Y: v9 u, C( A+ Q7 H    TR0 = 1;        //启动T0& ~" r3 }% H# N0 J0 ]
}$ O' L0 }9 v3 v5 p# O* c
/* T0中断服务函数,执行按键扫描 */
5 x7 N  l8 Q7 ]2 c" Bvoid InterruptTimer0() interrupt 1
5 t0 l) w6 [/ }{7 R5 t& G4 f: t* p
    TH0 = T0RH;  //重新加载重载值" R" ^; Q" q' L
    TL0 = T0RL;
& J$ U* Y1 s3 l5 ~( T    KeyScan();   //按键扫描" V1 d( h' B2 [$ ~+ k* A5 I
}

2 M' D0 S& \+ U* F0 z: V' h( u7 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-29 05:38 , Processed in 0.078125 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表