一、设计要求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接口电路和键盘接口电路结合到一起就是简易计算器的逻辑电路图,如下:8255APA0PA1PA2PA3PA4PA5PA6PA7PB0PB1PB4PB5PB6PB7PC0PC1PC2PC374LS373GCSA1A0D0~D7WR RD RESETWR RD RSTALEP2.78031+5VQ2~Q7Q1Q0A2~A7A1A0D0~D7A8~A11OE CEP0.0~P0.7P2.0~2.3PSEN+5V2732XTAL2XTAL1晶振6MHZ8X74LS072X74LS064X4键盘三、软件设计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 70hdata2 equ 71hdizhi1 equ 72hdizhi2 equ 73hLEDBuf equ 60h ; 显示缓冲ljmp StartLEDMAP: ; 八段管显示码db 3fh, 06h, 5bh, 4fh, 66h, 6dh, 7dh, 07hdb 7fh, 6fh, 77h, 7ch, 39h, 5eh, 79h, 71h Delay: ; 延时子程序mov r7, #0DelayLoop:djnz r7, DelayLoopdjnz r6, DelayLoopretDisplayLED:mov r0, #LEDBufmov r1, #2 ; 共2个八段管mov r2, #00000010b ; 从左边开始显示Loop:mov dptr, #OUTBITmov a, #0movx @dptr, a ; 关所有八段管mov a, @r0mov dptr, #OUTSEGmovx @dptr, amov dptr, #OUTBITmov a, r2movx @dptr, a ; 显示一位八段管mov r6, #1call Delaymov a, r2 ; 显示下一位rr amov r2, ainc r0djnz r1, LoopretTestKey:mov dptr, #OUTBITmov a, #0movx @dptr, a ; 输出线置为0mov dptr, #INmovx a, @dptr ; 读入键状态cpl aanl a, #0fh ; 高四位不用retKeyTable: ; 键码定义db 0dh, 0ch, 0bh, 0ahdb 0eh, 03h, 06h, 09hdb 0fh, 02h, 05h, 08hdb 00h, 01h, 04h, 07h GetKey:mov dptr, #OUTBITmov P2, dphmov r0, #Low(IN)mov r1, #00100000bmov r2, #4KLoop:mov a, r1 ; 找出键所在列cpl amovx @dptr, acpl arr amov r1, a ; 下一列movx a, @r0cpl aanl a, #0fhjnz Goon1 ; 该列有键入djnz r2, KLoopmov r2, #0ffh ; 没有键按下, 返回0ffhsjmp ExitGoon1:mov r1, a ; 键值= 列X 4 + 行mov a, r2dec arl arl amov r2, a ; r2 = (r2-1)*4mov a, r1 ; r1中为读入的行值mov r1, #4LoopC:rrc a ; 移位找出所在行jc Exitinc r2 ; r2 = r2+ 行值djnz r1, LoopCExit:mov a, r2 ; 取出键码mov dptr, #KeyTablemovc a, @a+dptrmov r2, aWaitRelease:mov dptr, #OUTBIT ; 等键释放clr amovx @dptr, amov r6, #10call Delaycall TestKeyjnz WaitReleasemov a, r2retStart:mov sp, #40hmov LEDBuf+0, #0mov LEDBuf+1, #03fhmov dptr, #7FFFhmov a, #89hmovx @dptr, aMLoop:call DisplayLED ; 显示call TestKey ; 有键入?jz MLoop ; 无键入, 继续显示call GetKey ; 读入键码Jisuan:mov r3, acjne r3, #0fh, Qita ;判断是否为清零键?mov r3, #00h ;清零mov r4, #00hmov r5, #00hmov data1, #00hmov data2, #00hmov dizhi1, #00hmov dizhi2, #00hmov LEDBuf+0, #0mov LEDBuf+1, #03fhljmp MLoopQita: clr ccjne r3, #0ah ,follow ;判断是数字键还是功能键?follow:jc Shuziljmp GnShuzi: mov a, r4 ;判断是否已有运算符输入,没有就将数值存在jnz Shuzi2 data1,有就将数值存在data2mov a, r3mov data1, aljmp Xs ;显示第一次输入的数值Shuzi2:mov a, r3mov data2, aljmp Xs ;显示第二次输入的数值Gn: mov r4, #01h ;将01h给r4,说明已有运算符输入cjne r3, #0eh, Ja ;判断键值是否为“=”?mov r4, #00h ;将r4清零mov a, dizhi1 ;执行“=”mov dph, amov a, dizhi2mov dpl, amov a, #00hjmp @a+dptr ;转到本次输入的算法程序Ja: cjne r3, #0ah, Jn ;若键值为“+”则将“+”的程序首地址存在mov dptr, #Jia dizhi1和dizhi2中mov a, dphmov dizhi1, amov a, dplmov dizhi2, aljmp MLoopJn: cjne r3, #0bh, Ce ;若键值为“-”则将“-”的程序首地址存mov dptr, #Jian dizhi1和dizhi2中mov a, dphmov dizhi1, amov a, dplmov dizhi2, aljmp MLoopCe: cjne r3, #0ch, Cu ;若键值为“*”则将“*”的程序首地址存在mov dptr, #Cheng dizhi1和dizhi2中mov a, dphmov dizhi1, amov a, dplmov dizhi2, aljmp MLoopCu: cjne r3, #0dh, Zhuan ;若键值为“/”则将“/”的程序首地址存在mov dptr, #chu dizhi1和dizhi2中mov a, dphmov dizhi1, amov a, dplmov dizhi2, aZhuan: ljmp MLoopJia: mov a, data1 ;加法程序add a, data2ljmp XsJian: mov a, data1 ;减法程序subb a, data2ljmp XsCheng: mov a, data1 ;乘法程序mov b, data2mul abljmp XsChu: mov a, data1 ;除法程序mov b, data2div abXs: mov b, #10 ;显示个位数字div abmov r5, amov a, bmov dptr,#LEDMapmovc a, @a+dptrmov LEDBuf+1,amov a, r5First:cjne a,#0,Nextljmp MLoop ;运算完后继续扫描键盘Next:mov b,#10 ;显示十位数字div abmov r5, amov a, bmov dptr, #LEDMapmovc a, @a+dptrmov LEDBuf+0, amov a, r5ljmp Firstend四、系统调试与存在的问题1.在打开一个程序要进行编译运行时,要在项目中打开它,而不是单单以一个文件的形式打开。