您现在的位置是:首页 > 电路图 > 电路图

2位LED显示单片机计算器

转载来源:电子技术应用-AET chinaaet.com 电子发烧友 elecfans.com2017-03-16

简介一、设计要求 1.设计4*4的键盘,其中10个数字键0~9,其余6个为“+” “-” “*”“/” “=”和“C” 2.设计2位LED接口电路 3.实现1位数的简单运算 二、硬件系统设计 1、LED接口电路 简

一、设计要求

1.设计4*4的键盘,其中10个数字键0~9,其余6个为“+” “-” “*”“/” “=”和“C”

2.设计2位LED接口电路

3.实现1位数的简单运算

二、硬件系统设计

1、LED接口电路

简易计算器需要2位8段码LED显示电路。用8031单片机经8255A扩展2位8段码LED显示器,用8255A的A口作为段码(字形代码)数据口,PB0和PB1作为位控制端口。在位控制口加集电极开路的反相高压驱动器74LS06以提供驱动LED显示器所需的足够大的电流,然后接至各数码显示器的共阴极端。同理,在段码数据口集电极开路的正相高压驱动器74LS07提供足够大的电流,然后接到数码显示器的各段。逻辑电路结构如下:

 

    2、键盘接口电路

简易计算器需要4*4的行列式键盘。用8031单片机经8255A扩展4*4行列式键盘,8255A的B口和C口用于扩展键盘接口,B口高4位作为输出口,C口低4位作为输入口。逻辑电路结构如下:

 

 


 

3、计算器逻辑电路图

将LED接口电路和键盘接口电路结合到一起就是简易计算器的逻辑电路图,如下:


三、软件设计

1、LED显示程序设计

LED显示器由七段发光二极管组成,排列成8字形状,因此也成为七段LED显示器,器排列形状如下图所示:

 

为了显示数字或符号,要为LED显示器提供代码,即字形代码。七段发光二极管,再加上一个小数点位,共计8段,因此提供的字形代码的长度正好是一个字节。简易计算器用到的数字0~9的共阴极字形代码如下表:

0~9七段数码管共阴级字形代码

 

2位LED显示的程序框图如下:


 

2、读键输入程序设计

   为了实现键盘的数据输入功能和命令处理功能,每个键都有其处理子程序,为此每个键都对应一个码——键码。为了得到被按键的键码,现使用行扫描法识别按键。其程序框图如下:


3、主程序设计

   (1)数值送显示缓冲程序设计

简易计算器所显示的数值最大位两位。要显示数值,先判断数值正负,如果是负值,则符号位显示“-”,然后将数值除以10,余数送显最最低位,判断商是否为0,若为0则返回,若不为0,则将商除以10,将余数送显高位。程序框图如下:

 

 


 

   (2)运算主程序设计

    首先初始化参数,送LED低位显示“0”,高位不显示。然后扫描键盘看是否有键输入,若有,读取键码。判断键码是数字键、清零键还是功能键(“+”“-”“*”“/”“=” ),是数值键则送LED显示并保存数值,是清零键则做清零处理,是功能键则又判断是“=”还是运算键,若是“=”则计算最后结果并送LED显示,若是运算键则保存相对运算程序的首地址。运算主程序框图如下所示:


 

4、简易计算器源程序

OUTBIT   equ 07FFDh  ; 位控制口

OUTSEG   equ 07FFCh  ; 段控制口

IN       equ 07FFEh  ; 键盘读入口

data1    equ 70h

data2    equ 71h

dizhi1   equ 72h

dizhi2   equ 73h

 

LEDBuf equ   60h     ; 显示缓冲

 

       ljmp  Start

 

LEDMAP:              ; 八段管显示码

       db    3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07h

       db    7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71h

 

Delay:               ; 延时子程序

       mov   r7, #0

DelayLoop:

       djnz  r7, DelayLoop

       djnz  r6, DelayLoop

       ret

 

DisplayLED:

       mov   r0, #LEDBuf

       mov   r1, #2          ; 共2个八段管

       mov   r2, #00000010b  ; 从左边开始显示

