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

基于1602液晶的简易计算器

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
基于1602液晶的简易计算器
" L/ G* w$ h0 i6 `: z) ?
5 z" e/ n. _; W) k' `, ]3 {4 P

9 `& u5 G. Y) @#include <reg52.h>
# W5 P+ _1 h* k. w- j6 I6 ~, H( r5 @7 o* e; _
unsigned char step = 0;  //操作步骤3 ?9 s# G; b# R$ Z+ }# y1 R
unsigned char oprt = 0;  //运算类型
& @" k3 x3 [! s( L' xsigned long num1 = 0;    //操作数15 j6 E( ?' _2 \7 g9 k7 H7 A
signed long num2 = 0;    //操作数2
  r1 F) x. K" zsigned long result = 0;  //运算结果
: C7 s' M6 ]6 [+ _- F6 b  xunsigned char T0RH = 0;  //T0重载值的高字节
, f  t  ]( ~# i2 m" bunsigned char T0RL = 0;  //T0重载值的低字节/ R/ U9 E1 H  y, E' J2 q" ~
0 G8 S) j' F2 _8 T; h
void ConfigTimer0(unsigned int ms);9 A9 I+ Z# Y" Q6 X* b1 X7 }2 O( y
extern void KeyScan();5 V% x+ B7 W- @- b2 t# ]
extern void KeyDriver();
# f; Z, c- k2 K* @, Gextern void InitLcd1602();
# y4 i1 B8 v4 q5 `extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);* f) I- Q3 Q: k4 T
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);3 p6 A# k8 @# _
extern void LcdFullClear();
$ g8 W0 j# }; L8 X4 S' F2 c
6 d5 T' u# R4 I; C; g9 V3 n3 \: Nvoid main()8 j9 V* H+ ~, F; M/ n
{6 l3 _- M4 M/ N- I
    EA = 1;           //开总中断
8 c4 Z7 L% X. g; v) O    ConfigTimer0(1);  //配置T0定时1ms  D' A* J7 S. D6 P+ _
        InitLcd1602();    //初始化液晶
