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

基于1602液晶的简易计算器

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
基于1602液晶的简易计算器
1 ~* ]1 ?' I8 F: L! Z( P9 l& |: w- O2 R: Z8 ]# C, |2 M4 D
/ ~9 E! z& S; y# u
#include <reg52.h>
7 S" S& Z2 \# ~% Q, ^' q
0 M" X  J  `+ R/ s7 _; Munsigned char step = 0;  //操作步骤9 J6 G, X! w2 b  o2 D
unsigned char oprt = 0;  //运算类型$ C0 {0 _' v# v/ |: {
signed long num1 = 0;    //操作数1* D& n  y8 |" Q6 g
signed long num2 = 0;    //操作数2
' e6 f, C' A% r$ v+ E7 bsigned long result = 0;  //运算结果
! \- G2 r2 x3 U; E. d/ ^unsigned char T0RH = 0;  //T0重载值的高字节
' ^7 t6 N% n$ z8 x0 ~2 |unsigned char T0RL = 0;  //T0重载值的低字节
7 q$ I7 K" I, V. f
6 i* a# X4 U6 x! ]( ]3 P* R4 dvoid ConfigTimer0(unsigned int ms);
" k. E; j6 W6 W9 Yextern void KeyScan();
! d& ?( t+ ~  `9 U. fextern void KeyDriver();
) |2 |  m% S( Rextern void InitLcd1602();
+ @  S2 d7 E- ^& cextern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);' c% ]/ v# N8 y* a3 u5 l: I9 E
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
& g2 ~( M9 w2 n9 e! z4 j' ^3 Gextern void LcdFullClear();
7 s9 N/ M  |! G3 L2 }3 ?& s6 s; R& {0 Y6 a. S
void main(). n" ^* M! O# z: W' y  g
{
) P1 \1 P$ Q1 ^9 S; `    EA = 1;           //开总中断4 q  Y- X. i% ~2 r
    ConfigTimer0(1);  //配置T0定时1ms+ v- I; O# t: ^
        InitLcd1602();    //初始化液晶4 \- l3 P: j0 s- N
    LcdShowStr(15, 1, "0");  //初始显示一个数字0% ~5 s5 I/ K7 m! ?/ b

# h0 ]' \9 b9 F% J. N. N: G5 v    while (1)# I% P4 K" ]* @2 D+ Y
    {
) S3 i" K. X4 I/ J5 d        KeyDriver();  //调用按键驱动
, N6 {  `, i0 V5 k# h# p2 V: p, n  L    }( d( B, W" T5 m1 q( T3 ^" X- h
}
$ _) L/ ?8 a" t! Z5 l/* 长整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */( E; L3 L) P7 j! O7 U
unsigned char LongToString(unsigned char *str, signed long dat)- p; I& |, l" D9 }; P% h; F
{
7 n6 H0 r, h. X, q) V( n    signed char i = 0;$ c. {9 ]2 u5 u9 ~' `" _+ E9 ?
    unsigned char len = 0;4 X# y! L. e$ |4 |- \7 ]" p& R
    unsigned char buf[12];, J/ }* o4 x" g( w% o
8 V: r. z: d/ H( J+ a
    if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号/ _( s3 S$ B0 K: p7 i
    {
" j+ ]' r3 T' U' ~1 G* M9 @" Z        dat = -dat;
8 _( H7 `1 G' N" a( o" z        *str++ = '-';* K8 u& A: W1 J7 ?
        len++;/ C/ A5 B) P4 O& s" G7 x% P8 I6 I
    }  D; N1 Y/ ^5 }
    do {          //先转换为低位在前的十进制数组
, ?' O$ }( [& I4 h6 v( k3 N        buf[i++] = dat % 10;
  N* }; K$ I: d( {6 k7 [6 x. }        dat /= 10;. c2 ^' s. r! T# |/ j* ?% E# ]4 v
    } while (dat > 0);2 P0 P* a, _. G2 V
    len += i;     //i最后的值就是有效字符的个数6 U/ f% ^+ J. a5 f+ w$ f
    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上: p- x) l" J8 V5 Y
    {
' W& q, J3 F6 O% E$ \: q+ @        *str++ = buf + '0';6 C- K: t4 L% J; }) I. e* f! G
    }# ^/ @2 s) s5 ]: r9 u( Z* ~( O8 v
    *str = '\0';  //添加字符串结束符
* s; `/ D+ C. N' d9 W% n. x
, g$ l: B6 |1 l0 L" M7 V    return len;   //返回字符串长度
: r4 R: `% H; x5 K}
; \1 i( f! `, _- [' K/* 显示运算符,显示位置y,运算符类型type */0 ^/ [0 `; ~0 B. b9 N7 P, p. o6 A
void ShowOprt(unsigned char y, unsigned char type)+ _* \% z, o/ I" L" {# j
{. W2 j/ I2 o+ G4 G$ H
    switch (type)+ G; f( G+ o5 j) |7 m- c7 x
    {: o/ v0 j3 }3 [
        case 0: LcdShowStr(0, y, "+"); break;  //0代表+
' R# z( p9 _: d3 i8 o        case 1: LcdShowStr(0, y, "-"); break;  //1代表-3 a3 M0 Q' t4 ?1 B
        case 2: LcdShowStr(0, y, "*"); break;  //2代表*
- v" Z6 p, N* M2 Z4 |3 [9 L7 D        case 3: LcdShowStr(0, y, "/"); break;  //3代表/) S0 Z$ d4 p- B0 O
        default: break;
6 _; z7 F! ]! [6 g: |* H: w    }0 ~: T0 D1 v: D$ c% k# Y2 n- B5 A& |$ j
}& l1 x8 u  O6 y8 A: h
/* 计算器复位,清零变量值,清除屏幕显示 */
/ R$ b) e/ I6 H+ h, X2 N9 dvoid Reset()
& w- h/ P$ d9 [: Z6 p: L& Z# s$ J8 N{' C+ x/ z% D1 `1 `" w# |" v: k
    num1 = 0;' G/ O: A3 P  @: k
    num2 = 0;
6 y( S5 s1 M$ u  i, p% e    step = 0;
6 C- C- G& K7 j    LcdFullClear();4 |: U( r" w( M* D; |- ]% p3 _
}! [* j( l4 l; O: k
/* 数字键动作函数,n-按键输入的数值 */: A( [( u( k# i) W
void NumKeyAction(unsigned char n)
6 K: U* k8 Z; K3 c; F7 }" m{
, [1 w3 l5 v2 z/ k: h3 Q7 B1 z4 t    unsigned char len;8 X2 C3 M* n, b' U. S' ~# O" a
    unsigned char str[12];7 S# ~# J# T8 \/ ]" @% M

! V4 I: x( f! G( V! Q$ K6 K    if (step > 1)  //如计算已完成,则重新开始新的计算
) s5 B2 W! V& Q7 l2 d    {2 J. j) e  D% c/ A% K: {
        Reset();% Y+ y- V8 z6 @4 z7 f3 h
    }8 {: m. g5 s# R4 i) y
    if (step == 0)  //输入第一操作数( d( q( ?" ]  z" l+ W0 v
    {
, {; I4 [$ h/ P: u; ~' w2 O; U/ X        num1 = num1*10 + n;             //输入数值累加到原操作数上; b9 C0 ^. h$ l4 C
        len = LongToString(str, num1);  //新数值转换为字符串6 ]/ q+ ?! R/ C
        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上. o! B" Q$ S0 J: X: T6 L
    }
7 U9 P" _( ^6 e, k- v8 v& p    else            //输入第二操作数+ V- r% `3 C- _, P" |
    {6 o/ |( o. Y5 s! O
        num2 = num2*10 + n;             //输入数值累加到原操作数上. g6 h' `! u- o, C
        len = LongToString(str, num2);  //新数值转换为字符串
* j" }; [( X6 r& ~) _( f        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上3 y9 {. A  p. Y0 u9 @
    }$ B$ Q- C0 U& V9 n
}
. B( r9 n- Z2 u& \; ^; b" P* U/* 运算符按键动作函数,运算符类型type */2 F& C" u. e" R* L$ G6 D
void OprtKeyAction(unsigned char type)2 x3 u4 y2 j% N3 i
{0 F0 B& `6 `# S" V( n- e
    unsigned char len;
$ e1 n6 N4 z8 K% w    unsigned char str[12];
6 o( t/ |+ Q+ M7 v0 K8 E9 i; O; R4 }) M) b0 C$ k% K8 C8 d
    if (step == 0)  //第二操作数尚未输入时响应,即不支持连续操作
! k- t7 t8 p* \  a4 [& J    {* v! J" K$ T- G& f" @5 J5 c
        len = LongToString(str, num1); //第一操作数转换为字符串
! W' O9 X  j& z9 L+ p' X7 h0 |# g0 o        LcdAreaClear(0, 0, 16-len);    //清除第一行左边的字符位
( }# @# V' e) Z7 {# M6 e        LcdShowStr(16-len, 0, str);    //字符串靠右显示在第一行7 F! J7 ~3 r, C, L' C- F  V
        ShowOprt(1, type);             //在第二行显示操作符+ K- }9 U* |6 d: e' e3 i
        LcdAreaClear(1, 1, 14);        //清除第二行中间的字符位; W0 p% j4 _+ ?0 M
        LcdShowStr(15, 1, "0");        //在第二行最右端显示0
0 O$ P0 K: T" ]) X- c        oprt = type;                   //记录操作类型
9 y6 ^" \* [8 G1 c, Z        step = 1;
7 e$ X2 Q: \+ y8 W- P    }6 }, o" C# K+ y+ V) e3 g. F1 e6 b( d
}: y: M" N* i# D
/* 计算结果函数 */
4 l7 @, D6 F* p& O. evoid GetResult()  K- F+ C& g+ ]0 \
{
0 D  t+ k1 n/ C$ m8 f; n    unsigned char len;& _$ L  D( w3 }
    unsigned char str[12];
2 ^9 n; F. @- C6 d7 b  H0 x$ F) G  c  O4 d2 _2 E+ w
    if (step == 1) //第二操作数已输入时才执行计算
9 [" m, F$ j# c    {
/ n& [6 i; e5 i3 C0 M7 l  `        step = 2;& [* z0 p% {) {- W8 C
        switch (oprt)  //根据运算符类型计算结果,未考虑溢出问题
' C# {1 k. A8 x  @        {
* m5 W2 A5 F' u# i$ n* p            case 0: result = num1 + num2; break;) d( e0 y8 U# n
            case 1: result = num1 - num2; break;" f5 r& b# M  g$ T; h
            case 2: result = num1 * num2; break;
% _$ m% K* N) l            case 3: result = num1 / num2; break;
+ D0 ^$ ~% q/ F( l  J            default: break;
1 c/ e% p! H2 z/ ~% k! x. ?        }" {3 M' T9 M; O# n1 _
        len = LongToString(str, num2);  //原第二操作数和运算符显示到第一行7 w# j# |$ m  y' U
        ShowOprt(0, oprt);
8 A- [- `& n2 S        LcdAreaClear(1, 0, 16-1-len);
1 I. w7 Q7 k. X" v8 B4 R        LcdShowStr(16-len, 0, str);
% ?- Q) c- V7 L/ K6 m7 J        len = LongToString(str, result);  //计算结果和等号显示在第二行
! j3 Z. y% ?. S' w        LcdShowStr(0, 1, "=");$ X5 S$ C8 K2 O. D8 v
        LcdAreaClear(1, 1, 16-1-len);
; l+ @* _% P& L, {        LcdShowStr(16-len, 1, str);* a0 m3 U7 s5 h: }
    }$ e& S0 \0 \) B( z. J/ T
}) N2 q4 t( ?; G# p  e
/* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */
$ ^9 B9 l7 u& u4 Z6 o( avoid KeyAction(unsigned char keycode)
: J9 |! g( w% D4 W8 J{
6 f* V# v1 V7 t9 O7 _1 Y    if  ((keycode>='0') && (keycode<='9'))  //输入字符
' }, Q: z* n. I    {
& i1 j7 i- V7 X6 ^$ |        NumKeyAction(keycode - '0');
" w8 E4 l. B7 r3 G% k    }
6 x+ u1 _3 P# g    else if (keycode == 0x26)  //向上键,+9 _. U3 x6 c8 t7 L$ V2 ^
    {: U5 }2 A$ Q. z6 q& W
        OprtKeyAction(0);
  d; y8 c4 ]; `- ]3 @$ s2 [    }
# {$ V) B+ ^2 ]3 Z9 g. z    else if (keycode == 0x28)  //向下键,-
6 j% s+ \  \+ L  H/ B    {! O+ z/ q; S0 e% {; C
        OprtKeyAction(1);
: X$ l& E% K4 _9 w$ c) z    }
* c4 A4 K* i) t+ S. o8 r% g    else if (keycode == 0x25)  //向左键,*
/ h3 s2 d& b7 ]  Z7 p3 Z( j    {
* |) P+ ]; y+ M4 m3 ]: m        OprtKeyAction(2);
+ n  J% i* T$ Q    }
1 M$ W, y3 f( N  M0 C" ?    else if (keycode == 0x27)  //向右键,÷
8 S4 w" g0 E& n  ^2 ^# H6 T% C    {/ ^: M- |7 T7 X: p* m) z
        OprtKeyAction(3);
3 g/ V& J: K1 U( d% g    }$ q* o/ V. g' L+ n: p1 U
    else if (keycode == 0x0D)  //回车键,计算结果
3 b" ]6 x4 d, g, r    {5 Q, W0 Y/ [( r% M: y
        GetResult();: T5 U: t  P1 s! d+ e! R
    }
( n2 Z# Z; M3 x9 R8 `# y    else if (keycode == 0x1B)  //Esc键,清除
. |/ s7 i6 c, v1 i2 y+ X9 ?6 B/ Z    {
! O' b  m* n7 t        Reset();
; Q' J, L) o5 L        LcdShowStr(15, 1, "0");2 \2 H# N8 g6 h: @; d
    }- I! g+ q2 y# Z( w* ~( p: w) }
}4 A, \" g) G2 Z, y0 n- a. c
/* 配置并启动T0,ms-T0定时时间 */$ ~( k# u+ z" }7 k+ w
void ConfigTimer0(unsigned int ms)% f1 d4 x. C2 a# P  c5 q
{
: d- S' W* Q  I1 W8 K    unsigned long tmp;  //临时变量2 H3 `5 J7 H( r! C+ S1 t( k
# c+ `# H  y* a1 z# p7 N( \, D
    tmp = 11059200 / 12;      //定时器计数频率: A+ W5 C8 b7 I, S5 Q
    tmp = (tmp * ms) / 1000;  //计算所需的计数值9 Q# }' }6 c# z* c: O0 l+ I
    tmp = 65536 - tmp;        //计算定时器重载值
8 @. F% G7 O$ Q. H    tmp = tmp + 28;           //补偿中断响应延时造成的误差
- }- ?8 v, v  N, g    T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节' A7 J* @* i8 u" c# ^4 b
    T0RL = (unsigned char)tmp;
  M/ f* M8 j) V- y- \/ l    TMOD &= 0xF0;   //清零T0的控制位
: _# _" D3 G" j  U* \/ z    TMOD |= 0x01;   //配置T0为模式1
; ?8 R3 U0 X1 b. j    TH0 = T0RH;     //加载T0重载值
7 W: W2 T$ s5 y9 L" A  M& \3 h/ T    TL0 = T0RL;
- `& [4 b- m6 F7 A. ]7 z: `* O7 v$ e    ET0 = 1;        //使能T0中断! D. C0 E7 J$ m  W* G
    TR0 = 1;        //启动T0
8 G# H3 P' ~) U! o}
( {+ {" s- _  @9 f: I/* T0中断服务函数,执行按键扫描 */9 H, B# q" R# F( X8 C
void InterruptTimer0() interrupt 1
  A3 K+ g$ e  M0 _; w3 @  ~{' \/ F" \, ~. t# K0 }( M
    TH0 = T0RH;  //重新加载重载值8 C+ d  p7 N; I0 l
    TL0 = T0RL;
" T8 {1 M3 D9 A7 E, i$ w5 N2 C    KeyScan();   //按键扫描1 y* |& B* w( E" x: S- M
}

$ Z3 R  Q  m$ J  M# e
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-8-11 12:44 , Processed in 0.125000 second(s), 23 queries , Gzip On.

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

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

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