Fpga设计 自动售货机 Verilog语言,具有真正投币功能,具有远程遥控功能,具有商品选择功能等。 提供完整的代码,仿真,实物。
这年头搞数电实验,不整点硬核的真对不起那些吃灰的开发板。最近用Verilog搓了个能投真硬币的自动售货机,顺带实现了远程遥控功能。直接上干货,咱们边看代码边聊门道。
硬币检测的黑科技
投币模块用了红外对射传感器阵列,不同硬币遮挡时间不同。代码里用状态机捕捉下降沿:
always @(posedge clk) begin case(coin_state) IDLE: begin if(!coin_sensor) coin_state <= DETECTING; end DETECTING: begin if(coin_counter > 20_000_000) begin // 1秒超时 coin_value <= (coin_width > 10) ? 5 : 1; // 根据遮挡宽度判断面值 total_money <= total_money + coin_value; coin_state <= IDLE; end coin_counter <= coin_counter + 1; end endcase end这段代码的精髓在于用时钟周期数测量硬币通过时间。实战中发现1元硬币直径24mm,通过速度约0.5m/s,遮挡时间48ms左右,对应代码里的阈值参数需要根据实际传感器间距调整。
商品选择与库存管理
商品选择用了4x4矩阵键盘,库存存在Block RAM里。核心逻辑在这:
reg [7:0] stock[0:3]; // 4种商品库存 always @(posedge key_pressed) begin case(key_code) 4'h1: if(stock[0] >0 && total_money >= price[0]) begin stock[0] <= stock[0] -1; total_money <= total_money - price[0]; end // 其他商品类似处理 endcase end重点在价格比较和库存递减的原子操作,必须确保这两个动作在一个时钟周期完成,否则可能出现"买了东西钱没扣"的bug。实测用非阻塞赋值刚好满足时序要求。
远程遥控的骚操作
通过ESP32转接UART协议,接收手机控制指令。协议设计简单粗暴:
| 字节1 | 字节2 | 字节3 |
|---|---|---|
| 0xA5 | 指令 | 数据 |
补货指令处理代码:
always @(posedge uart_rx_done) begin if(rx_buf[0] == 8'hA5) begin case(rx_buf[1]) 8'h01: stock[rx_buf[2][1:0]] <= rx_buf[2][7:2]; // 补货 8'h02: price[rx_buf[2][1:0]] <= rx_buf[2][7:2]; // 调价 endcase end end调试时发现UART波特率必须和FPGA时钟严格匹配,115200波特率对应每bit约8.68us,用50MHz时钟需要分频434次,实测误差必须小于3%才能稳定通信。
实物调试翻车现场
第一次上电时数码管疯狂乱闪,查代码发现金额显示模块的BCD转换没做时钟同步。改完又遇到硬币卡壳,最后用砂纸打磨传感器支架解决。远程控制最坑爹的是电磁干扰,后来给杜邦线套磁环才稳定。
Fpga设计 自动售货机 Verilog语言,具有真正投币功能,具有远程遥控功能,具有商品选择功能等。 提供完整的代码,仿真,实物。
完整工程已扔GitHub(假装有链接),下期可能加个人脸识别扣款功能——前提是老板别发现我拿公司开发板摸鱼。各位要是复现时遇到玄学问题,记住三大法宝:重启、换线、骂立决。