FPGA-超声波测距数码管显示系列(包含进制转换、均值滤波)

       首先在前文已经介绍过了超声波模块的原理和使用,之前没有介绍回响脉冲的计数问题,这次简单说一下吧,每隔一秒发一次触发信号,当触发信号来了后,每隔10Us进行一次脉冲的计数,计算出每秒的脉冲数,这时候就有一个问题,怎么根据回响信号进行计数呢?

1、首先我们可以看到回响信号是根据距离成正比的,而且脉冲计数是每隔10us进行一次脉冲方便进行距离的计算(精度2mm 决定)

2、当本次回响脉冲开始时候可以进行上次的数据的清零,然后进行本次数据的计数,当回响信号结束数据计数终止,将本次的计数值输出,用于距离的测量。

3、计算公式:

如果 距离是m  时间取s:     s=346*t/2;

如果距离是mm  时间取10us: s*0.001=346*t*0.00001/2   即:s=1.73/t    方便计算则取 s=(443 X t )/256

 

C-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能, 测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。基本工作原理:

(1)采用IO口TRIG触发测距,给至少10us的高电平信号;

(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;

(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。

  超声波测距模块电路图

  超声波测距模块工作原理_HC-SR04模块详解

  电气参数

  1

超声波测距模块工作原理_HC-SR04模块详解

  超声波时序图

  超声波测距模块工作原理_HC-SR04模块详解

 

原理介绍完毕:

贴代码:(这里的测得的数据是通过均值滤波处理后测得的回响数,然后通过乘法器和除法器进行进制转换后显示具体测得的距离)

 

这里的mul   div进行距离转换用到了IP核)

top.v:

module top(clk,rst_n,dtube_cs_n,dtube_data,ultrasound_trig,ultrasound_echo
    );
	input clk;
	input rst_n;
	
	output ultrasound_trig;
	output [3:0]dtube_cs_n;
	output [6:0]dtube_data;
	input ultrasound_echo;
	
	wire [15:0] echo_pulse_num;
	wire clk_100khz_en;
	wire [15:0]cnt;
	wire [15:0] out_num;
	wire pul_en;
	assign cnt={quotient_hund[3:0],quotient_thou[3:0],fractional_ten[3:0],quotient_ten[3:0]};
	clk_100khz_en uut_clk_100khz_en(
	.clk(clk),
	.rst_n(rst_n),
	.clk_100khz_en(clk_100khz_en)
    );

	cheju uut_cheju(
	.clk(clk),
	.rst_n(rst_n),
	.clk_100khz_en(clk_100khz_en),
	.ultrasound_trig(ultrasound_trig),
	.ultrasound_echo(ultrasound_echo),
	.echo_pulse_en(pul_en),
	.echo_pulse_num(echo_pulse_num)
    );
	
	seg_4 uut_seg_4(
	.clk(clk),
	.rst_n(rst_n),
	.dis_data(cnt),
	.dtube_cs_n(dtube_cs_n),
	.dtube_data(dtube_data)
	);
	filter uut_filter(
	.clk(clk),
	.rst_n(rst_n),
	.pul_en(pul_en),
	.pulse_num(echo_pulse_num),
	.filter_num(out_num)
    );
	//距离换算
	wire[31:0]mul_dout;
	mul_out uut_mul_out(
	.clk(clk), // input clk
	.a(16'd443), // input [15 : 0] a
	.b(out_num), // input [15 : 0] b
	.p(mul_dout) // output [31 : 0] p
	);
	
	//利用除法器进行进制转换
	wire [15:0]quotient_thou,fractional_thou;
	div_out uut_div_out1(
	.clk(clk), // input clk
	.rfd(), // output rfd
	.dividend(mul_dout[23:8]), // input [15 : 0] dividend
	.divisor(16'd1000), // input [15 : 0] divisor
	.quotient(quotient_thou), // output [15 : 0] quotient
	.fractional(fractional_thou)
	); // output [15 : 0] fractional
	
	wire [15:0]quotient_hund,fractional_hund;
	div_out uut_div_out2(
	.clk(clk), // input clk
	.rfd(), // output rfd
	.dividend(fractional_thou), // input [15 : 0] dividend
	.divisor(16'd100), // input [15 : 0] divisor
	.quotient(quotient_hund), // output [15 : 0] quotient
	.fractional(fractional_hund)
	); // output [15 : 0] fractional
	
	wire [15:0]quotient_ten,fractional_ten;
	div_out uut_div_out3(
	.clk(clk), // input clk
	.rfd(), // output rfd
	.dividend(fractional_hund), // input [15 : 0] dividend
	.divisor(16'd10), // input [15 : 0] divisor
	.quotient(quotient_ten), // output [15 : 0] quotient
	.fractional(fractional_ten)
	); // output [15 : 0] fractional
endmodule

clk_100khz_en.v:

module clk_100khz_en(clk,rst_n,clk_100khz_en
    );
	input clk;
	input rst_n;
	output clk_100khz_en;
	
	reg [7:0] cnt;
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			cnt<=1'b0;
		end
		else if(cnt==8'd249)begin
			cnt<=1'b0;
		end
		else begin
			cnt<=cnt+1'b1;
		end
	end
	assign clk_100khz_en=(cnt==8'd249);
endmodule

seg.v:

module seg_4(clk,rst_n,dis_data,dtube_cs_n,dtube_data
	);
	input clk;		//时钟信号25MHz
	input rst_n;			//复位信号
	input [15:0] dis_data;//
	output reg[3:0] dtube_cs_n;	//段选数据位
	output reg[6:0] dtube_data;//位选数据位
	reg [3:0]TimeH;			//两位输入高位  [0]
	reg [3:0]TimeL;			//两位输入低位  [1]
	reg [3:0]TimeH1;		//两位输入高位  [2]
	reg [3:0]TimeL1;		//两位输入低位  [3]	
	reg [3:0] display_num;	//当前显示数据
	reg [16:0] div_cnt;	//延时计数器计数位
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			TimeH<=1'b0;	
			TimeL<=1'b0;	
			TimeH1<=1'b0;
			TimeL1<=1'b0;
		end
		else begin
			TimeH <=dis_data[3:0];	
			TimeL <=dis_data[7:4];	
			TimeH1<=dis_data[11:8];
			TimeL1<=dis_data[15:12];
		end
	end
initial div_cnt = 0;//赋初值为0
//延时计数器模块
	always@ (posedge clk or negedge rst_n)
	begin
		if(!rst_n) 
			div_cnt <= 8'd0;
		else if(div_cnt==17'd80000)
			div_cnt <= 8'd0;		
		else 
			div_cnt <= div_cnt+1'b1;
	end
	
//显示当前的数据模块
	always @(posedge clk or negedge rst_n)
	begin
	if(!rst_n) 
		display_num <= 4'h0;
	else if(div_cnt < 17'd20000)
		display_num <= TimeL;
	else if((div_cnt>17'd20000)&(div_cnt <17'd40000))
		display_num <= TimeH;
	else if((div_cnt>17'd40000)&(div_cnt < 17'd60000))
		display_num <=TimeL1;
	else
		display_num <=TimeH1;
	end
		
//段选数据译码模块(共阴数码管)
	always @(*)
	begin
		if(!rst_n) 
			dtube_data <= 8'h00;
		else begin
			case(display_num) 
				4'h0: dtube_data <= 8'h3f;
				4'h1: dtube_data <= 8'h06;
				4'h2: dtube_data <= 8'h5b;
				4'h3: dtube_data <= 8'h4f;
				4'h4: dtube_data <= 8'h66;
				4'h5: dtube_data <= 8'h6d;
				4'h6: dtube_data <= 8'h7d;
				4'h7: dtube_data <= 8'h07;
				4'h8: dtube_data <= 8'h7f;
				4'h9: dtube_data <= 8'h6f;
				default:dtube_data <= 8'h00;
			endcase
		end
	end
//位选选译模块
	always @(posedge clk or negedge rst_n)	
	begin
		if(!rst_n) 
			dtube_cs_n <=  4'b1111;
		else if(div_cnt <= 17'd20000)
			dtube_cs_n <= 4'b1110;
		else if((div_cnt>17'd20000)&(div_cnt <=17'd40000))
			dtube_cs_n <= 4'b1101;
		else if((div_cnt>17'd40000)&(div_cnt <=17'd60000))
			dtube_cs_n <= 4'b1011;
		else 
			dtube_cs_n <=4'b0111;
	end
endmodule

filter.v:

module filter(clk,rst_n,pul_en,pulse_num,filter_num
    );
	input clk;
    input rst_n;
    input pul_en;
    input [15:0]pulse_num;
	output [15:0]filter_num;
	
	reg[15:0]pul_buf[7:0];
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			pul_buf[0]<=1'b0;
			pul_buf[1]<=1'b0;
			pul_buf[2]<=1'b0;
			pul_buf[3]<=1'b0;
			pul_buf[4]<=1'b0;
			pul_buf[5]<=1'b0;
			pul_buf[6]<=1'b0;
			pul_buf[7]<=1'b0;
		end
		else if(pul_en==1'b1)begin
			pul_buf[0]<=pulse_num;
			pul_buf[1]<=pul_buf[0];
			pul_buf[2]<=pul_buf[1];
			pul_buf[3]<=pul_buf[2];
			pul_buf[4]<=pul_buf[3];
			pul_buf[5]<=pul_buf[4];
			pul_buf[6]<=pul_buf[5];
			pul_buf[7]<=pul_buf[6];
		end 
	end
	reg [15:0]sum_pul;
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			sum_pul<=1'b0;
		end
		else begin
			sum_pul<=pul_buf[0]+pul_buf[1]+pul_buf[2]+pul_buf[3]+pul_buf[4]+pul_buf[5]+pul_buf[6]+pul_buf[7];
		end
	end
	
	assign filter_num ={3'b0,sum_pul[15:3]};
endmodule

cheju.v:

module cheju(clk,rst_n,clk_100khz_en,ultrasound_trig,ultrasound_echo,echo_pulse_en,echo_pulse_num
    );
	input clk;
	input rst_n;
	input clk_100khz_en;
	input ultrasound_echo;//回响信号
	output ultrasound_trig;//脉冲激励信号
	output reg echo_pulse_en;		//超声波测距模块回响信号计数值有效信号
	output reg[15:0] echo_pulse_num;	//以10us为单位对超声波测距模块回响信号高脉冲进行计数的最终值
	
	reg [16:0]timer_cnt;
	always@(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			timer_cnt<=1'b0;
		end
		else if(clk_100khz_en==1'b1)begin
			if(timer_cnt<17'd99_999)begin
				timer_cnt<=timer_cnt+1'b1;
			end
			else begin
				timer_cnt<=1'b0;
			end
		end
		else begin
			timer_cnt<=timer_cnt;
		end
	end
	assign ultrasound_trig=(timer_cnt==1'b1)?1'b1:1'b0;//每隔一秒产生一次脉冲					
 
	//超声波测距模块的回响信号echo打两拍,产生上升沿和下降沿标志位
	reg[1:0] ultrasound_echo_r;
 
	always @(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			ultrasound_echo_r <= 2'b00;
		end
		else begin
			ultrasound_echo_r <= {ultrasound_echo_r[0],ultrasound_echo};
		end
	end
	wire pos_echo = ~ultrasound_echo_r[1] & ultrasound_echo_r[0];	//echo信号上升沿标志位,高电平有效一个时钟周期
	wire neg_echo = ultrasound_echo_r[1] & ~ultrasound_echo_r[0];	//echo信号下降沿标志位,高电平有效一个时钟周期
 
	//以10us为单位对超声波测距模块回响信号高脉冲进行计数
	reg[15:0] echo_cnt;		//回响高脉冲计数器
	always @(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			echo_cnt <= 16'd0;
		end
		else if(pos_echo==1'b1)begin
			echo_cnt <= 16'd0;	//计数清零
		end
		else if(clk_100khz_en==1'b1 && ultrasound_echo_r[0]==1'b1)begin
			echo_cnt <= echo_cnt+1'b1;
		end
	end
	
	//计数脉冲数锁存
	always @(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			echo_pulse_num <= 16'd0;	
		end
		else if(neg_echo==1'b1)begin
			echo_pulse_num <= echo_cnt;
		end
	end
	//计数脉冲有效使能信号锁存
	always @(posedge clk or negedge rst_n)begin
		if(rst_n==1'b0)begin
			echo_pulse_en <= 1'b0;
		end
		else begin
			echo_pulse_en <= neg_echo;
		end
	end
endmodule

 

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vuko-wxh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值