易拉罐售货机控制器1303030335.docx
《易拉罐售货机控制器1303030335.docx》由会员分享,可在线阅读,更多相关《易拉罐售货机控制器1303030335.docx(15页珍藏版)》请在冰豆网上搜索。
易拉罐售货机控制器1303030335
目录
1设计目的1
2设计要求和任务1
3总体设计思路及原理描述2
4分层次方案设计及代码描述3
4.1主控模块代码3
4.2分频模块6
4.3二进制译码模块7
4.4BCD码译码模块8
4.5系统模块连接9
5各模块的时序仿真图10
5.1主控模块仿真10
5.2二进制译码仿真11
5.3BCD码译码仿真11
6总结12
7参考文献13
1设计目的
易拉罐售货机是能根据投入的钱币或硬币自动给出客人所选货物的机器,它是一种常用的商业自动化设备,它不受时间,地点的限制,可以节省人力,简化交易。
自动售货机在当今被普遍地应用在各大现代化都市的街道及便利店中,正逐渐地成为商业自动化的代表性设备。
它能够在无人操作的情况下根据程序自动地销售商品。
而且进入21世纪时,自动售货机也将进一步向节省资源和能源以及高功能化的方向发展。
从自动售货机的发展趋势来看,大量生产,大量消费以及消费模式和销售环境的变化,要求出现新的流通渠道,而相对的超市,百货购物中心等新的流通渠道的产生,人工费用也不断上升,在加上场地的局限性和购物的便利性等这些因素的制约,无人自动售货机作为一种必须的机器也就有了其相当可观的前景。
2设计要求和任务
易拉罐售货机要求:
1.能识别纸币、硬币;
2.能对五种易拉罐商品进行选择;
3.能选择商品的数量;
4.能为客人找钱。
顾客选择商品后,向售货机投入纸币或硬币,判断投币额是否足够,若投币额足够则根据顾客要求自动售货,若投币不够三秒后退出。
顾客通过按键选择商品后,有数码管显示该商品价格。
顾客投币过程中,数码管显示投币额。
当顾客买完商品后,还剩余额,售货机自动为顾客找钱,数码管将显示余额数。
3总体设计思路及原理描述
通过VHDL的状态机以及CASE语句进行编程,用6个状态分别表示商品选择、投币额累加、找零售货以及总销售额的累加等功能。
程序编起来需要对整体有较好的理解,各个状态的切换与跳转要思路清晰,不过在仿真过程中运行成功,且程序分为多个状态,看起来比较清晰。
图3.1程序设计图
该系统主要由分频、控制、译码和显示四个部分构成。
当有人需要购买物品时,首先选择所要购买的物品,这时,前两个数码显示管选中商品的单价。
之后顾客投币进行购买,后两个数码显示管显示总共投入了多少钱。
当按下确认键时,将在系统内部进行比较,比较单价和所投入的金额。
若投币金额大于或等于该商品单价时,系统显示成功售出该商品并进行找零,即投币金额与商品单价的差值,然后将售出总额加上这次的物品单价。
若投币金额小于该商品单价时,系统显示购买失败,在几秒钟的延迟后退换投币金额,售出总额不变。
无论哪种情况,完成后回到初始状态。
图3.2程序流程图
4分层次方案设计及代码描述
4.1主控模块代码
Libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitysellingmachineis
port(clk:
instd_logic;
set:
instd_logic;--复位键
coin5:
instd_logic;--投入五角和一元硬币
coin10:
instd_logic;
papermoney50:
instd_logic;--投入五元和十元纸币
papermoney100:
instd_logic;
water:
instd_logic;--五种商品
milk:
instd_logic;
juice:
instd_logic;
cola:
instd_logic;
coffee:
instd_logic;
paid:
outstd_logic_vector(6downto0);--投入的金额
needed:
outstd_logic_vector(6downto0);--不足时还差的金额
success:
outstd_logic;--售货成功
failure:
outstd_logic;--售货失败
showchange:
outstd_logic;--找钱
change:
outstd_logic_vector(6downto0);--退还的金额
sum:
bufferstd_logic_vector(6downto0));--售货机总的金额
endsellingmachine;
architecturebehavofsellingmachineis--结构体
typestate_typeis(qa,qb,qc,qg,qd,qf);--定义七个状态(结构体内定义的信号为内部信号,只在结构体内部起作用)
signalcurrent_state:
state_type:
=qa;
signalq:
integerrange0to100;--q为延时信号
begin
process(clk)--括号内为敏感信号
variablepaidtemp:
std_logic_vector(6downto0);--进程内部变量
variableneededtemp:
std_logic_vector(6downto0);
variablebackmoney:
std_logic_vector(6downto0);
variablepricetemp:
std_logic_vector(6downto0);
variablesumtemp:
std_logic_vector(6downto0);
begin
ifclk'eventandclk='1'then--若上升沿到来时就进行以下判断,该进入哪个状态
casecurrent_stateis
whenqa=>paidtemp:
="0000000";neededtemp:
="0000000";---------进入初态
backmoney:
="0000000";pricetemp:
="0000000";sumtemp:
="0000000";q<=0;
showchange<='0';change<="0000000";paid<="0000000";
needed<="0000000";failure<='0';success<='0';
ifwater='1'ormilk='1'orjuice='1'orcola='1'orcoffee='1'then--有选择商品的信号
ifwater='1'thenpricetemp:
=pricetemp+15;--判断选择了哪一商品
elsifmilk='1'thenpricetemp:
=pricetemp+20;
elsifjuice='1'thenpricetemp:
=pricetemp+25;
elsifcola='1'thenpricetemp:
=pricetemp+30;
elsepricetemp:
=pricetemp+35;
endif;
neededtemp:
=pricetemp;--选择商品后所需要的金额
needed<=neededtemp;
paid<=paidtemp;
current_state<=qb;
endif;
ifset='1'thenpaid<=sum;
endif;
whenqb=>ifcoin5='0'orcoin10='0'then--投币状态
ifcoin5='0'thenpaidtemp:
=paidtemp+5;--当有投币动作时
elsepaidtemp:
=paidtemp+10;
endif;
neededtemp:
=pricetemp-paidtemp;backmoney:
="0000000";--不够则进入继续投币状态qc
paid<=paidtemp;
needed<=neededtemp;
current_state<=qc;q<=0;
elsifpapermoney50='0'orpapermoney100='0'then
ifpapermoney50='0'thenpaidtemp:
=paidtemp+50;
elsepaidtemp:
=paidtemp+100;
endif;
ifpaidtemp>=pricetempthenneededtemp:
="0000000";--若继续投币足够,则进入出货找零状态qd
backmoney:
=paidtemp-pricetemp;--若成功则累计
paid<=paidtemp;
needed<=neededtemp;
q<=0;
current_state<=qd;
endif;
endif;
ifcoin5/='0'andcoin10/='0'andpapermoney50/='0'andpapermoney100/='0'then--若无投币动作则进入延时状态qf
ifq<3thenq<=q+1;
elsecurrent_state<=qf;
endif;
elseq<=0;
endif;
whenqc=>ifcoin5='0'orcoin10='0'then--若又有投币动作,则累计
ifcoin5='0'thenpaidtemp:
=paidtemp+5;
elsepaidtemp:
=paidtemp+10;
endif;
ifpaidtemp>=pricetempthenneededtemp:
="0000000";--若继续投币足够,则进入出货找零状态qd
backmoney:
=paidtemp-pricetemp;--若成功则累计
paid<=paidtemp;
needed<=neededtemp;
q<=0;
current_state<=qd;
elseneededtemp:
=pricetemp-paidtemp;--若不够则继续执行继续投币状态qc
backmoney:
="0000000";
paid<=paidtemp;
needed<=neededtemp;
current_state<=qc;
endif;
endif;
ifcoin5/='0'andcoin10/='0'andpapermoney50/='0'andpapermoney100/='0'then--若在继续投币状态无投币信号则计时准备进入还币状态qg
ifq<3thenq<=q+1;
elsecurrent_state<=qg;
endif;
elseq<=0;
endif;
whenqd=>ifq<1thensuccess<='1';q<=q+1;
ifbackmoney>"0000000"thenshowchange<='1';
change<=backmoney;--若需找钱则找钱灯亮并将钱返还
elseshowchange<='0';
endif;
sumtemp:
=pricetemp;
sum<=sum+sumtemp;
elsecurrent_state<=qa;
endif;
whenqf=>ifq<4thenq<=q+1;
elsecurrent_state<=qa;q<=0;
endif;
whenqg=>failure<='1';--若钱不够或超时未付钱,且再三秒延时后还没有投币则失败
showchange<='1';change<=paidtemp;
current_state<=qf;q<=0;
whenothers=>current_state<=qa;
endcase;
endif;
endprocess;
endbehav;
4.2分频模块
该分频模块的频数为50MHZ,将50HZ转换成50MHZ。
其程序代码如下:
libraryieee;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
useieee.std_logic_1164.all;
entityclkdivis
generic(temp:
integer:
=25000000);--类属参数说明语句
port(clk:
instd_logic;
clk_div:
outstd_logic);
endentityclkdiv;
architectureclk_divofclkdivis
constantperiod:
integer:
=50000000;--常数定义,分频数
signalcount:
integerrange0toperiod-1;--信号定义,计数作用
begin
process(clk)--进程,由clk这个信号启
begin
if(clk'eventandclk='1')then
if(countclk_div<='0';
count<=count+1;
elsif(countclk_div<='1';
count<=count+1;
else
count<=0;
endif;
endif;
endprocess;
endclk_div;
4.3二进制译码模块
该二进制译码模块有一个输入端和两个输出端,输入端b是一个7位的二进制数,输出端bcd0、bcd1,是两个4位的BCD码。
该模块的主要功能是实现将主控模块输出的二进制数(paid、price、change)转换成BCD码,以便输出到七段显示数码器上而显示出来。
该模块的原理是将一个7位的二进制数转换成2个4位的BCD码,分别为低4位和高4位。
该模块的程序代码如下:
Libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitycode1is
port(b:
instd_logic_vector(6downto0);
bcd0:
outstd_logic_vector(3downto0);
bcd1:
outstd_logic_vector(3downto0));
endcode1;
architectureoneofcode1is
begin
process(b)
begin
casebis
when"0000000"=>bcd0<="0000";bcd1<="0000";---------0
when"0000101"=>bcd0<="0101";bcd1<="0000";---------5
when"0001010"=>bcd0<="0000";bcd1<="0001";--------10
when"0001111"=>bcd0<="0101";bcd1<="0001";--------15
when"0010100"=>bcd0<="0000";bcd1<="0010";--------20
when"0011001"=>bcd0<="0101";bcd1<="0010";--------25
when"0011110"=>bcd0<="0000";bcd1<="0011";--------30
when"0100011"=>bcd0<="0101";bcd1<="0011";--------35
when"0101000"=>bcd0<="0000";bcd1<="0100";--------40
when"0101101"=>bcd0<="0101";bcd1<="0100";--------45
when"0110010"=>bcd0<="0000";bcd1<="0101";--------50
when"0110111"=>bcd0<="0101";bcd1<="0101";--------55
when"0111100"=>bcd0<="0000";bcd1<="0110";--------60
when"1000001"=>bcd0<="0101";bcd1<="0110";--------65
when"1000110"=>bcd0<="0000";bcd1<="0111";--------70
when"1001011"=>bcd0<="0101";bcd1<="0111";--------75
when"1010000"=>bcd0<="0000";bcd1<="1000";--------80
when"1010101"=>bcd0<="0111";bcd1<="1000";--------85
whenothers=>null;
endcase;
endprocess;
endone;
4.4BCD码译码模块
该模块有一个输入端和一个输出端。
输入端d是一个4位的BCD码,输出端q是一个7位数,输出连接到一个LED数码管显示出来。
该模块代码如下:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
entitycode2is
port(d:
instd_logic_vector(3downto0);
q:
outstd_logic_vector(6downto0));
endcode2;
architectureoneofcode2is
begin
process(d)
begin
casedis
when"0000"=>q<="0000001";
when"0001"=>q<="1001111";
when"0010"=>q<="0010010";
when"0011"=>q<="0000110";
when"0100"=>q<="1001100";
when"0101"=>q<="0100100";
when"0110"=>q<="0100000";
when"0111"=>q<="0001111";
when"1000"=>q<="0000000";
when"1001"=>q<="0001100";
whenothers=>q<="1111111";
endcase;
endprocess;
endone;
4.5系统模块连接
图4.1系统模块图
由图4.1中可以看到,八个代表不同意思的输入端口接入到主控模块上,从主控模块输出的两个端口分别连接在两个二进制译码器上,再将二进制译码器的输出端连接到数码显示管上,用来显示商品单价、投币金额和售出总额。
其余的五个输出端口分别表示购买成功、失败、找零、找零金额。
其中的找零金额因数码显示管数量有限不能显示,只能进行仿真。
5各模块的时序仿真图
5.1主控模块仿真
使用硬币
图5.1使用硬币仿真图
当顾客选择3.5元的coffee,投币4元时,程序仿真图如图5.1所示。
数码管前两位显示商品单价3.5元,后两位数码显示管将显示投币金额4元,并显示购买成功,找零金额为0元。
使用纸币
图5.2使用纸币仿真图
当顾客选择2.5元的juice,并投纸币5元时,程序仿真图如图5.2所示。
数码管前两位显示商品单价2.5元,后两位数码管显示投币金额10元,并显示购买成功,找零金额为7.5元。
5.2二进制译码仿真
图5.3二进制译码仿真图
当七位二进制数为1010101时,代表十进制数85。
此时第一个数码显示管现实的数字为8,第二个数码显示管显示的数字为5。
表明仿真正确。
5.3BCD码译码仿真
图5.3BCD译码仿真图
当BCD码输入为1001时,数码显示管表示的二进制数为0000100,代表十进制数9。
有仿真图5.3可知,当d为1001时,q为0000100,表明仿真成功。
6总结
这次课设相对之前的课设,难度有所增加,而且EDA的理论课是之前学的,有很多知识忘了,在做课设时总会遇到一些基础的东西模棱两可,不得不翻阅书籍,加上之前我们没有做过硬件方面的东西,做起来有些困难,但也让我学到了很多。
在这段时间里,我学到了很多知识也有很多感受。
当然在做的过程中也遇到过很多的麻烦,在调试的时候会有一些错误,自己很难改正,只得求助老师,最后得以解决。
这次毕业设计使我开始了自主的学习和试验,查看相关的资料和书籍,让自己头脑中模糊的概念逐渐清晰,使自己非常稚嫩作品一步步完善起来,每一次改进都是我学习的收获,每一次的成功都会让我兴奋好一段时间。
和老师的沟通交流更使我对设计有了新的认识也对自己提出了新的要求。
课题设计过程中我不怕失败,在失败中总结经验,为成功积累素材;学着自我超越,敢于尝试,在尝试中进步,这对我能力的提高大有好处。
设计中有太多的不懂和陌生,但是我会多看、多想、多问、多学。
非常感谢学校能给我们提供这样的一个可以自己动脑、动手进行设计的机会,同时也大大加强了同学之间的沟通,以及学生与老师之间的交流,我们理论知识与实际结合的平台,更是一个放飞自我的平台。
通过此次课程设计,我加深了对VHDL语言的了解,不仅学会用Quartus编程作图,更学会用Quartus软件,而且我们还学会将程序下载到开发板上运行操作,并深刻认识到同学之间相互协作的重要性,同时也更了解到老师们都是很好沟通的,谢谢老师给予的帮助!
这次课程设计真的是让人收获很多。
总之,这次课程设计让我觉得受益匪浅。
7参考文献
[1]徐志军,王金明等.EDA技术与VHDL设计.北京:
电子工业出版社,2009
[2]潘松,黄继业.EDA技术实用教程.北京:
科学出版社,2009
[3]周润景.基于QuartusII的FPGA/CPLD数字系统设计实例.北京:
电子工业出版社,2010
[4]郑燕.基于VHDL与QuartusⅡ软件的可编程逻辑器件应用与开发.北京:
国防工业出版社,2011
[5]李青.EDA技术在电子线路实训教学中的运用,2011