收银机.docx
《收银机.docx》由会员分享,可在线阅读,更多相关《收银机.docx(28页珍藏版)》请在冰豆网上搜索。
![收银机.docx](https://file1.bdocx.com/fileroot1/2023-2/3/8e9676d6-ae3e-448f-9209-5ad7bfa948a9/8e9676d6-ae3e-448f-9209-5ad7bfa948a91.gif)
收银机
上海电力学院
微处理器综合设计实践报告
题目:
收银台的设计
院系:
计算机与信息工程学院
专业:
电子科学与技术年级:
2008141
姓名:
丁晓亮学号:
20082614
指导老师:
阮颖、杨芳
一、课程设计目的:
综合应用所学的微处理器原理,汇编语言及相关硬件知识,设计一个具有一定功能的电路。
熟练掌握仿真器和编程器的使用。
二、课程设计要求:
要求:
以单片机为核心器件,组成一个收银机系统,能通过4×4键盘的“0”-“9”键实现商品单价和商品数量的输入,“A”、“B”、“C”、“D”键作为功能键,完成“+”、“×”、“=”和清零的功能,并通过LED显示结果。
三、系统组成与工作原理:
1、电路原理图
本电路原理图由基本的单片机系统组成,其中P1口与4*4键盘相连,行线与P1.0~P1.3相连,列线与P1.4~P1.7相连;P0口分别与七段数码管的字线a,b,c,d,e,f,g,ph相连,P0口作为输出口时外接上拉电阻;P2.0~P2.3分别控制七段数码管的位线ABCD,每根线上加由一个电阻和三极管构成的放大电路作为驱动;P2.0控制一个蜂鸣器;最小系统包括晶振,上电自动复位电路,电源等。
2、工作原理
课程设计的基本要求是要通过键盘输入商品单价和数量,运算出结果并显示到七段数码管上。
以此要求,本程序应该主要包括三个方面:
键盘输入单元、逻辑运算单元以及结果显示单元。
总体流程图如下:
单片机上电初始化之后始终处于键盘扫描,将扫描到的信息进行处理并将处理结果通过七段数码管显示出来的循环之中。
下面来分析各个模块的功能实现以及其中注意的问题:
(一)、键盘扫描
本设计使用的是一个4*4的矩阵式键盘,它是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。
在行线和列线的每一个交叉点上,设置一个按键。
这样键盘中按键的个数是4*4个。
这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。
下图是矩阵键盘的电路图,行线接P1.0~P1.3,列线接P1.4~P1.7。
当某一个按键按下时,该键所在的行与列相连,也就是在读取该键所在行的状态时就是该列的状态,读取该键所在列的状态时就是该行的状态,以此原理可以设计出键盘扫描程序,并得到各个按键的特征编码。
先从P1口的高四位输出低电平,低四位输出高电平,从P1口的低四位读取键盘状态;再从P1口的高四位输出高电平,低四位输出低电平,从P1口的高四位读取键盘状态。
将两次读取结果组合起来就可以得到当前按键的特征编码。
各数字特征编码如下:
未有键按下的特征码是FFH,部分扫描子程序如下:
MOVP1,#0FH
MOVA,P1
ANLA,#0FH
MOVB,A
MOVP1,#0F0H
MOVA,P1
ANLA,#0F0H
ORLA,B
最终累加器A中存储的是扫描到的特征码,随后可以通过建表查表的方法得
扫描子程序的流程为:
先判断有无按键按下,若无则返回主程序,若有按键按下则判断是否为各功能键,若为功能键则跳转到相应的功能键子程序完成相应功能,最终返回主程序。
若非功能键则通过查表方式得到相应的数字,存储后转到主程序。
(二)、结果显示
本设计运算的结果是通过四个七段数码管来显示,为了节省单片机的I/O口,采用了动态显示的方法。
数码管不同位显示的时间间隔可以通过调整延时程序的延时长短来完成。
数码管显示的时间间隔也能够确定数码管显示时的亮度,若显示的时间间隔长,显示时数码管的亮度将亮些,若显示的时间间隔短,显示时数码管的亮度将暗些。
若显示的时间间隔过长的话,数码管显示时将产生闪烁现象。
所以,在调整显示的时间间隔时,即要考虑到显示时数码管的亮度,又要数码管显示时不产生闪烁现象。
需要显示的运算结果会分别存在千位单元QW,百位单元BW,十位单元SW以及个位单元GW,因此结果显示子程序只需要读取各单元的内容,转换成七段数码管的特征码输出即可。
其流程图可表示如下:
七段数码管的各特征码如下:
(三)、逻辑运算
本设计最重要的就是中间的逻辑运算部分。
收银机主要会是以两种运算进行,第一是乘法,第二是加法。
其中乘法用来计算单价乘以数量,加法用来表示各个商品的总价格的和。
这样就会有两种类型的公式:
一种是A*B+C*D+···,另一种是当数量为1的时候A*B+C+D···。
所以在各个功能键的子程序中需要判断上一次按下的功能键。
例如A*B+C*D+···,当按下D后面的加号的时候要判断上一次的符号,若是乘法则直接相乘并与第一次相乘得到的结果相加得出最终结果,若是加法则将前两个数相加。
本设计中使用了三个操作数存储单元,分别是X,Y,Z。
流程图如下:
(四)、各子模块
具体的子模块又分为加法子程序,乘法子程序,错误处理子程序,延时子程序,显示器中间清零子程序等。
加法子程序:
加法就是将第一操作数X(高八位为XX)与第二操作数Y(高八位为YY)相加,并将结果高位存至XX,低位存到X,注意将YY清零。
再将结果的每一位依次存至QW、BW、SW、GW。
这里需要注意的地方是存储的操作数以及显示数据均为BCD码,在进行加法指令之后需要调用十进制转换指令DA来进行调整。
乘法子程序:
乘法有两种情况,一种是X与Y相乘,另一种是Y与Z相乘,不管是哪种情况,具体的思路都是一样的。
由于存储的操作数都是以BCD码的形式存储的,所以在使用乘法指令MUL之前,需要将BCD码均转化成等值的十六进制数,因此此处会有BCDH的子程序。
将转化完成的数相乘之后,需要将十六进制结果转换成能够显示并存储的BCD码,因此此处会有HBCD的子程序。
若是X*Y则将结果的高位存至XX,低位存到X;若是Y*Z则将结果的高位存至YY,低位存到Y。
再将结果的每一位依次存至QW、BW、SW、GW。
错误处理子程序:
当输出的结果超过9999时就会发生溢出错误。
因为每次最大的乘法是99*99=9801(本程序设计的是操作数最多是两位数)未溢出,所以只有加法才会出现溢出的情况,当发生溢出时,七段数码管显示“EEEE”,并且蜂鸣器报警,此时只有按下“清零”才能继续工作。
显示器中间清零子程序:
在每次输入数据的时候,显示器会实时显示对应的数字,但是在按下符号键之后输入另一个数据的时候,需要将原先显示的数据进行清零操作以实时显示另一数据的输入,因此也就有了中间清零的子程序。
该程序只在下一操作数按下时执行。
五、数据存储单元的设置及说明
ZANCUNEQU25H;暂存输入数据
GWEQU30H;输出显示的个位
SWEQU31H;输出显示的十位
BWEQU32H;输出显示的百位
QWEQU33H;输出显示的千位
FLAGEQU34H;判断是否松开键盘的标识
CHENG_ZANCUNEQU35H;乘法暂存
BCDH_ZANCUNEQU36H;BCD码转16进制暂存
DISPHEQU37H;暂存输出显示的高八位
DISPLEQU38H;暂存输出显示的低八位
ERROR_FLAGEQU39H;错误标识位
X1EQU40H;第一操作数的第一位输入
X2EQU41H;第一操作数的第二位输入
XEQU42H;第一操作数的结果
Y1EQU43H;第二操作数的第一位输入
Y2EQU44H;第二操作数的第二位输入
YEQU45H;第二操作数的结果
Z1EQU46H;第三操作数的第一位输入
Z2EQU47H;第三操作数的第二位输入
ZEQU48H;第三操作数的结果
XXEQU49H;第一操作数运算过程中产生的进位
YYEQU4AH;第二操作数运算过程中产生的进位
需要具体说明的标识如下:
FLAG:
判断是否松开键盘的标识。
其原理是在初始化程序中将其置1以保证在第一次正确扫描。
在主程序循环中,当无按键按下时将其置1,有按键按下后将其置0。
在每次扫描按键之后会判断FLAG中的值,若为0则表示按键按下后没有松开,输入无效,不执行数据存储,功能键判断等操作,直接返回主程序;若为1则表示中间有检测到松开键盘,输入有效,执行数据存数,功能键判断等操作。
ERROR_FLAG:
错误标识位。
初始化程序中将其置0,在发生溢出的情况下将其置1,在每一次扫描键盘后有一个判定,若ERROR_FLAG为0,则程序继续执行,若ERROR_FLAG为1则只判断扫描的特征码是否为“清零”的特征码,若是则转至清零程序,若不是则直接返回主程序。
X1,X2,Y1,Y2,Z1,Z2:
三组分别是X,Y,Z的第一位输入和第二位输入。
以操作数X为例,当输入的是第一位时,即R2=1时,,将ZANCUN单元(扫描到的数据存在ZANCUN单元)中的值给X1以及X;若有第二位输入,即R2=2时,将ZANCUN单元中的值给X2,此时X1中的值代表的是十位上的数,X2中的值代表的是个位上的数,因此需要将X1乘以10H并加上X2,结果存至X。
R2、R3、R4:
分别用来对操作数X,Y,Z的计数。
本设计中操作数最高为两位数,因此需要设置这样的标识来判断输入数目的个数。
这三个寄存器在初始化程序均清零。
以操作数X的输入为例,当输入第一位的时候,R2=1,当输入第二位的时候,R2=2;当再有连续的数据输入即R2>2时,程序选择忽略。
这些标志位在有功能键按下后进行清零。
R5:
R5用来存储符号,若按下“+”则将其置1;若按下“*”则将其置2;在初始化,按下“=”及“清零”时将其置0。
R6:
R6用来标识乘号所在的位置,即标识是否等待第三操作数。
R5、R6的状态将影响到操作数的存储,当R5=0时,则说明还没有符号被按下过,操作数存至X;当R5=1时,则说明上一次按下的符号是“+”,操作数存至Y;当R5=2时,则说明上一次按下的符号是“*”,此时需要检测“*”前面的符号,当R6=1时,则说明前面是“+”,需要等待第三操作数Z的输入,此时操作数存至Z;当R6=0时,则说明前面没有符号,此时操作数存至Y。
四、总结
1、电路设计过程中的问题及解决。
在电路设计时,看到发下来的一大堆的电路元器件时有些不知所措;接着静下心来,联系平时老师所教的知识设计思路。
由于DXP很久没用了,有些已经遗忘了,所以需要查找以前的书,找出如何设计器件。
我发现许多元器件在元件库中没有现成的,需要自己亲手来设计制作。
在设计晶振和蜂鸣器,我在单片机上找到了相应的接法。
最后是检查设计的电路,在单片机和led之间接了一个反向器后来发现没有反向器电路也可以正常工作,而反向器反而起到了画蛇添足的作用,于是将反向器拿掉了。
在最初设计放大电路的四个放大三极管的电位都一样,不能进行有效的工作,后来我将连接在的放大器件之间的那根线去掉,就能正常运行了。
2、面包板搭建过程中的问题及解决。
在面包板的搭建前首先要要考虑的是如何排版,如何按照电路图连接导线。
为了方便最后的检查,可以用不同颜色的线来区分,如接电源的用红线、接地的用蓝线等等。
在搭建面包板的时候,容易出现线安插的不够深导致接触不良或断路的问题。
3、软件编写过程中的问题及解决。
在编写程序的时,所谓困难重重,许多要用的程序不知道怎么写,子程序的调用也不是很清楚,通过上网找资料,找到了基本的框架,再通过翻阅单片机的书找到了一些资料。
最终在同学的帮助下才完成了软件的编写。
4、所采用的软硬件调试方法,调试过程中出现的问题及解决。
首先在用万用表检测时,发现有些地方不导通,经老师帮忙检查发现接“3、4、3”那边接错了;有些LED不显示,经过仔细的检查,发现其中一个导线没接好。
在用仿真器调试的时候,一开始单片机显示灯不亮,经过检测发现是接触不好导致的,所以要插紧芯片;加载运行时LED上不亮,经过检查是驱动没有选择好,在一系列的调试后终于成功了。
5、从本次课程设计中得到的体会。
回顾这几天的努力,我难以忘却,同样受益匪浅。
我记得刚开始需要画电路设计图的时候,我不知如何下手,但在同学的帮助下我很快就想出了设计思路,并画出了电路图。
虽然,在老师的检查下,有许多错误,如在最初设计时放大电路的四个放大三极管的电位都一样,不能进行有效的工作,但是我还是觉得自己把学到的东西应用起来,.有些成就感。
经过面包板搭建后,我觉得做任何事都要细心,一旦有一个细小的地方出错,将会全盘出错。
在编写程序的时,所谓困难重重,许多要用的程序不知道怎么写,子程序的调用也不是很清楚,我觉得自己学的东西还不能灵活运用,也告诉我要善于到网上等方面查阅自己需要的资料。
总之,本次课程设计让我对集成电路的设计过程有了更多的认识,单片机的知识有了进一步的加深强化,能够学以致用,同时我也加深了程序的设计的了解,增强了自己的动手操作能力,学到了许多书本上没有的东西。
五、附程序清单
ORG0000H
LJMPMAIN
ORG0050H
MAIN:
ZANCUNEQU25H;暂存输入数据
GWEQU30H;输出显示的个位
SWEQU31H;输出显示的十位
BWEQU32H;输出显示的百位
QWEQU33H;输出显示的千位
FLAGEQU34H;判断键盘是否松开键盘的标识
CHENG_ZANCUNEQU35H;乘法暂存
BCDH_ZANCUNEQU36H;BCD码转16进制暂存
DISPHEQU37H;暂存输出显示的高八位
DISPLEQU38H;暂存输出显示的低八位
ERROR_FLAGEQU39H;错误标识位
X1EQU40H;第一操作数的第一位输入
X2EQU41H;第一操作数的第二位输入
XEQU42H;第一操作数的结果
Y1EQU43H;第二操作数的第一位输入
Y2EQU44H;第二操作数的第二位输入
YEQU45H;第二操作数的结果
Z1EQU46H;第三操作数的第一位输入
Z2EQU47H;第三操作数的第二位输入
ZEQU48H;第三操作数的结果
XXEQU49H;第一操作数运算过程中产生的进位
YYEQU4AH;第二操作数运算过程中产生的进位
;---------------------初始化--------------------------
MOVSP,#60H
CLRA
MOVP2,#0FFH
MOVGW,A
MOVSW,A
MOVBW,A
MOVQW,A
MOVR0,A
MOVR1,A
MOVR2,A
MOVR3,A
MOVR4,A
MOVR5,A
MOVR6,A
MOVR7,A
MOVX,A
MOVY,A
MOVZ,A
MOVX1,A
MOVX2,A
MOVY1,A
MOVY2,A
MOVZ1,A
MOVZ2,A
MOVXX,A
MOVYY,A
MOVFLAG,#01H
MOVERROR_FLAG,A
;-------------------主程序循环-----------------------
LOOP:
LCALLKEY_SCAN
LCALLLED_DISPLAY
SJMPLOOP
;-----------------键盘扫描---------------------------
KEY_SCAN:
MOVP1,#0FH
MOVA,P1
ANLA,#0FH
MOVB,A
MOVP1,#0F0H
MOVA,P1
ANLA,#0F0H
ORLA,B
MOVR0,ERROR_FLAG
CJNER0,#00H,ERROR_NEXT;-----判断有无错误------
CJNEA,#0FFH,YS1
MOVFLAG,#01H
RET
ERROR_NEXT:
;------发生错误时只扫描键盘的清零键是否按下-----
CJNEA,#77H,ERROR_EXIT
LCALLCE
ERROR_EXIT:
RET
YS1:
MOVR0,FLAG
CJNER0,#01H,KEY_EXIT
CJNEA,#77H,YS2
LCALLCE;转清零
YS2:
CJNEA,#7DH,YS3
LCALLCHENG;转乘号判定
MOVFLAG,#00H
RET
YS3:
CJNEA,#7EH,YS4
LCALLJIA;转加号判定
MOVFLAG,#00H
RET
YS4:
CJNEA,#7BH,YS5
LCALLDENG;转等号判定
MOVFLAG,#00H
RET
YS5:
CJNEA,#0B7H,YS6
LCALLXING;转星号子程序
MOVFLAG,#00H
RET
YS6:
CJNEA,#0E7H,KEY_IN
LCALLJING;转井号子程序
MOVFLAG,#00H
RET
KEY_IN:
MOVR0,#0FFH
MOV26H,A
MOVDPTR,#KEY_TAB
KEY_IN1:
INCR0
MOVA,R0
MOVCA,@A+DPTR
CJNEA,26H,KEY_IN2
MOVZANCUN,R0
LCALLQINGLING;------有新数据输入,显示器清零----
LCALLCZS
SJMPKEY_EXIT
KEY_IN2:
JNZKEY_IN1
KEY_EXIT:
MOVFLAG,#00H
RET
;----------------操作数存储----------------------------
CZS:
CJNER5,#00H,CZS2
CZS1:
INCR2;-----------输入两位数的情况-----
CLRC
CJNER2,#02H,LL
MOVSW,X1
MOVX2,ZANCUN
MOVGW,X2
MOVA,X1;---------------拼成压缩BCD码----
MOVB,#10H
MULAB
ADDA,X2
MOVX,A
RET
LL:
JNCCZS1_EXIT;--------输入一位数的情况---
MOVX1,ZANCUN
MOVGW,X1
MOVX,X1
RET
CZS1_EXIT:
MOVR2,#02H;----R2保证输入的最多是两位数--
RET
CZS2:
CJNER6,#00H,CZS3
INCR3
CLRC
CJNER3,#02H,MM
MOVSW,Y1
MOVY2,ZANCUN
MOVGW,Y2
MOVA,Y1
MOVB,#10H
MULAB
ADDA,Y2
MOVY,A
RET
MM:
JNCCZS2_EXIT
MOVY1,ZANCUN
MOVGW,Y1
MOVY,Y1
RET
CZS2_EXIT:
MOVR3,#02H
RET
CZS3:
INCR4
CLRC
CJNER4,#02H,NN
MOVSW,Z1
MOVZ2,ZANCUN
MOVGW,Z2
MOVA,Z1
MOVB,#10H
MULAB
ADDA,Z2
MOVZ,A
RET
NN:
JNCCZS3_EXIT
MOVZ1,ZANCUN
MOVGW,Z1
MOVZ,Z1
RET
CZS3_EXIT:
MOVR4,#02H
RET
;-----------------各功能键判断-----------------
;----R5用来存储符号,加号表示为1,乘号表示为2,当等于0时表示还没有符号位按下过---
;----R6用来标识乘号所在的位置,即标识是否等待第三操作数-----
CHENG:
CJNER5,#01H,CHENG_EXIT
MOVR6,#01H
CHENG_EXIT:
MOVR5,#02H
MOVR4,#00H
MOVR3,#00H
RET
JIA:
CLRC
CJNER5,#01H,JIA1
LCALLJIAFA
SJMPJIA_EXIT
JIA1:
JCJIA_EXIT
CJNER6,#00H,JIA2
LCALLCHENGFA
SJMPJIA_EXIT
JIA2:
LCALLCHENGFA1
LCALLJIAFA
MOVR6,#00H
JIA_EXIT:
MOVR5,#01H
MOVR3,#00H
MOVR4,#00H
RET
DENG:
CJNER5,#01H,DENG1
LCALLJIAFA
SJMPDENG_EXIT
DENG1:
JCDENG_EXIT
CJNER6,#00H,DENG2
LCALLCHENGFA
SJMPDENG_EXIT
DENG2:
LCALLCHENGFA1
LCALLJIAFA
DENG_EXIT:
MOVR2,#00H
MOVR3,#00H
MOVR4,#00H
MOVR5,#00H
MOVR6,#00H
RET
CE:
LJMPMAIN
XING:
;MOVGW,#00H
;MOVSW,#0AH
;MOVBW,#11H
;MOVQW,#17H
RET
JING:
;。
。
。
。
。
。
。
。
。
。
。
。
。
随意
MOVGW,#04H
MOVSW,#01H
MOVBW,#06H
MOVQW,#02H
RET
;---------------加法子程序-------------------------
JIAFA:
PUSHPSW
CLRC
MOVA,X
ADDA,Y
DAA
MOVX,A
MOVA,XX
ADDCA,YY
DAA
JNCJIAFA_NEXT
LJMPERROR
JIAFA_NEXT:
MOVXX,A
MOVYY,#00H
MOVDISPH,XX
MOVDISPL,X
LCALLTODISP
POPPSW
RET
;-----------------乘法子程序----------------------
CHENGFA:
MOVA,X
LCALLBCDH
MOVCHENG_ZANCUN,A
MOVA,Y
LCALLBCDH
MOVB,CHENG_ZANCUN
MULAB
LCALLHBCD
MOVXX,DISPH
MOVX,DISPL
LCALLTODISP
RET
CHENGFA1:
MOVA,Y
LCALLBCDH
MOVCHENG_ZANCUN,A
MOVA,Z
LCALLBCDH
MOVB,CHENG_ZANCUN
MULAB
LCALLHBCD
MOVYY,DISPH
MOVY,DISPL
LCALLTODISP
RET
;---------------BCD转十六进制---------------------------------
BCDH:
PUSHPSW
MOVBCDH_ZANCUN,A
SWAPA
ANLA,#0FH
MOVB,#06H
MULAB
MOVB,A
MOVA,BCDH_ZANCUN
CLRC
SUBBA,B
POPPSW
RET
;--------------十六进制转BCD-------------------