3 q( ^5 E! F5 m# S  i  C1 N* b3 A    LcdShowStr(15, 1, "0");  //初始显示一个数字05 o) ?  }8 K. E
% l' x+ y3 J4 G) x( O4 P8 l
    while (1)
4 d* U. k, q8 P4 E    {1 ~/ X' P: U2 o# O3 U6 `
        KeyDriver();  //调用按键驱动& }, W% g2 w4 S3 z9 `- i
    }; X$ j/ m: U6 Y# e) H
}
6 \) f$ b3 n3 @7 s9 p% Y/* 长整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */
! x7 e0 v; R; l( e4 k% t- d$ ounsigned char LongToString(unsigned char *str, signed long dat)" W3 k- g; L+ P& X/ m  K# b
{( U. a& L/ L* j' M5 }0 u$ W1 y& o
    signed char i = 0;
$ f! X8 r: C  G; K9 r    unsigned char len = 0;
1 p7 s$ U# B. [# @8 v  e+ r    unsigned char buf[12];
+ Y; o$ c9 M2 ^* t* t( m: _4 ?. D- o
    if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号
/ T1 I- \" T) q( \! I2 x7 w+ O    {6 |$ Y+ o  i& R* ?2 `; l/ B
        dat = -dat;# T# K* s, \- X1 g$ E) j
        *str++ = '-';
' G0 p4 F' K0 K( [        len++;
3 y  z: z9 c. u: G    }
! _5 p% ], z7 N$ T7 k8 V3 W6 U    do {          //先转换为低位在前的十进制数组& U% S/ U# c/ F8 ^
        buf[i++] = dat % 10;) g' n& m$ Y0 w* d$ q+ w" w
        dat /= 10;2 E/ u0 F5 P$ e( [: F7 D
    } while (dat > 0);3 m& {2 p/ g& s
    len += i;     //i最后的值就是有效字符的个数
" V, X* m. D& [! K$ G5 {% y! e) X+ x+ K    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上; W4 g7 w* l& c4 Q5 m3 o
    {
; P( e- F2 k; F* m        *str++ = buf + '0';
( V, v8 l! i8 S    }! Z( Y. A7 @  w0 Y8 ]- H, T
    *str = '\0';  //添加字符串结束符1 _1 |+ n! N8 c

8 X8 V% M# n" M! M) T    return len;   //返回字符串长度$ k- Q# v. U" \# ]% ~& e2 N
}
% M* ?( g9 k. N6 v- i4 e/* 显示运算符,显示位置y,运算符类型type */
8 Z7 X: a! ~3 l: [5 Kvoid ShowOprt(unsigned char y, unsigned char type)
$ k1 d* H9 G  I{3 O. k2 e' _5 y: g% N4 d
    switch (type)" ~! K* U( ?$ l! u
    {4 e% \8 A0 M. y3 I2 b
        case 0: LcdShowStr(0, y, "+"); break;  //0代表+: U" g- u, k2 S: L" @, u' M& v
        case 1: LcdShowStr(0, y, "-"); break;  //1代表-1 ^, c- D' ]+ L: b3 F2 ]5 M
        case 2: LcdShowStr(0, y, "*"); break;  //2代表*
# V  V' _5 s" P: Q3 c% m& C8 E        case 3: LcdShowStr(0, y, "/"); break;  //3代表/4 k+ G2 R0 ~7 H6 {1 f4 l
        default: break;
' U: Z) S) e7 y2 N; C    }
" Z. h/ g9 w( A& f6 L}/ J7 i+ B( ~  O4 Z& q
/* 计算器复位,清零变量值,清除屏幕显示 */
& G0 O/ A9 y# H! w# W  s% wvoid Reset()5 [2 B4 a0 H4 O  x4 P4 Q
{
9 l9 f8 o6 a( {    num1 = 0;
  G3 D& p! \. ^5 y3 d0 n3 F    num2 = 0;3 e+ \/ u/ Z- j& \* v% w3 s( q0 ~
    step = 0;
- z! y9 Y. G" H4 \+ O    LcdFullClear();  E, \* B0 v2 N
}
$ f3 w( G! z% d$ U- P- {) F( a/* 数字键动作函数,n-按键输入的数值 */+ _- O8 U7 `# J0 @8 B
void NumKeyAction(unsigned char n)
3 k$ i3 k5 C0 [( H5 g2 g) B- Z' I{
- n' a7 {$ Q1 d& K    unsigned char len;. B4 |; |6 i* K! L" d0 O
    unsigned char str[12];" s3 y& z0 V+ Z$ F1 p% C* N- k
, n. H! M, F0 K) w8 r2 W9 v
    if (step > 1)  //如计算已完成,则重新开始新的计算/ w8 @" X( r% k4 g* E4 t* E  o
    {
9 j6 A$ v: x; W" I% ~/ j        Reset();- W* D6 Q' ]" F" M1 @
    }
& R& N! }# |6 P1 F    if (step == 0)  //输入第一操作数
; m2 Z1 P3 `6 }    {) R$ q/ P$ |0 t; \3 T- R
        num1 = num1*10 + n;             //输入数值累加到原操作数上
5 \/ }. T& _+ _5 E        len = LongToString(str, num1);  //新数值转换为字符串1 x6 `1 y# U+ A# D  J$ u  T
        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上2 z# l  J* a8 v+ l' T
    }
5 u+ v* Q6 j! b2 G1 L: d    else            //输入第二操作数
6 N4 r, v6 x: M% W# E5 ^    {
! }* R# G" q$ }5 R        num2 = num2*10 + n;             //输入数值累加到原操作数上! j! F' i+ D0 e5 @
        len = LongToString(str, num2);  //新数值转换为字符串4 Y4 b( @$ k5 q# ~
        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上& p- h! B0 s6 k& ~
    }5 C+ d' F, d" c0 ?2 N3 v
}
# x  K  H# Y+ O/* 运算符按键动作函数,运算符类型type */
3 [9 r5 y- l9 W3 p1 W8 N/ }8 X) F) Nvoid OprtKeyAction(unsigned char type)
* O  T9 L. `* J8 E' x{( E4 M  D3 k& }  X
    unsigned char len;( `6 d+ n7 j- y: f2 T( M
    unsigned char str[12];3 w  u' }$ m' Z0 D) Y' u
/ K" Q$ U! X. P, d
    if (step == 0)  //第二操作数尚未输入时响应,即不支持连续操作
! ]- M  e& ?( }) }" U6 |    {  d* t1 D4 h2 F8 P7 R
        len = LongToString(str, num1); //第一操作数转换为字符串
' X5 s# m. m2 Y8 ^6 R        LcdAreaClear(0, 0, 16-len);    //清除第一行左边的字符位
1 c1 T- v; |% q+ ]  }9 s7 t        LcdShowStr(16-len, 0, str);    //字符串靠右显示在第一行
$ P7 b+ g1 o/ Y8 U' b$ i        ShowOprt(1, type);             //在第二行显示操作符3 R+ X5 J) q0 }8 h
        LcdAreaClear(1, 1, 14);        //清除第二行中间的字符位
' \; H0 S' w  ^2 z: c* ]        LcdShowStr(15, 1, "0");        //在第二行最右端显示0$ c& Z0 ?6 A) D, |& T
        oprt = type;                   //记录操作类型/ R1 E* V3 P" o4 M0 Z, }5 A
        step = 1;; |# J0 d- W4 {! L6 k6 B
    }$ _. v5 `. o) Q9 ]% D3 Z
}1 ?6 g% |3 m0 [, p% E% m
/* 计算结果函数 */; D5 l% C5 S% V5 b, c5 A& V
void GetResult(), r: c, h& ?! W) c, c
{
7 w$ ~8 ?9 \  S. E    unsigned char len;! K; X( o) _. y: V  ^  X' X/ A
    unsigned char str[12];
* R- C7 Z, q, B4 t  h+ f
2 m- R& E% \9 b+ S    if (step == 1) //第二操作数已输入时才执行计算# \) \- p' ^" D8 n1 }4 G0 r
    {7 z7 V1 N' _# o8 q4 `
        step = 2;
3 a" |# ^! S* [& N" w* H+ R        switch (oprt)  //根据运算符类型计算结果,未考虑溢出问题
8 y$ a3 z2 u8 B+ \        {) Z3 [( _0 @0 N0 c5 C$ x
            case 0: result = num1 + num2; break;4 \* z& N. T: {" h! R1 F
            case 1: result = num1 - num2; break;
7 x5 f  U* g- J" }. A! O9 T            case 2: result = num1 * num2; break;/ j; F  r& w+ k/ p) k6 |
            case 3: result = num1 / num2; break;
# a8 j" i8 i0 x4 I7 W            default: break;
/ }( m4 W7 x  n9 B        }& o3 B; c( W( T  {+ a% [* v& T- i
        len = LongToString(str, num2);  //原第二操作数和运算符显示到第一行
4 \: [7 W. L  ~3 _& T        ShowOprt(0, oprt);
0 D) b2 }  O: p7 q; c4 W        LcdAreaClear(1, 0, 16-1-len);
' E% [8 J/ w( q( S' _        LcdShowStr(16-len, 0, str);
' V; J, O# z, e4 `" t        len = LongToString(str, result);  //计算结果和等号显示在第二行$ p1 {. t4 E) M
        LcdShowStr(0, 1, "=");) e; {: i! @! b; o3 |, y9 ]
        LcdAreaClear(1, 1, 16-1-len);
# U1 @! N1 g6 A+ ~$ f, W        LcdShowStr(16-len, 1, str);
+ ^- _9 k1 r! i7 ]# n/ w    }
1 _  \% u/ N/ w}% Q: \6 f4 d8 C4 l' W1 f+ D
/* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */
5 y2 u8 k+ p* Fvoid KeyAction(unsigned char keycode)
; r# a, b' E3 }6 C- h{$ m( E& n4 |  A
    if  ((keycode>='0') && (keycode<='9'))  //输入字符8 M% @' E4 B: r3 N  [* d1 ~3 Z
    {' t2 P$ l% k, g7 B
        NumKeyAction(keycode - '0');
4 ]+ w/ d# H3 O! e! h, T$ N, s" y    }% t7 D5 T# s' h: o* [
    else if (keycode == 0x26)  //向上键,+; c6 ]. Z1 d3 v+ L, A
    {7 T' [8 e* I* v' {* W& {) ?& _
        OprtKeyAction(0);
8 M) y6 |$ E: A  u0 Y; {3 C    }
1 u2 _1 p' d8 Q    else if (keycode == 0x28)  //向下键,-
( e, c7 H7 @" Z& ]    {- w/ l% E9 _" R3 V$ [  O4 e
        OprtKeyAction(1);
( |) A$ @6 B9 S    }* l) U. V" r5 ^! G: G0 k3 X
    else if (keycode == 0x25)  //向左键,*( Y( \0 f- ~# ^" E, k
    {) }; b3 M" b$ W6 v1 U
        OprtKeyAction(2);
* X. K: g$ t+ F' v2 N: n    }
' a" j! p0 I4 R; G; V! w1 [5 J& h    else if (keycode == 0x27)  //向右键,÷- A+ v# E2 f6 ^+ b( \5 P
    {5 z1 ^5 y& ~$ ~# u1 i: W
        OprtKeyAction(3);8 f2 g! P- O# V1 U( A
    }9 g2 ?  Q* Y7 h5 k! e
    else if (keycode == 0x0D)  //回车键,计算结果$ w, `: |  p) g! c0 p
    {
5 Q; O1 t0 Q" |        GetResult();
: T) v, l7 C6 J9 J, j    }- _* W; H$ J! ^+ t
    else if (keycode == 0x1B)  //Esc键,清除* Z- ]8 [. I% z
    {
* j, u  [; Z$ }' o        Reset();
. [- |- q+ [5 F2 c" D        LcdShowStr(15, 1, "0");# \2 D  G$ R) o2 j0 c# b5 f
    }
7 @) \& _; t. d5 X8 J; Y/ @) ^}
, l7 Q/ e7 m2 N/* 配置并启动T0,ms-T0定时时间 */; q  |' l6 d( o* r; r- Z# Z; V
void ConfigTimer0(unsigned int ms)
  ^; j6 C& d% m) s{
$ F/ C- ^* }# E    unsigned long tmp;  //临时变量
5 V0 g% m) A) [3 ^2 R8 z- D$ ]
- W; \7 t! F% y* ^6 l8 C% j( a    tmp = 11059200 / 12;      //定时器计数频率
* m; H6 _0 E: g6 B0 e    tmp = (tmp * ms) / 1000;  //计算所需的计数值% ^, A3 `9 v! y; E' n/ ?+ ~
    tmp = 65536 - tmp;        //计算定时器重载值
2 h7 E" o/ f. b' W+ z    tmp = tmp + 28;           //补偿中断响应延时造成的误差/ n9 Z( a: A. b: _+ ]& A
    T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节
/ E4 r1 L7 F6 t3 B# A( \    T0RL = (unsigned char)tmp;
, C  A' {. R& E4 \( x- q8 T( X    TMOD &= 0xF0;   //清零T0的控制位4 E! v5 q" H+ n- c
    TMOD |= 0x01;   //配置T0为模式1
1 S; y: p2 R$ G' C& p    TH0 = T0RH;     //加载T0重载值
- ^+ X9 c0 _- J' A$ P% O8 T    TL0 = T0RL;
! d* C" W1 m( r% W# B6 m: l    ET0 = 1;        //使能T0中断" N) `9 S& `/ h# z& e* j/ V1 U
    TR0 = 1;        //启动T0& K; H$ v$ F1 ^! Z) g! r7 J. T3 Y
}
0 H* `+ M2 c9 }) X+ |$ N4 m$ q/* T0中断服务函数,执行按键扫描 */
. J7 e6 ?' B8 K" `5 Y9 l: Yvoid InterruptTimer0() interrupt 1, F- ^9 |& `0 @! V$ _5 v
{/ p" S& e2 _7 V
    TH0 = T0RH;  //重新加载重载值
4 S: b" {* U7 b7 ~    TL0 = T0RL;
1 @8 r- L+ o2 h' l  q6 y- O8 K    KeyScan();   //按键扫描
. A0 v9 @# j- {$ a' ?5 m0 D9 d}

. j8 ~. p# z3 [6 R* V5 d. n
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

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

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

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

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