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

基于1602液晶的简易计算器

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
基于1602液晶的简易计算器1 ?% ]$ C7 w8 B8 u( J6 r# S

) r7 }5 @, B8 E+ [* D* _

* R) r1 M* p1 F7 R: T8 e#include <reg52.h>* ?5 y( R- H  y" V5 s

" M$ c: Z0 e! k2 Vunsigned char step = 0;  //操作步骤. _' v8 [0 ~, C3 r4 I4 a% U3 R+ H
unsigned char oprt = 0;  //运算类型
2 y: J( d3 V( f7 @# K8 [( |signed long num1 = 0;    //操作数1
" o$ P% y  `; a/ csigned long num2 = 0;    //操作数2
& u% Z2 o3 v+ msigned long result = 0;  //运算结果' P8 C% ~3 b6 J5 j7 W9 L' w0 L
unsigned char T0RH = 0;  //T0重载值的高字节
* [% l2 y, W. i+ O- {* Q3 s) aunsigned char T0RL = 0;  //T0重载值的低字节. W; P7 I' S3 s& U+ \
2 ]0 M% \3 a: d: R8 e9 G
void ConfigTimer0(unsigned int ms);
& f9 x' P/ v# B3 X( n# sextern void KeyScan();
) K% c3 F0 j( @0 @) y& S0 c8 s5 oextern void KeyDriver();3 I8 l' P+ V/ |3 ]
extern void InitLcd1602();
3 b, g% i/ J2 u5 K7 s* J2 Sextern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);5 ]  e5 P& W7 m0 L. l6 E7 S. J; _
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);2 A( ^, v, T4 A1 ^
extern void LcdFullClear();( G# [3 E! d$ S! s- m
  {3 d/ N2 R* I- L4 ?
void main()' O' ]: Y; ~8 U2 q
{
4 g! a+ Y" z' ?6 y) ?* S    EA = 1;           //开总中断; K% s; w- G. i  d/ B' \0 Y+ @
    ConfigTimer0(1);  //配置T0定时1ms- {* G9 p9 g: G" L9 L
        InitLcd1602();    //初始化液晶
* p3 X. m$ @9 `9 B, U3 X    LcdShowStr(15, 1, "0");  //初始显示一个数字0
5 M/ C: r+ a' [
+ l2 i5 y" Q, N7 ?% I# v# ?    while (1)
, x. ~" d5 Y/ C9 H8 n7 ]    {8 o5 b  u  W& Q+ W7 l6 i2 D" ~3 Q
        KeyDriver();  //调用按键驱动
8 _( D. z. u/ E- s0 w1 _, N* v    }7 H9 Z6 d+ Z- K$ i* N/ a4 Z
}' q% x) u% c8 P
/* 长整型数转换为字符串,str-字符串指针,dat-待转换数,返回值-字符串长度 */' T+ Z" @6 `9 Y$ U9 q, x4 C
unsigned char LongToString(unsigned char *str, signed long dat)
. V$ _: }! b, |' y& [8 ^4 ]. @. g+ c{
& Z8 Z5 L7 E# N* |& E    signed char i = 0;
+ |2 f6 Q( R* m  @! x    unsigned char len = 0;
( t7 G3 G: m# }, j    unsigned char buf[12];
( A% e. g+ p* Q7 a
, Y. t# P6 T% {" c    if (dat < 0)  //如果为负数,首先取绝对值,并在指针上添加负号+ x- Z& r" v* {1 b. l
    {5 `4 S* s8 P3 B, l; M6 r8 ~9 R
        dat = -dat;( ?3 R+ R5 ?+ X# P
        *str++ = '-';
# x1 K: Y* \3 F& W6 j/ w' m        len++;
0 [5 H, w" |8 h4 S2 `) C    }
6 u7 Y( d) ?/ z" T    do {          //先转换为低位在前的十进制数组
* \: g* ^: t) X* }7 A/ c0 a9 s& t) j        buf[i++] = dat % 10;! B; i$ p7 f' ~. W& [
        dat /= 10;( g* r. g0 k9 B$ |
    } while (dat > 0);
: Y1 M* i; ^; Q( U# s    len += i;     //i最后的值就是有效字符的个数3 h8 l& v/ [" Z+ [, X! Q$ h. R
    while (i-- > 0)   //将数组值转换为ASCII码反向拷贝到接收指针上
: c4 X, |: _! {- Z2 f) w    {  }! U; r1 W1 V$ k5 V0 ]! ?
        *str++ = buf + '0';4 n& a& f$ E/ q5 O
    }
