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

基于1602液晶的简易计算器

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
基于1602液晶的简易计算器- @) e$ R/ c* Q
% [" k. v3 E4 ^5 V

& ]$ B5 ]: N/ N* v: M$ c$ b#include <reg52.h>
2 r6 K, H* g0 ]% P4 A1 K) N" T* B
7 u: s2 q3 s. e+ @- V5 \unsigned char step = 0;  //操作步骤  E" U$ v* y) A9 ~, T' n) }! L
unsigned char oprt = 0;  //运算类型! D+ ~/ E4 T9 y' I
signed long num1 = 0;    //操作数1
) ^7 k4 E$ L. Vsigned long num2 = 0;    //操作数2  G* L8 {( {8 R* ?: ~2 j
signed long result = 0;  //运算结果$ A' U' D7 I' W2 R2 x% T5 D
unsigned char T0RH = 0;  //T0重载值的高字节8 R- M1 d: I- S% O5 n8 t: m& ~
unsigned char T0RL = 0;  //T0重载值的低字节; i0 X5 \" c5 Z+ y% ^- W. I3 H/ o. S

6 G1 j# E$ y$ Jvoid ConfigTimer0(unsigned int ms);
( n3 H& Z1 U. z0 oextern void KeyScan();  R! b1 z- A; e  O7 z4 D
extern void KeyDriver();* I2 r$ W6 i. Z- c/ k  @
extern void InitLcd1602();
+ i) o2 m: K* R/ Q+ |extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);/ o5 Q% `0 _8 \
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
2 h& g) O/ W3 M! Pextern void LcdFullClear();. @, J/ c9 q# f: q

  h7 f3 `8 s- g# W1 s$ x% {void main()
; a6 d  I5 [) m7 u: t' f{
5 [' Y8 D: |, d* B    EA = 1;           //开总中断& Y3 R. y# \# F- M; c- H
    ConfigTimer0(1);  //配置T0定时1ms2 K9 X" K8 F6 ?+ Y
        InitLcd1602();    //初始化液晶  M+ Y1 X: q" [/ F( {; ^" \; `
    LcdShowStr(15, 1, "0");  //初始显示一个数字0
& c- q6 @6 h# {& k) F0 z0 H: X1 J8 k3 s! S" X2 G
    while (1)3 E, \7 h7 h% C# Z
    {5 Y5 K3 m: g1 [/ ]4 w& K
        KeyDriver();  //调用按键驱动
; M( X$ u# G' \  o    }, C* G6 Q0 H* B* w$ ?
}+ o$ J  k: `  k, e
/* 长整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */( |# h' }6 M) o0 o  V3 o
unsigned char LongToString(unsigned char *str, signed long dat)' F) F$ }- G' E9 t. Y8 w0 K9 W* I/ \
{, u5 W  o- O! c. k( r1 Q
    signed char i = 0;
5 @3 A( }; `) F7 U8 `! @/ ?    unsigned char len = 0;1 z8 X; j! q5 k
    unsigned char buf[12];: N! \5 V2 T" M, q+ [

/ C. e) I8 ^3 H* U) U    if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号, J# F3 J8 }; z# f& E
    {
& }- X2 [) x2 G, y3 {( Z& X        dat = -dat;
+ d% D4 C1 r+ F1 S& h( X        *str++ = '-';0 \1 s/ N6 m; X4 w
        len++;
5 a9 P- P$ ^4 d7 j. D    }
  l2 t, O8 t( f; Z7 e. x+ u    do {          //先转换为低位在前的十进制数组
, q5 f; V+ n" F' z5 X7 M; J        buf[i++] = dat % 10;
$ I! j* y5 [$ B; G- |1 ~. G# e% x        dat /= 10;
( }; F# `& u  s7 V% j7 W    } while (dat > 0);
$ ^( e$ P$ I# G! d    len += i;     //i最后的值就是有效字符的个数
" j: A) @! @5 k. w7 [0 o    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上
  t7 m. a  a* |/ `* I    {  i$ E0 i. ]" _/ \) e5 R
        *str++ = buf + '0';
' i& X9 n5 @  ~    }1 T( k4 d  Z3 N' Y, h0 N- C5 T( n
    *str = '\0';  //添加字符串结束符
( t  _; }8 a2 l% S* x* A2 \# y/ B/ h9 q
    return len;   //返回字符串长度$ r# r. B4 q( j# l/ S$ T
}' h) Y. D+ Z% Y2 F
/* 显示运算符,显示位置y,运算符类型type */
6 \" a5 w# Y  A! @( J$ I  |8 ^6 T* {void ShowOprt(unsigned char y, unsigned char type)
' _2 c+ R3 e1 G" m{: \" Q% M" v. ~* w% b2 y- V) }: v
    switch (type)' B1 q" k/ I* a
    {
$ ~3 _: y" ]6 s: z2 p, E        case 0: LcdShowStr(0, y, "+"); break;  //0代表+# P4 a6 d8 o/ W3 k" a
        case 1: LcdShowStr(0, y, "-"); break;  //1代表-; w8 \/ A7 l/ Q- y8 g
        case 2: LcdShowStr(0, y, "*"); break;  //2代表*
3 ?, I( ^" k% U+ @+ V5 O        case 3: LcdShowStr(0, y, "/"); break;  //3代表/
1 W" R! i  ]; Z0 P' z# P  F& o( P! I        default: break;/ b4 D/ Z* S% U: A& H4 O6 A
    }" }( I! _) S4 P+ @) B; R& @  I
}2 w' K7 ~9 J8 t: u) t
/* 计算器复位,清零变量值,清除屏幕显示 */
4 H. _! A/ Y6 J/ r  j2 v/ tvoid Reset()
4 [- W0 V' p! m& V0 T{! ^* H6 v( I+ P* L9 }: ^
    num1 = 0;
4 `# ]5 ?5 C. p9 M5 ]    num2 = 0;
$ F. O0 p6 p! e- d+ ?1 G  N* s: h    step = 0;
0 R0 x* ?5 \: X    LcdFullClear();0 |6 X  [3 i- s
}
# f# C0 z' f1 o, }/* 数字键动作函数,n-按键输入的数值 */
* j0 @" }$ w( C) s, R% dvoid NumKeyAction(unsigned char n)
3 O) V9 B# d6 e" `6 }{, B% g; M! {3 L4 z: `* A
    unsigned char len;
