基于FPGA的超声波测距——数码管显示

这篇具有很好参考价值的文章主要介绍了基于FPGA的超声波测距——数码管显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

环境:
1、Quartus18.1
2、vscode
3、板子型号:EP4CE6F17C8N
4、超声波模块:HC_SR04
要求:
使用 EP4CE6F17C8开发板驱动 超声波检测模块(HC_SR04 ),并将所测得数据显示到开发板上的数码管上


一、超声波模块介绍

1、产品特点

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

(1)采用IO口 TRIG触发测距,给最少10us的高电平信呈。
(⑵)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

基于FPGA的超声波测距——数码管显示

2、超声波模块的时序图

基于FPGA的超声波测距——数码管显示

以上时序图表明你只需要提供一个10uS 以上脉冲触发信号,该模块内部将发出8个40kHz周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。

二、系统设计

1、系统框图

基于FPGA的超声波测距——数码管显示

2、源码

  • HC_SR04_TOP顶层文件:
module 	HC_SR04_TOP(
	input  			clk		, 
	input   		rstn	, 
	
	input   		echo	, // 距离信号
	output   		trig	, // 触发测距信号
	output  wire [5:0]	sel	,
	output  wire [7:0]	seg
);

	wire	[18:00]		data_o		;
	wire 				clk_us		;

	seg_driver u_seg_driver(  
		.clk		(clk	),
		.rstn		(rstn	),
		.data_in	(data_o	), //待显示数据
		.sel		(sel	),	// 我这里是8位段选,可以换6位,但是要自己改代码
    	.seg		(seg	)     
	);	

	clk_div	u_clk_div(
		.clk		(clk	), 
		.rstn		(rstn	),
		.clk_us		(clk_us )
	);
	trig_driver	u_trig_driver(
		.clk_us		(clk_us	),
		.rstn		(rstn	),
		.trig		(trig	)
	);

	echo_driver	u_echo_driver(
		.clk		(clk	),
		.clk_us		(clk_us	),
		.rstn		(rstn	),
		.echo		(echo	),
		.data_o		(data_o	)
		);

//Logic Description
endmodule 

  • trig_driver超声波驱动模块:
module 	trig_driver(
	input  wire			clk_us	,
	input  wire 		rstn	,
		   
	output wire  		trig	  //触发测距信号
);

	parameter CYCLE_MAX = 19'd29_9999;

	reg		[18:00]	cnt		;

// 10毫秒持续电平输出
	
	always @(posedge clk_us or negedge rstn) begin
		if(!rstn) begin
			cnt <= 19'd0;
		end
		else if(cnt == CYCLE_MAX) begin
			cnt <= 19'd0;
		end
		else begin
			cnt <= cnt + 19'd1;
		end
	end
	
	assign trig = cnt < 15 ? 1'b1 : 1'b0;

endmodule 
  • echo_driver测距模块:
module 	echo_driver(
	input  wire 		clk		,
	input  wire			clk_us	,
	input  wire 		rstn	,
		   
	input  wire 		echo	,
	output wire [18:00]	data_o	  //检测距离,保留3位小数,*1000实现
);

	parameter T_MAX = 16'd5_9999;//510cm 对应计数值

	reg				r1_echo,r2_echo; //边沿检测	
	wire			echo_pos,echo_neg; //
	
	reg		[15:00]	cnt		; 
	
	reg		[18:00]	data_r	;
	
	//如果使用clk_us 检测边沿,延时2us,差值过大
	always @(posedge clk or negedge rstn)begin  
		if(!rstn)begin  
			r1_echo <= 1'b0;
			r2_echo <= 1'b0;
		end  
		else begin  
			r1_echo <= echo;
			r2_echo <= r1_echo;
		end  
	end
	
	assign echo_pos = r1_echo & ~r2_echo;
	assign echo_neg = ~r1_echo & r2_echo;
	
	always @(posedge clk_us or negedge rstn) begin
		if(!rstn) begin
			cnt <= 16'd0;
		end
		else if(echo) begin
			if(cnt == T_MAX) begin
				cnt <= 16'd0;
			end
			else begin
				cnt <= cnt + 16'd1;
			end
		end
		else begin
			cnt <= 16'd0;
		end
	end
	
	always @(posedge clk or negedge rstn)begin  
		if(!rstn)begin  
			data_r <= 'd2;
		end  
		else if(echo_neg)begin  
			data_r <= (cnt << 4) + cnt;
		end  
		else begin  
			data_r <= data_r;
		end  
	end
	
	assign data_o = data_r >> 1;