Loop:

       mov   dptr, #OUTBIT

       mov   a, #0

       movx  @dptr, a        ; 关所有八段管

 

       mov   a, @r0

       mov   dptr, #OUTSEG

       movx  @dptr, a

 

       mov   dptr, #OUTBIT

       mov   a, r2

       movx  @dptr, a        ; 显示一位八段管

 

       mov   r6, #1

       call  Delay

 

       mov   a, r2           ; 显示下一位

       rr    a

       mov   r2, a

 

       inc   r0

 

       djnz  r1, Loop

 

       ret

 

TestKey:

       mov   dptr, #OUTBIT

       mov   a, #0

       movx  @dptr, a        ; 输出线置为0

       mov   dptr, #IN

       movx  a, @dptr        ; 读入键状态

       cpl   a

       anl   a, #0fh         ; 高四位不用

 

       ret

 

KeyTable:                    ; 键码定义

      

       db    0dh, 0ch, 0bh, 0ah

       db    0eh, 03h, 06h, 09h

       db    0fh, 02h, 05h, 08h

       db    00h, 01h, 04h, 07h

 

GetKey:

       mov   dptr, #OUTBIT

       mov   P2, dph

       mov   r0, #Low(IN)

       mov   r1, #00100000b

       mov   r2, #4

KLoop:

       mov   a, r1           ; 找出键所在列

       cpl   a

       movx  @dptr, a

       cpl   a

       rr    a

       mov   r1, a           ; 下一列

 

       movx  a, @r0

       cpl   a

       anl   a, #0fh

       jnz   Goon1           ; 该列有键入

 

       djnz  r2, KLoop

 

       mov   r2, #0ffh       ; 没有键按下, 返回 0ffh

       sjmp  Exit

Goon1:

       mov   r1, a           ; 键值 = 列 X 4 + 行

 

       mov   a, r2

       dec   a

       rl    a

       rl    a

       mov   r2, a           ; r2 = (r2-1)*4

 

       mov   a, r1           ; r1中为读入的行值

       mov   r1, #4

LoopC:

       rrc   a               ; 移位找出所在行

       jc    Exit

       inc   r2              ; r2 = r2+ 行值

       djnz  r1, LoopC

Exit:

       mov   a, r2           ; 取出键码

       mov   dptr, #KeyTable

       movc  a, @a+dptr

       mov   r2, a

 

WaitRelease:

       mov   dptr, #OUTBIT  ; 等键释放

       clr   a

       movx  @dptr, a

 

       mov   r6, #10

       call  Delay

       call  TestKey

       jnz   WaitRelease

 

       mov   a, r2

       ret

 

Start:

       mov   sp, #40h

       mov   LEDBuf+0, #0

       mov   LEDBuf+1, #03fh

       mov   dptr, #7FFFh

       mov   a,  #89h

       movx  @dptr,  a

 

MLoop:

       call  DisplayLED       ; 显示

       call  TestKey          ; 有键入?

       jz    MLoop            ; 无键入, 继续显示

       call  GetKey           ; 读入键码

 

Jisuan:

       mov   r3, a

       cjne  r3, #0fh, Qita   ;判断是否为清零键?

       mov   r3, #00h         ;清零

       mov   r4, #00h

       mov   r5, #00h

       mov   data1,  #00h

       mov   data2,  #00h

       mov   dizhi1, #00h

       mov   dizhi2, #00h

       mov   LEDBuf+0, #0

       mov   LEDBuf+1, #03fh

       ljmp  MLoop

 

Qita:  clr   c

       cjne  r3, #0ah ,follow   ;判断是数字键还是功能键?

follow:

       jc    Shuzi

       ljmp  Gn

 

Shuzi: mov   a,  r4          ;判断是否已有运算符输入,没有就将数值存在

jnz   Shuzi2           data1,有就将数值存在data2

       mov   a,  r3

       mov   data1, a

       ljmp  Xs              ;显示第一次输入的数值

Shuzi2:

       mov   a,  r3

       mov   data2, a

       ljmp  Xs              ;显示第二次输入的数值

 

Gn:    mov   r4, #01h        ;将01h给r4,说明已有运算符输入

       cjne  r3, #0eh, Ja    ;判断键值是否为“=”?

       mov   r4, #00h        ;将r4清零

       mov   a,   dizhi1     ;执行“=”

       mov   dph, a

       mov   a,   dizhi2

       mov   dpl, a

       mov   a,  #00h

       jmp   @a+dptr         ;转到本次输入的算法程序

 