' @; {+ M! r" \5 O( v    unsigned char str[12];
  [/ |! P$ e1 X' i3 t* i1 ?, P( c/ K4 q! u6 K( j
    if (step > 1)  //如计算已完成,则重新开始新的计算/ V3 {7 [  S! w) O# f7 V
    {9 ?4 e$ N1 U. p
        Reset();
( ^0 c8 J1 A. ]9 I( \  M    }# ~; y. u! ]: v& G% b5 o: ~, N
    if (step == 0)  //输入第一操作数
. }, ]7 i- t9 s3 ?7 ^    {
: `% K2 M% O* t        num1 = num1*10 + n;             //输入数值累加到原操作数上
$ E% y9 S: A; K. S' U0 ]' F5 O        len = LongToString(str, num1);  //新数值转换为字符串
! C' B! j% j' q4 Q, O        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上- t8 j% ^5 W, ]' q) ~/ U) g6 U/ M+ }
    }. A. o% N7 i, u& y
    else            //输入第二操作数
8 M! a" D2 {$ D  p7 d  M$ y    {
, i* q" n8 a6 U, M$ m; n8 W        num2 = num2*10 + n;             //输入数值累加到原操作数上0 E0 }# p/ F; I
        len = LongToString(str, num2);  //新数值转换为字符串# t, N8 A  _! O
        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上
, J4 O7 A5 }+ S. \, V    }& M( b5 b* I* v( Z: ]8 F3 O
}9 v7 P; t1 q- D
/* 运算符按键动作函数,运算符类型type */
7 S  \" P8 f' E5 Lvoid OprtKeyAction(unsigned char type)) n+ q% T4 }( L
{- H# `. k. h+ n( R+ O
    unsigned char len;( r1 H- G: u, B* i1 Y
    unsigned char str[12];
7 u$ K% M7 G( S, t% z+ F7 a/ T, Q7 T9 J, [. i, c2 R* F) q" J, ^
    if (step == 0)  //第二操作数尚未输入时响应,即不支持连续操作! C" t5 F8 c6 G7 c$ j5 \  f. I1 z7 R
    {# p1 O" M1 f# G" p5 i
        len = LongToString(str, num1); //第一操作数转换为字符串# X3 }/ V$ n7 l. w; y3 N$ Q
        LcdAreaClear(0, 0, 16-len);    //清除第一行左边的字符位, `! y  u7 y# h; y8 H
        LcdShowStr(16-len, 0, str);    //字符串靠右显示在第一行
. ^' J$ u0 D& o" l( O( U        ShowOprt(1, type);             //在第二行显示操作符
  x, V/ H; n0 z& C9 s3 L7 o( W! ]        LcdAreaClear(1, 1, 14);        //清除第二行中间的字符位
4 b  ^1 \( C( L0 f' ?+ B        LcdShowStr(15, 1, "0");        //在第二行最右端显示02 `) X3 z& Q6 o) d3 L/ z2 F% N
        oprt = type;                   //记录操作类型
% }9 x1 y; P3 m4 w- O; D6 s        step = 1;
1 B( b2 t1 ?6 c( P- x    }
* V5 V' K! ]# |+ `}
: q: y$ z" L1 O6 j& `0 n/* 计算结果函数 */
( n' \, G8 n' X' B6 q; r9 }/ P( kvoid GetResult()
# p! Y, |! M6 b; b8 F- P" c{
! l4 {, L; d2 i" O5 k' ~    unsigned char len;
5 ?. _) w0 E! L. E  D9 P5 @8 O' K    unsigned char str[12];7 \# R' W' T  {. u- @! Q

+ J4 n( d1 \  g2 d    if (step == 1) //第二操作数已输入时才执行计算
) {4 P2 s& i1 C    {
- k+ V1 v& j5 Q% y& [1 \$ h# r! t        step = 2;
& }% e# y! @0 U8 G, G9 y  `  H        switch (oprt)  //根据运算符类型计算结果,未考虑溢出问题/ v' ^4 L0 W+ Z3 K4 F
        {. b, b6 g8 R# l
            case 0: result = num1 + num2; break;: I! |  Y4 b+ M9 R0 g
            case 1: result = num1 - num2; break;
' J; r3 y5 j: r  [            case 2: result = num1 * num2; break;
* A* R) V2 M) C4 b0 `8 \            case 3: result = num1 / num2; break;/ H+ F' y, S8 h* t! L/ D
            default: break;5 l9 Q9 L0 d3 H) }
        }
4 q' T' s, w  h8 V8 {        len = LongToString(str, num2);  //原第二操作数和运算符显示到第一行+ z3 |2 F9 a. e2 m+ S0 L# P* E
        ShowOprt(0, oprt);
/ Y6 t- U8 b% y, G0 r* \/ }        LcdAreaClear(1, 0, 16-1-len);+ q! v, g+ _% h; G4 `6 ]' V1 Z
        LcdShowStr(16-len, 0, str);
7 J3 P. n% e- z) e# e0 `8 t7 |        len = LongToString(str, result);  //计算结果和等号显示在第二行
3 A0 f* W# |( V' ?        LcdShowStr(0, 1, "=");
5 Y, }( ?8 d& i% Y        LcdAreaClear(1, 1, 16-1-len);# {% i" ~5 _0 {$ ^
        LcdShowStr(16-len, 1, str);$ i) \; T4 j( w8 S* F- l0 o
    }' d; x+ d: J7 ^$ W" U4 Y
}, ~$ [# z$ n( I1 r- S% k9 `
/* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */: Z0 Z7 b/ N9 Z2 O
void KeyAction(unsigned char keycode)# H! C7 L$ Y4 J0 k' q7 H! \& B9 j
{  ^9 j/ k' o( C1 b# I3 B) J  u
    if  ((keycode>='0') && (keycode<='9'))  //输入字符
# c% L0 [6 ?& [    {
* r$ x. B0 S! i6 [4 v7 {, i6 J        NumKeyAction(keycode - '0');4 K5 [: Q* }' e0 [% R% W1 l
    }
/ K7 s: I9 v/ b* ^    else if (keycode == 0x26)  //向上键,+( G* t- g5 ^6 p0 v
    {4 R. t. O4 w8 A0 Y& }1 }
        OprtKeyAction(0);6 p* [# ~" a# _6 T$ F
    }/ \9 H/ X' x! I# a, n
    else if (keycode == 0x28)  //向下键,-* T% P/ h& V7 r& r: z: C, t+ s
    {
0 B2 c- |! Q3 t* f+ G1 A% y, Z        OprtKeyAction(1);
% z6 m( c! c+ m  T0 ]/ `    }
4 Y2 C$ q" N5 \2 z    else if (keycode == 0x25)  //向左键,*
9 z; S1 }( y% ^1 I8 M6 l" _    {5 n0 i# r: y' I. `" X* y4 P8 p
        OprtKeyAction(2);' P8 V$ r! h- h" C# d0 p
    }
5 I- S% Q8 f6 N% K    else if (keycode == 0x27)  //向右键,÷
4 `: C. c8 d) r, b4 m    {, T( i8 A: E! A) W3 w  b$ F% x
        OprtKeyAction(3);) E0 e5 @9 _1 R" [5 y' V. ~
    }
6 K! y& S) v  m0 S    else if (keycode == 0x0D)  //回车键,计算结果0 w1 X- D2 s/ G4 d8 d0 S
    {) T' V# V+ d9 h
        GetResult();
5 c6 D, X# f& q6 `; t& m# T    }, J# P  C3 ^* _
    else if (keycode == 0x1B)  //Esc键,清除+ R* c- F- T2 {( e$ g! Y2 k
    {0 O4 k2 B. s& y8 L. U$ i3 H3 i
        Reset();2 h9 w2 [" W/ b2 v1 u' R5 Q
        LcdShowStr(15, 1, "0");; P0 e0 E( N% K! y, R  b
    }/ t. h4 s+ _. c
}
; j4 t; \/ e9 ~$ l, D/* 配置并启动T0,ms-T0定时时间 */
6 E  D) Y" n( Yvoid ConfigTimer0(unsigned int ms)
: M2 Q; g) X# O: |5 X- N! K; Y{& l% W" J& c! V/ z+ V
    unsigned long tmp;  //临时变量5 i2 e; D8 b4 J& h2 M1 Y2 [

4 V6 D  d, {+ R/ O* A    tmp = 11059200 / 12;      //定时器计数频率: _1 S, e* l) c
    tmp = (tmp * ms) / 1000;  //计算所需的计数值9 [' _1 {; I& Y. Q
    tmp = 65536 - tmp;        //计算定时器重载值
( O6 E+ i3 \" ^+ x3 Y1 t    tmp = tmp + 28;           //补偿中断响应延时造成的误差& q/ e" F0 w$ s/ Y! ?' G( X
    T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节) d. j4 g" x$ }! a6 s( D! F/ j
    T0RL = (unsigned char)tmp;, q, }0 ~; m2 X( o3 O6 s
    TMOD &= 0xF0;   //清零T0的控制位) c. R  ?- a5 K1 R5 j$ j( l3 l4 v
    TMOD |= 0x01;   //配置T0为模式1
+ n) }& y. S4 L( D3 W    TH0 = T0RH;     //加载T0重载值1 X6 \: f' w5 g9 N, l& u+ Y
    TL0 = T0RL;) @5 u: [: @% d9 [
    ET0 = 1;        //使能T0中断4 M: X% F' A. V
    TR0 = 1;        //启动T0
) d& A* A5 V( e* l. r8 _}
# S) l, ]4 i0 m0 u0 p7 t" G/* T0中断服务函数,执行按键扫描 */# t! G) {8 f) R; K! B
void InterruptTimer0() interrupt 1- A0 g  l( Z& i+ o0 }; b
{
5 h' f' s. o# U+ ^4 ~- y1 ~    TH0 = T0RH;  //重新加载重载值
5 e. W, J4 ^% H" M    TL0 = T0RL;+ T. y  O' I- Y( L3 e
    KeyScan();   //按键扫描8 y0 H0 G! P" [+ t2 w
}
4 v9 v& e2 x( I$ y0 Z* o$ q
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-10-9 14:08 , Processed in 0.156250 second(s), 23 queries , Gzip On.

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

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

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