一、实验设备
硬件:PC 机、DE2-115、HC-SR04超声波测距模块
软件:Quartus Prime 18.1
二、实验原理
超声波测距原理是在超声波发射装置发出超声波,它的根据是接收器接到超声波时的时间差,与雷达测距原理相似。 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。
超声波在空气中的传播速度为340m/s,根据计时器记录的时间t(秒),就可以计算出发射点距障碍物的距离(s),即:s=340t/2
HC-SR04模块
- 采用IO口TRIG触发测距,给至少10us的高电平信号,模块自动发送8个40khz的方波,自动检测是否有信号返回。
- 有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2。
三、代码实现
vlg_en模块
//产生1us为周期的时钟使能信号
//1us/20ns=50,r_divcnt内部计数周期为0~49
module vlg_en(
parameter P_CLK_PERIORD = 20) //i_clk的时钟周期为20ns,50MHZ
(
input i_clk,
input i_rst_n,
output reg o_clk_en //o_clk_en的时钟周期为1us
);
reg[7:0] r_divcnt;
//对输入时钟i_clk做分频计数,产生1us的时钟使能信号
always @(posedge i_clk)
if(!i_rst_n) r_divcnt <= 'b0;
else if(r_divcnt<50)r_divcnt <= r_divcnt+1'b1;
else r_divcnt <= 'b0;
//产生时钟使能信号
always @(posedge i_clk)
if(!i_rst_n)o_clk_en<= 'b0;
else if(r_divcnt==49)o_clk_en<= 'b1;
else o_clk_en <= 'b0;
endmodule
vlg_trig模块
module vlg_trig(
input i_clk,
input i_rst_n,
input i_clk_en,
output reg o_trig
);
reg[16:0] r_tricnt;
//100ms的周期计数
always @(posedge i_clk)
if(!i_rst_n) r_tricnt <= 'b0;
else if((i_clk_en==1)&&(r_tricnt<99999))r_tricnt <= r_tricnt+1'b1;
else r_tricnt <= 'b0;
//产生保持10us的高脉冲o_trig信号
always @(posedge i_clk)
if(!i_rst_n) o_trig<=1'b0;
else if((r_tricnt > 'b0) && (r_tricnt <= 10))o_trig<=1'b1;
else o_trig<=1'b0;
endmodule
vlg_echo模块
module vlg_echo(
input i_clk,
input i_rst_n,
input i_clk_en,
input i_echo,
output reg[15:0] o_t_us
);
reg[1:0] r_echo;
wire pos_echo,neg_echo;
reg r_cnt_en;
reg[15:0] r_echo_cnt;
//对i_echo信号同步处理,获取边沿检测信号,产生计数使能信号r_cnt_en
always @(posedge i_clk)
if(!i_rst_n) r_echo<= 'b0;
else r_echo <= {r_echo[0],i_echo};
assign pos_echo =r_echo[0] & ~r_echo[1] ;
assign neg_echo = ~r_echo[0] &r_echo[1] ;
always @(posedge i_clk)
if(!i_rst_n) r_cnt_en <= 'b0;
else if(pos_echo) r_cnt_en <= 'b1;
else if(neg_echo) r_cnt_en <= 'b0;
else ;
//对i_echo信号高脉冲计时,以us为单位
always @(posedge i_clk)
if(!i_rst_n) r_echo_cnt <= 'b0;
else if(!r_cnt_en) r_echo_cnt <= 'b0;
else if(i_clk_en) r_echo_cnt <= r_echo_cnt+1;
else ;
//对r_echo_cnt计数最大值做锁存
always @(posedge i_clk)
if(!i_rst_n) o_t_us <= 'b0;
else if(neg_echo) o_t_us <= r_echo_cnt;
endmodule
vlg_cal模块
module vlg_cal(
input i_clk,
input i_rst_n,
input[15:0] i_t_us,
output[13:0] o_s_mm
);
//乘法器IP例化
wire[25:0] w_mult_result;
mult_gen_0 uut_mult_gen_0 (
.CLK(i_clk), // input wire CLK
.A(10'd709), // input wire [9 : 0] A
.B(i_t_us), // input wire [15 : 0] B
.P(w_mult_result) // output wire [25 : 0] P
);
assign o_s_mm = w_mult_result[25:12];
endmodule
顶层模块
module vlg_design(
input i_clk,
input i_rst_n,
output o_trig,
input i_echo
);
localparam P_CLK_PERIORD = 20;
wire w_clk_en;
wire[15:0] w_t_us;
wire[13:0] o_s_mm;
//
//使能时钟产生模块
vlg_en #(
.P_CLK_PERIORD(P_CLK_PERIORD) //i_clk的时钟周期为20ns
)
uut_vlg_en(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.o_clk_en(w_clk_en)
);
//
//产生超声波测距模块的触发信号o_trig
vlg_trig uut_vlg_trig(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.i_clk_en(w_clk_en),
.o_trig(o_trig)
);
//
//超声波测距模块的回响信号i_echo的高电平时间采集
vlg_echo uut_vlg_echo(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.i_clk_en(w_clk_en),
.i_echo(i_echo),
.o_t_us(w_t_us)
);
//
//进行时间和距离的转换运算s = 0.179t
vlg_cal uut_vlg_cal(
.i_clk(i_clk),
.i_rst_n(i_rst_n),
.i_t_us(w_t_us),
.o_s_mm(o_s_mm)
);
//
//VIO IP例化
debug_vio uut_debug_vio (
.clk(i_clk), // input wire clk
.probe_in0(o_s_mm) // input wire [13 : 0] probe_in0
);
endmodule
四、总结
本次实验学习了HC-SR04模块的使用,了解了超声波测距的基本原理,由于时间仓促,未能在实验室做出效果,但在课后利用STM32完成了测距,基本原理并无大异,也是通过给出10us的高点平信号后通过信号持续时间测算距离
五、参考资料
https://blog.csdn.net/weixin_56912944/article/details/124756202
https://www.freesion.com/article/7737471899/