Ja:    cjne  r3, #0ah, Jn    ;若键值为“+”则将“+”的程序首地址存在

mov   dptr,  #Jia       dizhi1和dizhi2中

       mov   a,  dph

       mov   dizhi1, a

       mov   a,  dpl

       mov   dizhi2, a

       ljmp  MLoop          

 

Jn:    cjne  r3, #0bh, Ce    ;若键值为“-”则将“-”的程序首地址存

mov   dptr, #Jian      dizhi1和dizhi2中

       mov   a,  dph

       mov   dizhi1, a

       mov   a,  dpl

       mov   dizhi2, a

       ljmp  MLoop          

 

Ce:    cjne  r3, #0ch, Cu    ;若键值为“*”则将“*”的程序首地址存在

mov   dptr, #Cheng      dizhi1和dizhi2中

       mov   a,  dph

       mov   dizhi1, a

       mov   a,  dpl

       mov   dizhi2, a

       ljmp  MLoop          

 

Cu:    cjne  r3, #0dh, Zhuan ;若键值为“/”则将“/”的程序首地址存在

mov   dptr, #chu        dizhi1和dizhi2中

       mov   a,  dph

       mov   dizhi1, a

       mov   a,  dpl

       mov   dizhi2, a

Zhuan: ljmp  MLoop          

 

Jia:   mov   a,  data1       ;加法程序

       add   a,  data2

       ljmp  Xs

 

Jian:  mov   a,  data1       ;减法程序

       subb  a,  data2

       ljmp  Xs

 

Cheng: mov   a,  data1       ;乘法程序

       mov   b,  data2

       mul   ab

       ljmp  Xs

 

Chu:   mov   a,  data1       ;除法程序

       mov   b,  data2

       div   ab

 

Xs:    mov   b,  #10         ;显示个位数字

       div   ab

       mov   r5, a

       mov   a,  b

       mov   dptr,#LEDMap

       movc  a, @a+dptr

       mov   LEDBuf+1,a

       mov   a,  r5

First:

       cjne  a,#0,Next

       ljmp  MLoop          ;运算完后继续扫描键盘

 

Next:

       mov   b,#10          ;显示十位数字

       div   ab

       mov   r5, a

       mov   a,  b

       mov   dptr, #LEDMap

       movc  a, @a+dptr

       mov   LEDBuf+0, a

       mov   a,  r5

       ljmp  First

 

       end

 

 

   

四、系统调试与存在的问题

1.在打开一个程序要进行编译运行时,要在项目中打开它,而不是单单以一个文件的形式打开。

2.打开WAVE6000后,需要对仿真器进行设置,然后才能用其对所编程序进行编译并执行。

3.试验箱上提供的6位的LED显示器和4*6的键盘,而简易计算器只用两位LED显示器和4*4键盘,所以必须用软件方法把前4位LED和键盘后2列屏蔽掉。

4. 十位上的LED显示管有数字时才显示,没有数字时不显示,而不是显示“0”,做清零操作后LED显示器个位显示“0”,而全部关闭不显示。

 

五、心得体会

   课程设计是培养学生综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程。随着科学技术发展的日新日异,单片机已经成为当今计算机应用中空前活跃的领域,在生活中可以说得是无处不在。因此作为电子信息工程专业的学生来说掌握单片机的开发技术是十分重要的。
    我的题目是简易计算器,对于我们这些实践中的新手来说,这是一次考验。怎么才能找到课堂所学与实际应用的最佳结合点?怎样让自己的业余更接近专业?怎样让自己的计划更具有序性,而不会忙无一用?这都是我们所要考虑和努力的。这次课程设计我学到很多很多的东西,学会了怎么样去制定计划,怎么样去实现这个计划,并掌握了在执行过程中怎么样去克服心理上的不良情绪。不仅巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识,掌握了一种系统的研究方法,可以进行一些简单的编程。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。同时在设计的过程中发现了自己的不足之处,对以前所学过的知识理解得不够深刻,掌握得不够牢固,对单片机汇编语言掌握得不够好。

    这次课程设计通过我们小组的努力终于顺利完成了,在设计中遇到了很多编程问题,最后在老师的辛勤指导下,终于迎刃而解,在此我表示感谢!同时,对给过我帮助的所有同学和各位指导老师再次表示忠心的感谢!