简易加油机控制系统.docx
- 文档编号:24876149
- 上传时间:2023-06-02
- 格式:DOCX
- 页数:20
- 大小:154.95KB
简易加油机控制系统.docx
《简易加油机控制系统.docx》由会员分享,可在线阅读,更多相关《简易加油机控制系统.docx(20页珍藏版)》请在冰豆网上搜索。
简易加油机控制系统
1、设计课题的任务要求
设计并实现一个简易加油机控制系统,能够完成定值加油、加油至油箱满等功能,并显示所加油量和钱数。
基本要求:
1、油价固定设为5元/升。
2、用2个按键(btn7、btn6)分别表示一百元、十元,用btn5做加油开始键,用btn0做系统复位键。
用3个数码管(disp2、disp1、disp0)显示钱数,以元为单位,上限990元;用数码管(disp5、disp4、disp3)显示加油量,精确到0.1升,最大显示99.9升。
3、定值加油时,先输入钱币,数码管同时显示钱数,按加油键,开始加油。
加油过程中,钱数及加油量的显示从零开始递增,直到钱数到达预定值。
并用发光二极管表示购买成功。
加油过程中,所有按键按下无效。
4、加油至油箱满:
在钱币数为零的状态下,按加油键,钱数及加油量的显示从零开始递增,直到油箱加满。
自行设计一个随机数发生器,控制加油量自动停止在30升至50升之间,精确到0.1升。
加油过程中,所有按键按下无效。
5、复位键(btn0)按下后,系统复位,此时数码管显示钱币数及加油量均为零。
2、系统设计(包括设计思路、总体框图、分块设计)
1.设计思路:
这次设计将整个程序分为控制计数模块,按键输入模块,数码管现实模块,防抖模块以及随机数产生模块。
其中控制计数模块为系统核心,识别分析所有按键输入信号并给出控制信号;按键输入模块用于消除按键时机械抖动时可能产生的错误输入信号;数码管现实模块采用分时显示的方法让六个数码管分别显示油价与油量;随机数产生模块用于产生一个一定范围的随机数。
2.总体框图:
3.分块设计
控制和计费模块:
采用多重if语句判断实现逻辑功能。
当时钟上升沿来临,若清零键被按下(btn0=‘1’)则清零变量,完成判断;若清零键非零则判断是否按下加油键(按下则m=‘1’),若按下则
按键防抖模块:
按键有效的判断条件是按键是否按下一定时间(其中btn7,btn6是按下150ms后有效,btn5,btn0是按下100ms后有效)。
一般按键抖动时间在5ms到10ms之间,故该判断条件能有效防抖。
显示模块:
该模块需同时显示油价和油量两个数据。
本来需要两类信号来分别储存油量数据和油价数据。
但考虑到油价与油量有一个固定的函数关系(油量=油价/5),可以将油量类的信号省去,只储存油价类的信号。
在显示时,只需要把油价信号进行一个函数变换即可显示油量。
这样做简化了信号个数,也方便对数据进行操作。
随机数产生模块:
实验要求为产生一个30升到50升的随机加油量,对应到油价就是一个150到250的数。
故随机数模块依据按下加油键的时间为随机变量产生一个150到250的随机数送到油价信号。
3、仿真波形及波形分析
由于整个程序功能复杂,故做分模块仿真。
1.分频模块:
采用clk_100为例子进行仿真。
鉴于50MHz是一个很大的频率,基础时钟的频率在仿真中设置为10kHz,分频系数为100.
2.防抖模块:
鉴于4个按键都采用相同的防抖手段,故采用加油键(btn5)作例子。
可以看见前面两个小的抖动m值都未发生变化,直到加油键被按下超过100毫秒时m值才变为1,即实现了防抖功能。
3.显示模块:
啊dgtc控制某个数码管亮,可以看见它在六个时钟周期内循环变化;dgt控制显示数码显示数字,可以看见在一个时钟周期(红色椭圆内)其稳定为一个值,输入数码管之后就稳定为一个数字;而point为油价小数点,它只在某个特定的数码管后亮起,在仿真上可以看见它每隔六个时钟周期值变为1。
4.控制模块:
初始输入油价状态:
Btn7与btn6两个键分别控制油价的百位与十位,可以看见按下btn6键后油价十位(price2)变为1,按下btn7键后油价百位变为1(price2),再按下btn6键后油价十位(price2)变为2.
输入油价为零的加油过程:
直接按下btn5键后可以看见目标油价(goalpri2、1、0)被直接赋给随机数值(在150到250之间的一个数),显示油价从零开始递增(price2、1、0)。
已输入油价加油过程:
输入油价10元(即只按btn6键一下),再按下加油键(btn5),可以看见目标油价被赋值为10元(goalpri1被赋值为1,goalpri2、goalpri0),显示油价(price2、1、0)从零开始递增,每0.1秒增加一次。
增加到目标油价后显示油价不再变化,同时led值变为‘1’,即加油完成后led灯亮起。
清零过程:
在仿真
后按下清零键(btn0),显示油价与led标志都被清零,即加油指示灯、油价显示都回到初始状态。
4、源程序(要有注释)
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_unsigned.all;
useIEEE.STD_LOGIC_ARITH.ALL;
entityoilmis
port(
clk,btn7,btn6,btn5,btn0:
instd_logic;--按键输入,btn7与btn6控制油价百位、十位变化,btn5为加油键,btn0为重置键
dgt:
outstd_logic_vector(6downto0);--输出,控制数码管显示数字
dgtc:
outstd_logic_vector(5downto0);--输出,分频控制某个数码管亮
point,led:
outstd_logic);--输出,控制小数点
endoilm;
architectureaofoilmis
signalclk_100,clk_1k,clk_10:
std_logic;--分频后频率
signalk,fuelf,zerof,m:
std_logic;--状态标志量,m=‘1’表示加油键按下,fuelf=‘1’表示加油过程中,zerof=‘1’表示输入油价为零,k由于控制改变加油最终油价
signalspri2,pri2,vpri2:
integerrange0to4;--spri2、1、0储存按键后的油价,pri2、1、0储存显示的油价,vpri2、1、0储存加油最终油价
signalspri1,pri1,spri0,pri0,vpri1,vpri0,cap2,cap1,cap0:
integerrange0to9;--cap2、1、0用于储存显示油价pri2、1、0对应的油量值
signalcnt00:
integerrange0to249999;
signalcnt01:
integerrange0to24999;
signalcnt02:
integerrange0to2499999;
signalcnt17,cnt16:
integerrange0to14;
signalcnt15,cnt10:
integerrange0to9;
signalcnt2:
integerrange0to5;
signalcnt3:
integerrange150to250;
signaltmp32:
integerrange0to2;
signaltmp31,tmp30:
integerrange0to9;
begin
zf:
process(spri2,spri1)--时刻判断输入油价是否为零
begin
if(spri2+spri1)>0then
zerof<='0';
else
zerof<='1';
endif;
endprocesszf;
control:
process(spri2,spri1,spri0,m,clk_10,btn0)--控制模块
begin
ifclk_10'eventandclk_10='1'then
ifbtn0='1'andfuelf/='1'then
k<='0';led<='0';
else
ifm='0'then
pri2<=spri2;pri1<=spri1;pri0<=spri0;
else
ifzerof='0'andk='0'then
fuelf<='1';
vpri2<=spri2;vpri1<=spri1;vpri0<=spri0;
pri2<=0;pri1<=0;pri0<=0;k<='1';
elsifzerof='1'andk='0'then
fuelf<='1';
vpri2<=tmp32;vpri1<=tmp31;vpri0<=tmp30;
pri2<=0;pri1<=0;pri0<=0;k<='1';
endif;
endif;
if(m='1')and(fuelf='1')then
if(pri2*100+pri1*10+pri0)<(vpri2*100+vpri1*10+vpri0)then
if(pri0=9)then
pri0<=0;
if(pri1=9)then
pri1<=0;
pri2<=pri2+1;
else
pri1<=pri1+1;
endif;
else
pri0<=pri0+1;
endif;
else
fuelf<='0';
led<='1';
endif;
endif;
endif;
endif;
endprocess;
frequency:
process(clk)--分频模块
begin
if(clk'eventandclk='1')then
ifcnt00=249999thencnt00<=0;clk_100<=notclk_100;
elsecnt00<=cnt00+1;
endif;
endif;
if(clk'eventandclk='1')then
ifcnt01=24999thencnt01<=0;clk_1k<=notclk_1k;
elsecnt01<=cnt01+1;
endif;
endif;
if(clk'eventandclk='1')then
ifcnt02=2499999thencnt02<=0;clk_10<=notclk_10;
elsecnt02<=cnt02+1;
endif;
endif;
endprocess;
anti_shake:
process(clk_100,btn7,btn6,btn5,btn0)--防抖模块
begin
ifclk_100'eventandclk_100='1'then
ifbtn7='1'then
ifcnt17=14then
cnt17<=0;
ifspri2=4then
spri2<=0;
else
spri2<=spri2+1;
endif;
else
cnt17<=cnt17+1;
endif;
endif;
ifbtn6='1'then
ifcnt16=14then
cnt16<=0;
ifspri1=9then
spri1<=0;
else
spri1<=spri1+1;
endif;
else
cnt16<=cnt16+1;
endif;
endif;
ifbtn5='1'then
ifcnt15=9then
cnt15<=0;
m<='1';
else
cnt15<=cnt15+1;
endif;
endif;
ifbtn0='1'andfuelf/='1'then
ifcnt10=9then
cnt10<=0;
m<='0';spri2<=0;spri1<=0;
else
cnt10<=cnt10+1;
endif;
endif;
endif;
spri0<=0;
endprocessanti_shake;
dis1:
process(clk_1k,pri2,pri1,pri0)--显示模块一,完成油价油量对应运算
begin
if(clk_1k'eventandclk_1k='1')then
if(pri0*2>=10)then
cap0<=(pri0*2rem10);
if((pri1*2+1)>=10)then
cap1<=(pri1*2+1)rem10;
cap2<=pri2*2+1;
else
cap1<=pri1*2+1;
cap2<=pri2*2;
endif;
else
cap0<=pri0*2;
if(pri1*2>=10)then
cap1<=pri1*2rem10;
cap2<=pri2*2+1;
else
cap1<=pri1*2;
cap2<=pri2*2;
endif;
endif;
endif;
endprocessdis1;
dis2:
process(clk_1k,pri2,pri1,pri0,cap2,cap1,cap0)--显示模块二,六个数码管显示
begin
if(clk_1k'eventandclk_1k='1')then
ifcnt2=5then
cnt2<=0;
else
cnt2<=cnt2+1;
endif;
endif;
casecnt2is
when5=>dgtc<="011111";
when4=>dgtc<="101111";
when3=>dgtc<="110111";
when2=>dgtc<="111011";
when1=>dgtc<="111101";
whenothers=>dgtc<="111110";
endcase;
casecnt2is
when2=>casepri2is
WHEN0=>dgt<="0111111";
WHEN1=>dgt<="0000110";
WHEN2=>dgt<="1011011";
WHEN3=>dgt<="1001111";
WHENothers=>dgt<="1100110";
endcase;
point<='0';
when1=>casepri1is
WHEN0=>dgt<="0111111";
WHEN1=>dgt<="0000110";
WHEN2=>dgt<="1011011";
WHEN3=>dgt<="1001111";
WHEN4=>dgt<="1100110";
WHEN5=>dgt<="1101101";
WHEN6=>dgt<="1111101";
WHEN7=>dgt<="0100111";
WHEN8=>dgt<="1111111";
WHENothers=>dgt<="1101111";
endcase;
point<='0';
when0=>casepri0is
WHEN0=>dgt<="0111111";
WHEN1=>dgt<="0000110";
WHEN2=>dgt<="1011011";
WHEN3=>dgt<="1001111";
WHEN4=>dgt<="1100110";
WHEN5=>dgt<="1101101";
WHEN6=>dgt<="1111101";
WHEN7=>dgt<="0100111";
WHEN8=>dgt<="1111111";
WHENothers=>dgt<="1101111";
endcase;
point<='0';
when5=>casecap2is
WHEN0=>dgt<="0111111";
WHEN1=>dgt<="0000110";
WHEN2=>dgt<="1011011";
WHEN3=>dgt<="1001111";
WHEN4=>dgt<="1100110";
WHEN5=>dgt<="1101101";
WHEN6=>dgt<="1111101";
WHEN7=>dgt<="0100111";
WHEN8=>dgt<="1111111";
WHENothers=>dgt<="1101111";
endcase;
point<='0';
when4=>casecap1is
WHEN0=>dgt<="0111111";
WHEN1=>dgt<="0000110";
WHEN2=>dgt<="1011011";
WHEN3=>dgt<="1001111";
WHEN4=>dgt<="1100110";
WHEN5=>dgt<="1101101";
WHEN6=>dgt<="1111101";
WHEN7=>dgt<="0100111";
WHEN8=>dgt<="1111111";
WHENothers=>dgt<="1101111";
endcase;
point<='1';
whenothers=>casecap0is
WHEN0=>dgt<="0111111";
WHEN1=>dgt<="0000110";
WHEN2=>dgt<="1011011";
WHEN3=>dgt<="1001111";
WHEN4=>dgt<="1100110";
WHEN5=>dgt<="1101101";
WHEN6=>dgt<="1111101";
WHEN7=>dgt<="0100111";
WHEN8=>dgt<="1111111";
WHENothers=>dgt<="1101111";
endcase;
point<='0';
endcase;
endprocessdis2;
rand1:
process(clk)--随机数产生模块
begin
ifclk'eventandclk='1'then
ifcnt3=250then
cnt3<=150;
else
cnt3<=cnt3+1;
endif;
endif;
endprocessrand1;
tmp32<=cnt3/100;
tmp31<=(cnt3rem100)/10;
tmp30<=cnt3rem10;
end;
5、功能说明及资源利用情况
功能说明:
初始状态按下btn7、btn6两个键会分别改变油价百位和十位(按一次就加1)。
当按下加油键(btn5),状态量m改变,进入加油状态,以0.1秒为间隔加油,每次油价加1元。
按下加油键之后会根据之前输入油价是否为零(zerof为0则输入油价不为零),若输入油价为零则给加油目标油价赋一个150到250之间的随机数,若不为零则直接把输入油价赋给加油目标油价。
清零键在初始状态及加油完成后都能使用,但加油过程中清零键无效。
资源利用情况:
6、故障及解决方法
在写程序中遇到的问题是多时钟沿问题。
开始的时候设置的按键防抖是输入信号是按键产生一个上升沿后才给油价加1,结果在控制程序中和时钟clk_10的上升沿产生了冲突,导致程序无法通过。
后来修改了防抖程序,只需按键按下150毫秒后油价就加1,避开了时钟沿,程序编译通过。
第一次下载后初始状态可以输入加油,但按下加油键后无法加油,油价显示只有个位在跳动,十位和百位都为零,和输入油价不符。
仔细检查代码后发现控制模块出错。
原来按下加油键后每次进行判断都会重新给显示油价清零,重新给目标油价赋值。
给控制模块加入标志量k后保证显示油价清零只进行一次,目标油价赋值只进行一次,程序可以正常执行功能。
七、总结与可行优化
这次数电实验进行的颇为周折。
对硬件编程语言不熟悉的我把c语言的那些编程想法拿到vhdl编程里边来,导致程序出现诸多错误,无法通过编译。
比如while语句,在c语言中很常用,但是放到vhld中便没有硬件实现的基础,导致编译无法通过,这也告诉我硬件编程要考虑实际,不能天马行空,想怎么写就怎么写。
可行优化:
这次控制程序写得比较low,只是多重if语句嵌套。
相信使用状态机的话控制程序看着会有条理许多。
(使用三个状态s0、s1、s2。
s0为初始状态,负责输入油价,当按下加油键的时候切断到状态s1;s1为赋值状态,根据输入油价是否为零为加油时的目标油价赋值,若为零为目标油价赋随机值,若非零则将该值赋给目标油价,同时进入状态s2;s2为加油状态,内有一个if判断语句,当显示油价未达到目标油价时就不停给显示油价加1,达到后就停住。
无论在哪个状态按下清零键后都回到状态s0,显示油价清零。
)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 简易 加油机 控制系统