+ b; h' _, _5 ?) s- |# S2 e3 @1 f    *str = '\0';  //添加字符串结束符: R7 S! S' V7 k; C  J* x* I+ d
! B1 g5 R1 I  Q7 O5 Q
    return len;   //返回字符串长度  w* F' O* g9 P- ], f
}- L# t' {, V( w3 ^0 V% E$ o
/* 显示运算符,显示位置y,运算符类型type */
$ o; H- d# J/ P, y8 f3 X% Cvoid ShowOprt(unsigned char y, unsigned char type)
9 _, T/ E, U% Y/ I{5 D7 P' {3 D1 J* U
    switch (type)
$ ?8 r% g# _8 ]  F2 v/ \    {! r: J* V8 z# Z3 M4 S2 N' j
        case 0: LcdShowStr(0, y, "+"); break;  //0代表+! F2 k9 d2 h9 e9 w: x
        case 1: LcdShowStr(0, y, "-"); break;  //1代表-
# S7 s* {/ a& B* P5 t9 _$ ~$ j" {        case 2: LcdShowStr(0, y, "*"); break;  //2代表*7 m; Y3 \. z8 ]" t  i8 B
        case 3: LcdShowStr(0, y, "/"); break;  //3代表/
$ I5 r7 f6 \9 s. ?/ `- j        default: break;
( [5 _$ b% U& z5 g    }
+ p& C' h, y0 t2 x. y: ^; w6 p}
5 R  c" P( p6 K* F5 w/* 计算器复位,清零变量值,清除屏幕显示 */
! e- }' g1 M- K" Wvoid Reset()
, h8 j8 {8 e$ a{
) v5 G7 w* B# j% |0 B9 w# n* ~    num1 = 0;! e- {! ?* C! S) x/ N) r
    num2 = 0;
( E5 f% V2 z3 H* ]8 u  h    step = 0;
" K; U- _2 ?- g' l    LcdFullClear();
0 @; P0 u& E2 [% Y3 t- [3 u}
& n2 P3 Q5 J! Z" V! u/* 数字键动作函数,n-按键输入的数值 */
  ]1 S; O$ }  {void NumKeyAction(unsigned char n). ^6 H1 H: S' }5 |; f! z
{9 u8 r; ~0 q, `/ r7 S) [
    unsigned char len;
% p& \: U' u' @, h/ D: W    unsigned char str[12];
2 m5 E: F$ L9 |# @# x) |' ?1 U. ?
8 }- X9 J3 u7 y0 f8 ^( @9 C. r5 o: J    if (step > 1)  //如计算已完成,则重新开始新的计算* D; t8 |2 ]& H. F2 P
    {/ b3 ~2 [; {$ t* V" ?1 y
        Reset();
) Y% H% G, h4 k7 ~, b    }9 [1 \5 `( @& t: M
    if (step == 0)  //输入第一操作数% u% ?' \# [6 K4 W! A
    {: ~, K0 Z! M4 i' G( h4 y! g1 m
        num1 = num1*10 + n;             //输入数值累加到原操作数上
7 d* K' O# W3 X+ r* {, V        len = LongToString(str, num1);  //新数值转换为字符串
- O) c7 S% N3 `+ ?- @        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上/ {. i5 x. C7 u% b3 g. U
    }
6 ~" _8 r( A7 \+ \2 B" f( d    else            //输入第二操作数
1 e) @& X. y  l, S$ T; Y    {  ~$ f# l7 {  E
        num2 = num2*10 + n;             //输入数值累加到原操作数上! R5 y: f7 q: a5 N0 J0 X% q+ o- N
        len = LongToString(str, num2);  //新数值转换为字符串' b2 N- o0 a* d1 e. _, A, g" z
        LcdShowStr(16-len, 1, str);     //显示到液晶第二行上
. v! H* I- Q; Y, y0 @  Z2 Y    }- \1 K/ g- c/ `8 ?$ Y( p
}
# k) ^; c/ F7 x. {/* 运算符按键动作函数,运算符类型type */
) R5 {6 Y1 y" A. ^& pvoid OprtKeyAction(unsigned char type)% x7 V% q% \7 R9 n
{" u* u- F* K9 u, o& i6 ?
    unsigned char len;
2 t/ V7 ?8 Y& V( g4 J8 M7 g4 ]/ }; ?4 n    unsigned char str[12];
% L2 B* L6 Z- ~2 ~  v, i2 t  e& K' n5 L( @
    if (step == 0)  //第二操作数尚未输入时响应,即不支持连续操作
& }5 h/ _8 W- T, X# d2 |    {$ e8 {. T5 F) U7 c
        len = LongToString(str, num1); //第一操作数转换为字符串6 F* I' `+ e( Y. V
        LcdAreaClear(0, 0, 16-len);    //清除第一行左边的字符位
/ S* F: P7 T2 W: t7 M+ h' I& @        LcdShowStr(16-len, 0, str);    //字符串靠右显示在第一行
  K& N7 G! X' I( n: f        ShowOprt(1, type);             //在第二行显示操作符
- _  \1 R. r$ v6 G; G% k        LcdAreaClear(1, 1, 14);        //清除第二行中间的字符位
) L  ?8 W" g: o5 b. y% J2 I        LcdShowStr(15, 1, "0");        //在第二行最右端显示0
$ O* l, R+ a5 Q        oprt = type;                   //记录操作类型) p9 ?! c+ Y1 _8 J/ w% `
        step = 1;
3 T% }& a  C; L, N9 Z4 x" g    }
- f& C* G9 y  x' A: h; k" j: k1 u1 [}* q# v( K' M, m, y$ O- o, H
/* 计算结果函数 */
- @$ H6 I% g1 T2 F% Uvoid GetResult()
. A- M; P- J$ q$ k{
  M2 q" [) m. @! w- ], m- H8 z' H    unsigned char len;
6 W9 U2 l. R. _    unsigned char str[12];
3 v0 a& U* q* n4 n+ k
* T/ ^# i2 W, j' ~3 p8 ~& ?, C    if (step == 1) //第二操作数已输入时才执行计算
4 c  }/ N& [, c6 ?2 u    {  w# f4 ^0 y# p: D0 `; p# o) b
        step = 2;
* ~; q0 y. P. ~        switch (oprt)  //根据运算符类型计算结果,未考虑溢出问题6 Z+ d9 }) ]$ K* n8 c5 w
        {
0 ~0 Q9 k6 R1 }3 s0 k! ~" `            case 0: result = num1 + num2; break;
" H: M: ]* j$ T2 m            case 1: result = num1 - num2; break;
9 k/ m; E8 }# p- p- l& D6 }& d            case 2: result = num1 * num2; break;
; @8 l0 K) _1 k3 U            case 3: result = num1 / num2; break;
' a& m8 J6 K# Q0 o! x9 W5 u% N1 K( h2 R            default: break;
. o4 u1 ~7 O6 p        }# t3 R. h7 R8 ~  c% \
        len = LongToString(str, num2);  //原第二操作数和运算符显示到第一行
' W! L! S8 m2 B' u8 I        ShowOprt(0, oprt);
8 s) X! G. r- x8 ~        LcdAreaClear(1, 0, 16-1-len);
+ Q: T9 Y5 k! z        LcdShowStr(16-len, 0, str);6 U7 ?" M9 J8 I: \+ g! g$ D8 o2 z
        len = LongToString(str, result);  //计算结果和等号显示在第二行8 `/ x3 E) e. t  |
        LcdShowStr(0, 1, "=");1 }& ], ]2 e' p% W
        LcdAreaClear(1, 1, 16-1-len);
