基于FPGA的自动售货机设计---第一版
欢迎各位朋友关注“郝旭帅电子设计团队”,本篇为各位朋友介绍基于FPGA的自动售货机设计---第一版。
功能说明:
1. 自动售货机的显示信息为数码管。
2. 前三个数码管显示商品的名字和价格(A 2.0 B2.5 C 3.0)
3. 在未确定状态,可以通过选择商品按键进行商品选择。
4. 选择好商品后,可以按下确认选择按键,此时前三个数码馆开始闪烁。此时选择商品键将无法使用。
5. 当选择完商品后,可以通过按键模拟投入0.5元和1元,钱数显示在最后两个数码管上。
6. 当输入钱数等于商品价格时,钱数显示归0,控制led(leda、ledb、ledc),点亮1秒钟,表示有商品输出,商品从新进入可以选择的状态。
7. 当输入钱数大于商品价格时,钱数显示归0,控制led(leda、ledb、ledc),点亮1秒钟,表示有商品输出,商品从新进入可以选择的状态;控制led2,点亮一秒钟,表示有找零输出。
8. 在输入钱的时候,商品无法切换,且前三个数码管一直闪烁。9. 在选择商品时,无法输入金钱。
使用平台:本次设计应用Altera的平台设计(芯片:EP4CE10F17C8N)。
作者QQ:746833924
说明:本篇设计中不涉及到IP和原语,代码在其他平台依然可以适用;当其他板卡电路不同时,会导致不同的现象出现,如有需要修改代码请联系作者;如需作者使用的板卡,请联系作者;
设计思想如下:
key_ctrl模块负责将外部的按键信号进行消抖,并且产生对应边沿变化时的脉冲;auto_seller_ctrl模块负责根据脉冲信号和设计逻辑产生对应数字逻辑;water_mode_convert模块负责将选择的水和价格译码出来,并且根据是否选择确定,来控制数码管对应的位置是否闪烁;led_ctrl模块是根据外部的脉冲,控制led点亮一秒钟;seven_tube_drive(七段数码管驱动)模块负责将产生的数字逻辑显示到数码管上。
key_ctrl模块设计思想为:按键信号是由外部机械式按键产生,每次按下或者抬起时,会产生一定的抖动。如果直接对其进行边沿检测就会导致多次触发。故而需要设计按键消抖,进而对消抖之后的波形进行边沿检测。消抖原理为:外部按键信号发生改变后,如果能够持续20ms,没有新的改变,就认为此次改变不是抖动,而是真正的按下,然后进行采样即可。
auto_seller_ctrl模块的设计思想:利用状态机设计进行实现。共有八个状态。
localparam STATE_IDLE = 8'b0000_0001; localparam STATE_SEL = 8'b0000_0010; localparam STATE_ZERO_ZERO = 8'b0000_0100; localparam STATE_ZERO_FIVE = 8'b0000_1000; localparam STATE_ONE_ZERO = 8'b0001_0000; localparam STATE_ONE_FIVE = 8'b0010_0000; localparam STATE_TWO_ZERO = 8'b0100_0000; localparam STATE_TWO_FIVE = 8'b1000_0000;
复位结束后,在IDLE状态。之后进入SEL状态,可以通过切换商品按键切换商品的选择。通过按下选择OK键,进入到投递金钱的状态。下面把所有的有可能出现的金钱都做状态设计,根据现有状态和投入的金钱做出对应的动作(输出对应的出货脉冲和找零脉冲、输出输入的钱数)即可。
always @ * begin case (c_state) STATE_IDLE : n_state = STATE_SEL; STATE_SEL : n_state = (flag_ok == 1'b1) ? STATE_ZERO_ZERO : STATE_SEL; STATE_ZERO_ZERO : if (flag_half == 1'b1) n_state = STATE_ZERO_FIVE; else if (flag_one == 1'b1) n_state = STATE_ONE_ZERO; else n_state = STATE_ZERO_ZERO; STATE_ZERO_FIVE : if (flag_half == 1'b1) n_state = STATE_ONE_ZERO; else if (flag_one == 1'b1) n_state = STATE_ONE_FIVE; else n_state = STATE_ZERO_FIVE; STATE_ONE_ZERO : if (flag_half == 1'b1) n_state = STATE_ONE_FIVE; else if (flag_one == 1'b1) if (water_mode == 2'd0) n_state = STATE_IDLE; else n_state = STATE_TWO_ZERO; else n_state = STATE_ONE_ZERO; STATE_ONE_FIVE : if (flag_half == 1'b1) if (water_mode == 2'd0) n_state = STATE_IDLE; else n_state = STATE_TWO_ZERO; else if (flag_one == 1'b1) if (water_mode == 2'd0) n_state = STATE_IDLE; else if (water_mode == 2'd1) n_state = STATE_IDLE; else n_state = STATE_TWO_FIVE; else n_state = STATE_ONE_FIVE; STATE_TWO_ZERO : if (flag_half == 1'b1) if (water_mode == 2'd1) n_state = STATE_IDLE; else n_state = STATE_TWO_FIVE; else if (flag_one == 1'b1) n_state = STATE_IDLE; else n_state = STATE_TWO_ZERO; STATE_TWO_FIVE : if (flag_half == 1'b1) n_state = STATE_IDLE; else if (flag_one == 1'b1) n_state = STATE_IDLE; else n_state = STATE_TWO_FIVE; default : n_state = STATE_IDLE; endcase end
water_mode_convert模块的设计思想为:根据选择的水,解析出对应的种类和价格;当未确定选择时,正常输出水的种类和价格;当确定选择时,让输出在正常输出和息屏输出每0.5s进行切换一次。
always @ (posedge clk) begin if (rst_n == 1'b0) water_mode_bcd_src <= 12'hA20; else case (water_mode) 2'd0 : water_mode_bcd_src <= 12'hA20; 2'd1 : water_mode_bcd_src <= 12'hB25; 2'd2 : water_mode_bcd_src <= 12'hC30; default : water_mode_bcd_src <= 12'hA20; endcase end
led_ctrl模块的设计思想为:根据外部输入的脉冲,控制对应的led点亮一秒钟即可。
七段数码管为普通六位一体的共阳极数码,采用动态驱动的方式,在此不再赘述。
下板时,按下复位,此项设计开始运行。
讲解和演示视频链接如下:
https://www.bilibili.com/video/BV1Tr42177wX/?spm_id_from=333.999.0.0&vd_source=b5405faeab8632f02533bcbfc5e52e55
本设计所有内容(设计代码、设计工程)链接为:
链接:https://pan.baidu.com/s/1JfUSrUaIRrb5-4aEg7vfeA
提取码:ojzq
本篇内容中有部分资源来源于网络,如有侵权,请联系作者。
如果您觉得本公众号还不错的话,可以推给身边的朋友们,感谢并祝好!