endmodule 

  • 时钟分频模块:
module 	clk_div(
	input  wire			clk		,
	input  wire 		rstn	,
		   
	output wire  		clk_us 	  //
);

	parameter CNT_MAX = 19'd49;//1us的计数值为 50 * Tclk(20ns)

	reg		[5:0]	cnt		; 
	wire			add_cnt ;
	wire			end_cnt ;
	
	// 时钟分频
	always @(posedge clk or negedge rstn) begin
		if(!rstn) begin
			cnt <= 6'd0;
		end
		else if(cnt == CNT_MAX) begin
			cnt <= 6'd0;
		end
		else begin
			cnt <= cnt + 6'd1;
		end
	end
	
	assign clk_us = cnt >= CNT_MAX ;
	

endmodule 

  • seg_driver数码管驱动模块:
module seg_driver(  
	input	wire		clk		,
	input	wire		rstn	,
	
	input	wire [18:0]	data_in	, //待显示数据

    output  reg [5:0]   sel     ,	// 我这里是8位段选,可以换6位,但是要自己改代码
    output  reg [7:0]   seg     
);								  
 	//parameter define  
	localparam	NUM_0	=	8'b1100_0000,	
				NUM_1 	= 	8'b1111_1001,
				NUM_2   = 	8'b1010_0100,
				NUM_3   = 	8'b1011_0000,
				NUM_4   = 	8'b1001_1001,
				NUM_5   = 	8'b1001_0010,
				NUM_6   = 	8'b1000_0010,
				NUM_7   = 	8'b1111_1000,
				NUM_8   = 	8'b1000_0000,
				NUM_9   = 	8'b1001_0000,
				NUM_A   = 	8'b1000_1000,
				NUM_B   = 	8'b1000_0011,
				NUM_C   = 	8'b1100_0110,
				NUM_D   = 	8'b1010_0001,
				NUM_E   = 	8'b1000_0110,
				NUM_F   = 	8'b1000_1110,
				ALL_LIGHT = 8'b0000_0000,
				LIT_OUT = 	8'b1111_1111,
                LINE    =   8'b1011_1111;

    localparam MAX_10us     =   10'd999     ;
 	//reg 、wire define		
	reg		[3:0]	cm_hund	    ;//100cm
	reg		[3:0]	cm_ten	    ;//10cm
	reg		[3:0]	cm_unit	    ;//1cm
	reg		[3:0]	point_1	    ;//1mm
	reg		[3:0]	point_2	    ;//0.1mm
	reg		[3:0]	point_3	    ;//0.01mm
    reg     [9:0]   cnt_10us    ;
    reg     [7:0]   num         ;// 段选输出判断

	always @(posedge clk or negedge rstn)begin  
		if(!rstn)begin  
			cm_hund	<= 'd0;
			cm_ten	<= 'd0;
			cm_unit	<= 'd0;
			point_1	<= 'd0;
			point_2	<= 'd0;
			point_3	<= 'd0;
		end  
		else begin  
			cm_hund <= data_in / 10 ** 5;
			cm_ten	<= data_in / 10 ** 4 % 10;
			cm_unit <= data_in / 10 ** 3 % 10;
			point_1 <= data_in / 10 ** 2 % 10;
			point_2 <= data_in / 10 ** 1 % 10;
			point_3 <= data_in / 10 ** 0 % 10;
		end  
	end 

    // 修改后   段选

	always @(posedge clk or negedge rstn) begin
		if(!rstn) begin
			cnt_10us <= 10'd0;
		end
		else if(cnt_10us == MAX_10us) begin
			cnt_10us <= 10'd0;
		end
		else begin
			cnt_10us <= cnt_10us + 10'd1;
		end
	end

    // 数码管位移
    always @(posedge clk or negedge rstn) begin
        if(!rstn) begin
            sel <= 6'b111_110;
        end
        else if(cnt_10us == MAX_10us) begin
            sel <= {sel[0],sel[5:1]};
        end
        else begin
            sel <= sel;
        end
    end

    // 确定输出数字
    always @(*) begin
        case (sel)
			6'b01_1111	:    num = hex_data(point_3);
			6'b10_1111	:    num = hex_data(point_2);
			6'b11_0111	:    num = hex_data(point_1);
			6'b11_1011	:    num = hex_data(cm_unit);
			6'b11_1101	:    num = hex_data(cm_ten)	;
			6'b11_1110	:    num = hex_data(cm_hund);
			// 6'b11_1111	:    num = LINE;
			// 6'b11_1111	:    num = LIT_OUT;

            default         :    num = NUM_0;
        endcase
    end

    // 位选输出
    always @(posedge clk or negedge rstn) begin
        if(!rstn) begin
            seg <= LINE;
        end
        else begin
            case (num)
                NUM_0       :   seg <= NUM_0    ;
                NUM_1       :   seg <= NUM_1    ;
                NUM_2       :   seg <= NUM_2    ;
                NUM_3       :   seg <= NUM_3    ;
                NUM_4       :   seg <= NUM_4    ;
                NUM_5       :   seg <= NUM_5    ;
                NUM_6       :   seg <= NUM_6    ;
                NUM_7       :   seg <= NUM_7    ;
                NUM_8       :   seg <= NUM_8    ;
                NUM_9       :   seg <= NUM_9    ;
                LINE        :   seg <= LINE     ;
                LIT_OUT     :   seg <= LIT_OUT  ;
                ALL_LIGHT   :   seg <= ALL_LIGHT;
            endcase
        end
    end

    // 函数,4位输入,7位输出,判断要输出的数字
    function  [7:0]	hex_data; //函数不含时序逻辑相关
		input   [03:00]	data_i;//至少一个输入
		begin
			case(data_i)
				4'd0:hex_data = NUM_0;
				4'd1:hex_data = NUM_1;
				4'd2:hex_data = NUM_2;
				4'd3:hex_data = NUM_3;
				4'd4:hex_data = NUM_4;
				4'd5:hex_data = NUM_5;
				4'd6:hex_data = NUM_6;
				4'd7:hex_data = NUM_7;
				4'd8:hex_data = NUM_8;
				4'd9:hex_data = NUM_9;
				default:hex_data = ALL_LIGHT;
			endcase	
		end 
	endfunction

