名称:超声测距显示与蜂鸣报警的设计Verilog代码Quartus MINI_FPGA 开发板
软件:QuartusII
语言:Verilog
代码功能
该工程实现超声测距的三种输出形态:1)测得的距离在LCD屏上显示;2)同一距离值在数码管上动态显示;3)当距离低于阈值(默认100mm)时启动蜂鸣器报警。系统对回波信号做上升沿检测,统计两次上升沿之间的主时钟计数,并对多次测量做平均与线性校准后输出更稳定的距离结果。
FPGA代码Verilog/VHDL代码资源下载:www.hdlcode.com
本代码已在MINI_FPGA 开发板验证,MINI_FPGA 开发板如下,其他开发板可以修改管脚适配:
MINI_FPGA 开发板.png
演示视频:
设计文档:
代码实现思路
测距部分采用状态机:等待起始沿后开始计数,等待结束沿后锁存Time_Count;为了降低抖动,将16次测量结果累加后取平均,再用线性模型k、b对结果做校准(代码中以定点放大倍数实现,最终右移恢复实际距离)。显示部分把距离值先转换为BCD码,再交由数码管扫描模块输出;LCD部分通过封装好的FPGA_LCD与SPI发送模块,在初始化完成后按指定坐标绘制字符/数字。报警部分则用简单的分频方波作为蜂鸣器驱动,在距离小于阈值时使能。
代码结构
顶层Main模块集成测距、数码管显示、蜂鸣器与LCD显示:前端用同步寄存器把异步回波信号同步到主时钟域并做边沿检测;中间用状态机与计数器计算平均后的距离并转换为BCD;后端分别连接Digitron_TimeDisplay_module进行数码管动态显示,连接FPGA_LCD完成LCD初始化与图文显示,连接beep_ctrl实现距离阈值报警。整体结构从“采样→计算→显示/告警”清晰分层。
文件/模块一览
radar_LCD_newDigitron_TimeDisplay_module.v:Digitron_TimeDisplay_module
radar_LCD_newFPGA_LCD.v:FPGA_LCD
radar_LCD_newMain.v:Main
radar_LCD_newSPI_TX.v:SPI_TX
radar_LCD_newbeep_ctrl.v:beep_ctrl
radar_LCD_newbinary2bcd.v:binary2bcd
radar_LCD_newblock_rom.v:block_rom
radar_LCD_newlcd_funcmod.v:lcd_funcmod
部分代码
radar_LCD_newMain.v
module Main( input Main_CLK, input RSTn, input [1:0]Radar_Receiver, output [7:0] Digitron_Out, output [5:0] DigitronCS_Out, output beep,//蜂鸣器 output LCD_RESET, output LCD_BLK, output LCD_DC, outputCS, outputMOSI, outputSCK ); localparam IDLE = 0; localparam Start = 1; localparam Count = 2; localparam Wait_Multi = 3;//等待乘法器完成 localparam Cal = 4; //颜色 parameter Red = 16'h07FF ; parameter White = 16'h0000 ; parameter Black = 16'hFFFF ; parameter Green = 16'hF81F ; parameter Yellow = 16'h001F ; parameter Brown = 16'h43BF ; parameter Blue = 16'hFFE0 ; reg count_begin ;// 第一个信号过来,开始计时 reg count_end ;// 第二个信号过来,结束计时 reg Radar_Start_Temp ; reg Radar_End_Temp ; reg [1:0]Radar_Receiver_Reg ; always@(posedge Main_CLK) //把异步信号转成同步,防止竞争冒险 begin Radar_Receiver_Reg <= Radar_Receiver ; end always@(posedge Main_CLK) begin Radar_Start_Temp <= Radar_Receiver_Reg[0] ; if(Radar_Receiver_Reg[0] == 1'b1 && Radar_Start_Temp==1'b0) //检测到上升沿 begin count_begin <=1'b1 ; end else count_begin <=1'b0 ; end always@(posedge Main_CLK) begin Radar_End_Temp <= Radar_Receiver_Reg[1] ; if(Radar_Receiver_Reg[1] == 1'b1 && Radar_End_Temp==1'b0) //检测到上升沿 begin count_end <=1'b1 ; end else count_end <=1'b0 ; end reg[3:0]state ; reg[18:0]Time_Count /* synthesis preserve */; //记录雷达两个上升沿之间的主时钟计数 reg [4:0]Ave_Count /* synthesis preserve */;//用于平均操作的计数器,平均16次 reg[22:0] Distance_Sum /* synthesis preserve */; //存储累加16次的Time_Count reg[21:0] b = 22'd2761201;//计算公式里的b,放大了65536倍 reg[8:0] k = 9'd233 ; //计算公式里的k,放大了65536倍 reg[27:0] Distance_Cal /* synthesis preserve */;//校准后的距离值,跟随k,b的放大倍数,放大了65536倍 wire done ; reg [3:0]wait_time ; //等待乘法器完成的节拍 always@(posedge Main_CLK or negedge RSTn) begin if(!RSTn) begin state <= IDLE ; end else begin case(state) IDLE: begin state <= Start ; Time_Count <= 19'd0 ; // div1_start <= 1'b1 ; Ave_Count <= 5'd0 ; Distance_Sum <= 23'd0 ; wait_time <= 4'd0 ; end Start: begin if(count_begin==1'b1) begin state <= Count ; Time_Count <= 19'd0 ; end end Count: begin if(count_end==1'b0) Time_Count <= Time_Count + 1'b1 ; else begin if(Ave_Count<5'd16) begin Distance_Sum <= Distance_Sum + Time_Count ; Ave_Count <= Ave_Count + 1'b1 ; state <= Start ; end else begin state <= Wait_Multi ; Distance_Cal <=Distance_Sum[22:4]*k - b ; end end end Wait_Multi: begin if(wait_time<4'd4) wait_time <= wait_time + 1'b1 ; else state <= Cal ; end Cal: begin state <= IDLE ; end endcase end end wire[11:0] Distance; // 实际的距离值 //Distance_Cal被放大了65536倍,因此这次右移16位,相当于除以65536; assign Distance = Distance_Cal[27:16]; wire [11:0]Distance_bcd ; // 转换成BCD码显示到数码管上binary2bcd U2 ( .a(Distance), .b(Distance_bcd) ); Digitron_TimeDisplay_module U3 ( .clk(Main_CLK), .data_display(Distance_bcd[11:0]),//BCD_Display .Digitron_Out(Digitron_Out), .DigitronCS_Out(DigitronCS_Out) ); beep_ctrl i_beep_ctrl( . clk(Main_CLK), . Distance(Distance), // 实际的距离值 . beep(beep) ); reg [23:0]data_integer ; always@(Distance_bcd ) begin case(Distance_bcd[11:8]) 0: begin data_integer[23:16] = " "; end 1: begin data_integer[23:16] = "1";end 2: begin data_integer[23:16] = "2";end 3: begin data_integer[23:16] = "3";end 4: begin data_integer[23:16] = "4";end 5: begin data_integer[23:16] = "5";end 6: begin data_integer[23:16] = "6";end 7: begin data_integer[23:16] = "7";end 8: begin data_integer[23:16] = "8";end 9: begin data_integer[23:16] = "9";end endcase case(Distance_bcd[7:4]) 0: begin data_integer[15:8] = "0"; end 1: begin data_integer[15:8] = "1";end 2: begin data_integer[15:8] = "2";end 3: begin data_integer[15:8] = "3";end
266