基于FPGA的超声波测距

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


1. 实验平台与目


DE2-E115 FPGA开发板 + Quartus + Modelsim
学习并掌握HC_SR04模块的使用

2. 实验要求

使用DE2开发板驱动HC_SR04模块,并将所测得数据显示到开发板上的数码管。
在这里插入图片描述

3. 实验原理

3.1. 理论原理

超声波原理:
HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为HC-SR04外观,其基本工作原理为给予此超声波测距模块触发信号后模块发射超声波,当超声波投射到物体而反射回来时,模块输出回响信号,以触发信号和回响信号间的时间差,来判定物体的距离。
在这里插入图片描述

3.2. 硬件模块时序图

在这里插入图片描述

4. 系统架构设计

在这里插入图片描述
顶层文件top_wave

module top_wave(
	input  				s_clk			,
	input  				s_rst_n			,
	//supersonic wave module singnals
	input 				Echo 			,
	output 	 			trig 			,
	//Nixie tube display
	output 		[6:0]	Y				,
	output 		[3:0]	an				,
	output 			 	dp
    );
wire [15:0] data;
measurement measurement_0 (
    .s_clk              (s_clk      ), 
    .s_rst_n            (s_rst_n    ), 
    .Echo               (Echo       ), 
    .trig               (trig       ), 
    .data               (data       )
    );

xianshi xianshi_0 (
    .s_clk              (s_clk      ), 
    .s_rst_n            (s_rst_n    ), 
    .A0                 (data[3:0]  ), 
    .A1                 (data[7:4]  ), 
    .A2                 (data[11:8] ), 
    .A3                 (data[15:12]), 
    .Y                  (Y          ), 
    .an                 (an         ), 
    .dp                 (dp         )
    );

endmodule

数码管显示文件xianshi

module xianshi(
		input  s_clk,
		input  s_rst_n,
		input [3:0] A0,
		input [3:0] A1,
		input [3:0] A2,
		input [3:0] A3,
		output reg [6:0]Y,//显示器段选
		output reg [3:0]an,//显示器位选
		output reg dp
    );
parameter AB=18'd300000;
reg[17:0] cnt;//动态扫描计数器
//这个时间其实可以自己控制,只要在人眼不能观察到间隔就行
always@(posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		cnt<=1'b0;
	else 
		if(cnt == (AB-1) )
			cnt<=1'b0;
		else 
			cnt<=cnt+1;
end
/*动态扫描	选择要显示的数码管(第一个要显示),当速度快到人眼无法区分的时候就是“所有”数码管一//起显示了*/
reg[3:0]digit;//定义一个储存要显示数据的寄存器
always@(posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n) 
		begin
			an <= 4'b0111;
			dp <= 0;
		end
	else 
		if(cnt==AB-1) 
			begin
				an <= {an[0],an[3:1]};
				dp <= 1'b1;
			end
		else 
			begin
				an <= an;
				dp <= dp;
			end
end
//当某一个数码管被点亮的时候,赋予其对应位置的数据
always@(posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		digit<=4'b1111;
	else 
		case(an)
			4'b1110:digit <= A0   		;
			4'b1101:digit <= A1   		;
			4'b1011:digit <= A2   		;
			4'b0111:digit <= A3   		;
			default:digit <= digit		;
		endcase
end
//七段译码器(显示器)
always@(*)
begin
	case(digit)
		4'b0000:Y<=7'b0000001;
		4'b0001:Y<=7'b1001111;
		4'b0010:Y<=7'b0010010;
		4'b0011:Y<=7'b0000110;
		4'b0100:Y<=7'b1001100;
		4'b0101:Y<=7'b0100100;
		4'b0110:Y<=7'b0100000;
		4'b0111:Y<=7'b0001111;
		4'b1000:Y<=7'b0000000;
		4'b1001:Y<=7'b0000100;
		default Y<=7'b0000001;
	endcase
end
endmodule

倒车模块measurement

module measurement(
	//system singnals
	input 				s_clk 		,
	input 				s_rst_n 	,
	//supersonic wave module singnals
	input 				Echo 		,
	output 	reg 		trig 		,
	//connect with Nixie tube display
	output 	reg [15:0] 	data 	
    );
//
//generate cnt_17M_en
//单比特跨时钟域处理,延时两拍
reg [2:0] Echo_delay;
always @ (posedge s_clk or negedge s_rst_n)
begin
if(!s_rst_n)
	begin
		Echo_delay <= 'd0;
	end
else 
	begin
		Echo_delay <= {Echo_delay[1:0],Echo};
	end
end 
//检测上升沿下降沿
wire nege_Echo;
wire pose_Echo;
assign pose_Echo = (~Echo_delay[2])&&Echo_delay[1];
assign nege_Echo = Echo_delay[2]&&(!Echo_delay[1]);
//产生计数使能信号
reg cnt_17M_en;
always @ (posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		cnt_17M_en <= 'd0;
	else 
		if(pose_Echo)
			cnt_17M_en <= 1'b1;
		else 
			if(nege_Echo)
				cnt_17M_en <= 1'b0;
			else 
				cnt_17M_en <= cnt_17M_en;
end
//
//div_clk_17Mhz
reg [11:0] cnt_17M;
always @ (posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		cnt_17M <= 'd0;
	else 
		if(cnt_17M_en)
			begin
				if(cnt_17M == 'd2942)
					cnt_17M <= 'd0;
		        else 
		        	cnt_17M <= cnt_17M + 1'b1;
			end
		else 
			cnt_17M <= 'd0;
end 
reg clk_17M;
always @ (posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		clk_17M <= 1'b0;
	else 
		if(cnt_17M == 'd2942)
			clk_17M <= 1'b1;
		else 
			clk_17M <= 1'b0;
end
//
//generate trig 
reg [25:0] cnt_500Ms;
always @ (posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		cnt_500Ms <= 1'b0;
	else 
		if(cnt_500Ms == 'd12_500_000)
			cnt_500Ms <= 'd0;
		else 
			cnt_500Ms <= cnt_500Ms + 1'b1;
end
always @ (posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		trig <= 1'b0;
	else 
		if(cnt_500Ms <= 'd500)
			trig <= 1'b1;
		else 
			trig <= 1'b0;
end 
//显示部分,使用计数器进行计数(17MHz)
always @ (posedge s_clk or negedge s_rst_n)
begin
	if(!s_rst_n)
		data <= 'd0;
	else 
		if(clk_17M == 1'b1)
			begin
				if(data[3 :0 ] == 'd9)
					begin
						data[7 :4 ] <= 1'b1 + data[7 :4 ];
						data[3 :0 ] <= 'd0;
					end 
				else 
					if(data[7 :4 ] == 'd9)
						begin
							data[11:8 ] <= 1'b1 + data[11:8 ];
							data[7 :4 ] <= 'd0;
						end 
					else 
						if(data[11:8 ] == 'd9)
							begin
								data[15:12] <= 1'b1 + data[15:12];
								data[11:8 ] <= 'd0;
							end 
						else 
							data <= data + 1'b1;
			end 
		else 
			if(cnt_500Ms == 'd12_500_000)
				data <= 'd0;
			else
				data <= data;
end 

endmodule

总结

基本实现了倒车模块和在数码管上显示距离,但是存在一定的问题,传输过来的信号不大稳定,使数码管上显示的距离会波动。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值