一、实验准备
软件:Quartus + Modelsim
硬件:DE2-E115 FPGA开发板+HC_SR04模块
二、实验要求
使用DE2开发板驱动HC_SR04模块,并将所测得数据显示到开发板上的数码管。
三、实验原理
模块实物图:
模块引脚介绍:
从上图我们可以看到超声波模块的4个引脚,它们的作用罗列如下:
-
VCC: 电源引脚,超声波模块工作电压为5伏。
-
Trig: 是Trigger(触发)这个单词的缩写,该引脚用于触发超声波脉冲。
-
Echo: 该引脚会在高电平和低电平之间转换,当检测到障碍物时,在高电平保持的时间就表示信号发射出去并反射回来的时间。
-
GND: 接地引脚。
模块测距工作原理:
-
主控设备给 Trig 脚提供一个 10us 的脉冲信号。
-
HC-SR04 接收到信号,开始发送超声波,并把 Echo置为高电平,然后准备接收返回的超声波。
-
HC-SR04 接收到返回的超声波,把 Echo 置为低电平。
-
Echo 高电平持续的时间就是超声波从发射到返回的时间间隔。
超声波时序图:
四、模块实现
hc_sr_trig
模块
module hc_sr_trig(
input wire clk ,
input wire rst_n ,
output wire trig //触发测距信号
);
//trig:超声波触发信号,高电平至少为10us,同时考虑到信号不要重叠,所以当距离为5000mm时的来回时间做为超声波触发信号的周期T
//T=(5/340) * 1000ms = 14.7ms,来回就是29.4ms,所以就让触发脉冲的周期至少为30ms,高电平时间为10us
//为了防止发射信号对回响信号产生影响,这里直接设定为100ms的周期,高电平为10us
parameter CNT_10US_MAX = 9'd500;
parameter CNT_100MS_MAX = 23'd5000_000;
reg [22:0] cnt_100ms ;
wire cnt_100ms_flag ;
reg trig_r;
//cnt_100ms and cnt_100ms_flag
assign cnt_100ms_flag = cnt_100ms==CNT_100MS_MAX - 1'b1;
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
cnt_100ms<=23'd0;
end
else if(cnt_100ms_flag) begin
cnt_100ms<=23'd0;
end
else begin
cnt_100ms<=cnt_100ms+1'b1;
end
end
//trig
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
trig_r<=1'b0;
end
else if(cnt_100ms<CNT_10US_MAX) begin
trig_r<=1'b1;
end
else begin
trig_r<=1'b0;
end
end
assign trig = trig_r;
endmodule
hc_sr_echo
模块
module hc_sr_echo(
input wire clk ,
input wire rst_n ,
input wire echo ,
output reg fall_flag_r1, //下降沿标志的打拍信号
output wire [12:0] data_o //检测距离,保留3位小数,*1000实现
);
/*计算:s=340*t/2 m = 340_000 mm * t /2
记脉冲个数:N
s=N*20*340_000/1000_000_000/2 mm = N*0.0034 mm = N*34/10000 ;
5000/0.0034=1470588 21bit ; 34 6bit
*/
reg echo_r1 ;
reg echo_r2 ;
wire raise_flag ;//上升沿标志信号
wire fall_flag ;//下降沿标志信号
reg [20:0] cnt_pulse ;//考虑的范围25~4000mm
reg [20:0] temp_pulse ;
reg [12:0] data_bin ;
//raise_flag
assign raise_flag = ((~echo_r2) && (echo_r1)) ? 1'b1 : 1'b0 ;
assign fall_flag = ((echo_r2) && (~echo_r1)) ? 1'b1 : 1'b0 ;
//beat time
always @ (posedge clk or negedge rst_n) begin
if(!rst_n) begin
echo_r1<=1'b0;
echo_r2<=1'b0