: ]7 B$ q/ n1 H9 q4 A9 `( f        LcdShowStr(16-len, 1, str);7 M+ u( C% `( \, s3 P9 x! Q" ^0 s% v
    }
6 O! v: ~0 C2 F8 w: U}
( a  o7 M( w4 N% }' S* a( Y/* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */
' j3 F, B/ l! ]0 f* i$ s) gvoid KeyAction(unsigned char keycode)
& s4 x3 L% s4 b! v" o{
- r* g, o) j9 K' k8 t    if  ((keycode>='0') && (keycode<='9'))  //输入字符0 t; ^7 k5 Z# b6 e
    {; V7 [3 ?- J% z) w4 x: n
        NumKeyAction(keycode - '0');  P/ h) A$ u( g. S8 ^- Q" _
    }
5 O$ k/ `+ m4 j# Q    else if (keycode == 0x26)  //向上键,+8 @0 g" W7 {( G- J/ o; n
    {
* w% ?4 A" f& l" B+ U7 j  v; Q0 a        OprtKeyAction(0);
+ H$ z4 K  {9 c8 f# D    }8 k) ~4 G4 D% E5 z
    else if (keycode == 0x28)  //向下键,-
+ A2 m8 T" Y; k, @+ R    {. z$ @/ q- X4 G+ }) X/ D6 i0 J5 |) G3 f3 [
        OprtKeyAction(1);! M& T% f9 D5 P* d
    }6 O# E! t" W$ Q2 e! E
    else if (keycode == 0x25)  //向左键,*
' [7 S) k8 i1 z! n. A  f5 G    {
6 ]" ~; d) y+ u        OprtKeyAction(2);
; Z: D( c; c$ U( p; u% z7 \% w5 j    }3 A0 j" K. y! K" Q) X
    else if (keycode == 0x27)  //向右键,÷
* I/ C0 R- J5 C/ v- W" A    {
  Z/ H  s2 n8 i# J4 k        OprtKeyAction(3);0 ~2 Z  e: L3 J7 k6 Q
    }
4 L) p8 Q3 j$ d6 L* S" i    else if (keycode == 0x0D)  //回车键,计算结果$ E: [, p# O. z2 b# j' p# c
    {* C) l; U2 y) o. t
        GetResult();
( a! R4 g' J" z& |) O7 o7 `    }) Z7 k. k( B# C8 s3 Q& d- \# b, E; ^
    else if (keycode == 0x1B)  //Esc键,清除
7 s$ U2 _  q+ f) s, C    {: [/ Z5 ^4 e/ z$ i
        Reset();/ t! ?8 e! m- _3 g
        LcdShowStr(15, 1, "0");8 W0 y0 {' C9 m1 p( D0 m0 ^
    }
4 H: x% d0 ?& h# K}- ^, Q; Z  Z+ q, y, n# f: }# ?8 y2 `
/* 配置并启动T0,ms-T0定时时间 */
. X9 S4 y: D" f6 N; t; V% {void ConfigTimer0(unsigned int ms), c( e+ D: q- `7 B; t. m0 Z
{' p2 j! C6 }1 y  V$ C; {6 t. G
    unsigned long tmp;  //临时变量
. ?: u  v  b! a2 `% l
( M: H( i1 N: M5 h9 e, D) V    tmp = 11059200 / 12;      //定时器计数频率
$ {' M2 ^; l- R4 F$ K    tmp = (tmp * ms) / 1000;  //计算所需的计数值
1 G- `- I/ d1 S9 A3 x2 Q: Q4 A    tmp = 65536 - tmp;        //计算定时器重载值* O9 c  c7 O- t8 S
    tmp = tmp + 28;           //补偿中断响应延时造成的误差4 |: [" [: H1 f3 k9 E+ |1 g- `
    T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节
$ R; f0 Q3 Y8 Y5 t( L+ Q1 {    T0RL = (unsigned char)tmp;
! l3 z# T$ l$ {8 B    TMOD &= 0xF0;   //清零T0的控制位: D! T" f; I  t  o1 i$ l' {2 q
    TMOD |= 0x01;   //配置T0为模式1
4 g, D9 u6 [3 N" r2 ^# M5 g, Q. g    TH0 = T0RH;     //加载T0重载值0 A  }: B2 U' A* r
    TL0 = T0RL;
- n: Y" V' _$ \+ ~& Y    ET0 = 1;        //使能T0中断
/ L4 S# r5 r2 [" d3 N( l  ~    TR0 = 1;        //启动T0
( P' l5 ~) Y6 y% U2 F}; |2 [  T7 a# E1 l) B+ }2 j$ x
/* T0中断服务函数,执行按键扫描 */8 i, F" K. e3 b+ I# C4 U0 h+ ]
void InterruptTimer0() interrupt 1
2 X. ^; X0 i+ d/ n3 b{' m: H7 L& b' T  l% [" m
    TH0 = T0RH;  //重新加载重载值& n2 g, g) g7 A* _
    TL0 = T0RL;
7 B5 I% y& J1 ]! v; P6 I    KeyScan();   //按键扫描" P5 e0 j$ i2 v0 P( z8 s: I
}

) b4 ]3 v% m& h- z
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-7-20 03:53 , Processed in 0.125000 second(s), 23 queries , Gzip On.

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

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

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