endmodule  

3、RTL视图

基于FPGA的超声波测距——数码管显示

4、效果

超声波测距


三、总结

数码管的前三位表示百、十、个的厘米单位,后三位为保留小数位,总体来说测距模块还是相对准确的。通过这次的操作,基本理解了超声波模块的使用驱动原理,对数码管的操作更加熟练。

四、参考资料

基于DE2 115开发板驱动HC_SR04超声波测距模块【附源码】文章来源地址https://www.toymoban.com/news/detail-455115.html

到了这里,关于基于FPGA的超声波测距——数码管显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于MAX-10 FPGA 超声波测距模块HC_SR04

    HC-SR04是一种基于超声波的测距模块。该模块向前15度内发送超声波并接收回响,通过发出超声波到收到回响的这个时间间隔计算前方的障碍物距离,可以用来给智能小车做障碍物监测。可提供2cm- 400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接

    2024年02月07日
    浏览(48)
  • 【嵌入式系统应用开发】FPGA——基于HC-SR04超声波测距

    硬件 DE2-115 HC-SR04超声波传感器 软件 Quartus 18.1 使用DE2-115开发板驱动HC-SR04模块,并将所测得数据显示到开发板上的数码管。 HC-SR04 超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为 HC-SR04 外观,

    2024年02月08日
    浏览(58)
  • FPGA一键测距仪之超声波模块篇

    FPGA一键测距仪之数码管篇 FPGA一键测距仪之[按键+控制+蜂鸣器]篇 FPGA一键测距仪之终篇 第一个FPGA小项目:基于BASYS3的超声波一键测距仪 本篇会对超声波测距模块进行详细的讲解,包括测距原理、各模块的时序图构思以及代码实现。 所用到的软件工具: Vivado 2019.1 Modelsim SE

    2024年02月02日
    浏览(46)
  • 基于STM32的超声波测距

    一、HC-SR04模块介绍 HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可高达3mm;模块包括超声波发射器、接收器、与控制电路。 模块的基本工作原理为: (1)采用 IO口 TRIG触发测距,给最少 10us的高电平信呈。 (2)模块自动发送 8个 40khz的方波,自动检测是

    2024年02月13日
    浏览(44)
  • 基于单片机超声波测距语音播放

    一、系统方案 本设计采用52单片机作为主控器,HC-SR04测距,液晶1602显示,按键设置报警阀值,语音报警。 二、硬件设计 原理图如下: 三、单片机软件设计 1、首先是系统初始化 uint dist; // 保存超声波模块测量到的结果 2、液晶显示程序 / / // 1602液晶写命令函数,cmd就是要写

    2024年02月09日
    浏览(47)
  • 基于STM32超声波测距系统设计

    随着社会的发展和科技的进步,人们对测距的要求越来越高,特别是在一些要求实时测距的场合,传统的测距方式已经无法满足人们的需求,而超声波测距由于其非接触和实时反馈的特点在生活中得到广泛应用。 本系统硬件部分由电源模块、控制模块、显示模块、报警模块、

    2024年02月04日
    浏览(52)
  • 基于单片机的超声波语音测距系统

    一、系统方案 超声波具有指向性强,能量消耗缓慢,在介质中传播的距离较远,因而超声波经常用于距离的测量,如测距仪和物位测量仪等都可以通过超声波来实现。利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制,并且在测量精度方面能达到工业实用的

    2024年02月10日
    浏览(51)
  • 基于c51单片机超声波测距仪

            整个系统由AT89C51,超声波电路,显示电路和报警电路,按键控制组成,系统复位后,首先对各模块进行初始化,初始化后根据超声波模块返回的回波进行数据计算,把数据显示到LMO16L液晶显示器上,并与设定的报警值相比较,小于报警值则蜂鸣器响起、指示灯亮

    2024年02月04日
    浏览(51)
  • 基于51单片机的超声波测距及温度显示

    (仿真+程序+PCB+原理图+设计报告) 功能介绍 具体功能: 1.超声波测距传感器HC-SR04、温度传感器DS18B20将检测的数据传给51单片机; 2.LCD1602实时显示测得的距离和温度; 3.按键可以设置距离的上下限; 4.距离超过设定范围,蜂鸣器+LED产生声光报警; ​演示视频: 基于5

    2024年04月24日
    浏览(49)
  • 基于STM32_HAL库实现超声波测距

    核心板               : STM32F103C8T6。 超声波测距模块 : HC-SR04超声波测距模块 实验目的            : 利用超声波测距,将测量的距离打印在串口并输出。 HC-SR04超声波测距模块介绍         接口定义:Vcc、 Trig(控制端——PA2)、 Echo(接收端——PA11)、 Gnd        

    2024年02月16日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包