Verilog 实现超声波测距

news2024/11/16 3:41:41

Verilog 实现超声波测距

教学视频: https://www.bilibili.com/video/BV1Ve411x75W?p=33&spm_id_from=pageDriver&vd_source=19ae31dff4056e52d2729a4ca212602b

超声波测距原理

参考资料:STM32的超声波测距程序_超声波测距stm32程序_VaderZhang的博客-CSDN博客

推荐一波自己的文章:STM32蓝牙控制循迹避障小车源代码——3.舵机、超声波测距模块_stem32超声波舵机代码_灵风_Brend的博客-CSDN博客

  • 超声波模块工作原理:
    输出TRIG触发测距,需要给最少10us的高电平信呈;
    模块自动发送8个40KHZ的方波,自动检测是否有信号返回;
    有信号返回,通过IO口ECHO输出高电平,高电平持续时间就是超声波从发射到返回的时间;
    测试距离=高电平持续时间*声速/2

需求分析与功能定义:

  • 每隔100ms时间,定时产生10us时间的TRIG高脉冲给到超声波测距模块,用于触发超声波测距模块工作
  • 采集回响信号ECHO的高脉冲保持时间
  • 将ECHO高脉冲保持时间换算成距离信息:s = 0.173*t
  • 人机交互

代码思路:(详细教学可以看最上面的链接)

代码组成:

在这里插入图片描述


vlg_en :输出clk_en信号,对输入时钟clk做分频计数,产生1us的时钟使能信号(计数单位为us)


module vlg_en #(
	parameter P_CLK_PERIORD = 20	//clk的时钟周期为20ms
)
( 
	input 		clk,
	input 		rst_n,
	
	output reg 	clk_en
);

localparam P_DIVCLK_MAX = 1000/P_CLK_PERIORD - 1;	//分频计数器的最大值
reg [7:0] r_divcnt;

///
//对输入时钟clk做分频计数,产生1us的时钟使能信号
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		r_divcnt <= 8'b0;
	else if(r_divcnt < P_DIVCLK_MAX)
		r_divcnt <= r_divcnt + 1'b1;
	else
		r_divcnt <= 8'b0;
end

///
//产生时钟使能信号
always @(posedge clk) begin
	if(r_divcnt == P_DIVCLK_MAX)
		clk_en <= 1'b1;
	else
		clk_en <= 1'b0;
end

endmodule

vlg_tirg :每隔100ms时间,定时产生10us时间的TRIG高脉冲给到超声波测距模块,用于触发超声波测距模块工作

module vlg_tirg
( 
	input 		clk,
	input 		rst_n,
	input 		clk_en,
	
	output reg 	trig
);

localparam P_TRIG_PERIORD_MAX = 100_000 - 1;	//100ms计数最大值
localparam P_TRIG_HIGH_MAX = 10;			//10us高脉冲保持时间

reg [16:0] tricnt;

///
//100ms周期计数
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		tricnt <= 'b0;
	else if(clk_en)begin
		if(tricnt < P_TRIG_PERIORD_MAX)
			tricnt <= tricnt + 1'b1;
		else
			tricnt <= 'b0;
	end		
end

///
//产生保持10us的trig信号
always @(posedge clk) begin
	if((tricnt > 'b0)&&(tricnt <= P_TRIG_HIGH_MAX))
		trig <= 1'b1;
	else
		trig <= 1'b0;
end

endmodule

上面两个信号的波形展示:

在这里插入图片描述

vlg_echo : 采集回响信号ECHO的高脉冲保持时间。(echo信号的高电平保持时间即为超声波往返的时间)

module vlg_echo
( 
	input 		clk,
	input 		rst_n,
	input 		clk_en,
	input 		echo,

	output reg [15:0] t_us
);

reg [1:0] r_echo;
wire pos_echo,neg_echo;
reg cnt_en;
reg [15:0] echo_cnt;

///
//对echo信号锁存两拍,获取边沿检测信号,产生计数使能信号cnt_en
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		r_echo <= 'b0;
	else
		r_echo <= {r_echo[0],echo};	//高位锁存,低位移位	
end

assign pos_echo = ~r_echo[1] & r_echo[0];
assign neg_echo = r_echo[1] & ~r_echo[0];

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		cnt_en <= 'b0;
	else if(pos_echo)
		cnt_en <= 1'b1;
	else if(neg_echo)
		cnt_en <= 1'b0;
	else ;
end

///
//对echo信号的高电平保持时间进行1us为单位的计数
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		echo_cnt <= 'b0;
	else if(!cnt_en)
		echo_cnt <= 'b0;
	else if(clk_en)
		echo_cnt <= echo_cnt + 1'b1;
	else ;
end	

///
//对echo_cnt计数最大值做锁存
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		t_us <= 'b0;
	else if(neg_echo)
		t_us <= echo_cnt;
end

endmodule

cal :将时间计算为距离。测试距离=高电平持续时间 * 声速/2。 (s = 0.173*t)

module cal
( 
	input 		clk,
	input 		rst_n,
	input [15:0] t_us,

	output [14:0] s_mm
);

/*	s=0.173*t
	s*4096=0.173*t*4096=709*t	 避免小数部分
	s=709*t/4096=709*t>>12
	
	709实现方法:  1)乘法器
				2)709=512+128+64+4+1
	本代码使用乘法器来实现。直接调用乘法器IP核
*/
wire [25:0] mult_result;

mult_gen_0 u_mult_gen_0 (
  .CLK(clk),  // input wire CLK
  .A(10'd709),      // input wire [9 : 0] A
  .B(t_us),      // input wire [15 : 0] B
  .P(mult_result)      // output wire [25 : 0] P
);

assign s_mm = mult_result[25:12];


endmodule

顶层文件 vlg_top

module vlg_top(
	input 	clk,
	input 	rst_n,
	
	output 	trig
);

localparam P_CLK_PERIORD = 20;


//接口声明
reg clk;
reg rst_n;
reg echo;

wire clk_en;
wire trig;
wire [15:0] t_us;
wire [14:0] s_mm;

//使能时钟产生模块
vlg_en #(
	.P_CLK_PERIORD (P_CLK_PERIORD)	//clk的时钟周期为20ns
)
u_vlg_en( 
	.clk 		(clk),
	.rst_n 		(rst_n),
	
	.clk_en 	(clk_en)
);

//产生触发信号trig
vlg_tirg u_vlg_tirg(
	.clk	(clk),
    .rst_n	(rst_n),
    .clk_en	(clk_en),

    .trig   (trig)
);

//测距模块的回响信号echo的高电平采集时间
vlg_echo u_vlg_echo(
	.clk	(clk),
	.rst_n	(rst_n),
	.clk_en	(clk_en),
	.echo	(echo),

	.t_us   (t_us)
);

//乘法器,计算距离
cal u_cal(
	.clk	(clk),
	.rst_n	(rst_n),
	.t_us	(t_us),

	.s_mm   (s_mm)
);

endmodule

调用乘法器IP核

点击IP核,输入MUL,进行下面的操作:

在这里插入图片描述


在这里插入图片描述

TB文件

`timescale 1ns/1ps

module tb_top();

reg clk;
reg rst_n;
reg echo;

wire [14:0] s_mm;

vlg_top u_vlg_top(
	.clk	(clk),
	.rst_n	(rst_n),

	.trig   (trig)
);

//产生时钟
initial clk = 1;
always #10 clk = ~clk;


//测试激励产生
initial begin
	rst_n = 0;
	echo = 0;
	#200;
	rst_n = 1;
	
end

//函数实现 s=0.173*t
function real function_t2s;
	input real t;
	begin
		function_t2s = 0.173*t;
	end
endfunction

integer tricnt = 0;
integer dly_time;

always @(posedge trig)begin
	tricnt = tricnt + 1;
	#5000;
	echo = 1;
	dly_time = 11+{$random}%26011;		//11<t<26011
	#500;
	$display("test %0d:\n dly_time=%0d us\n s=%0d mm\n",tricnt,dly_time,s_mm,function_t2s(dly_time));
	#(dly_time*1000);
	echo = 0;
end


endmodule

仿真结果

  • 仿真波形

在这里插入图片描述

  • 结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/930920.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cs231n assignment3 q5 Self-Supervised Learning for Image Classification

文章目录 嫌墨迹直接看代码Q5 Self-Supervised Learning for Image Classificationcompute_train_transform CIFAR10Pair.__getitem__()题面解析代码输出 simclr_loss_naive题面解析代码输出 sim_positive_pairs题面解析代码输出 compute_sim_matrix题面解析代码输出 simclr_lo…

37、springboot 为 spring mvc 提供的自动配置及对自动配置的一些自定义定制(大体思路)

springboot 为 spring mvc 提供的自动配置及对自动配置的一些自定义定制&#xff08;大体思路&#xff09; ★ Spring Boot主流支持两个MVC框架&#xff1a; Spring MVC&#xff08;基于Servlet&#xff09; Spring WebFlux&#xff08;基于Reactive&#xff0c;属于响应式AP…

开源双语对话语言模型 ChatGLM-6B 本地私有化部署

本文首发于&#xff1a;https://www.licorne.ink/2023/08/llm-chatglm-6b-local-deploy/ ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型&#xff0c;基于 General Language Model (GLM) 架构&#xff0c;具有 62 亿参数。结合模型量化技术&#xff0c;用户可以在消费级…

人员跌倒检测识别预警

人员跌倒检测识别预警系统通过pythonopencv深度学习网络模型架构&#xff0c;人员跌倒检测识别预警系统实时监测老人的活动状态&#xff0c;通过图像识别和行为分析算法&#xff0c;对老人的姿态、步态等进行检测和识别&#xff0c;一旦系统检测到跌倒事件&#xff0c;立即发出…

Vue2向Vue3过度Vuex核心概念state状态

目录 1 核心概念 - state 状态1.目标2.提供数据3.访问Vuex中的数据4.通过$store访问的语法5.代码实现5.1模板中使用5.2组件逻辑中使用5.3 js文件中使用 2 通过辅助函数 - mapState获取 state中的数据1.第一步&#xff1a;导入mapState (mapState是vuex中的一个函数)2.第二步&am…

Dubbo—流量管控

此任务基于一个简单的线上商城微服务系统演示了 Dubbo 的流量管控能力。 线上商城的架构图如下&#xff1a; 系统由 5 个微服务应用组成&#xff1a; Frontend 商城主页&#xff0c;作为与用户交互的 web 界面&#xff0c;通过调用 User、Detail、Order 等提供用户登录、商品…

为什么使用Nacos而不是Eureka(Nacos和Eureka的区别)

文章目录 前言一、Eureka是什么&#xff1f;二、Nacos是什么&#xff1f;三、Nacos和Eureka的区别3.1 支持的CAP3.2连接方式3.3 服务异常剔除3.4 操作实例方式 总结 前言 为什么如今微服务注册中心用Nacos相对比用Eureka的多了&#xff1f;本文章将介绍他们之间的区别和优缺点…

推荐前 6 名 JavaScript 和 HTML5 游戏引擎

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建3D应用场景 事实是&#xff0c;自从引入JavaScript WebGL API以来&#xff0c;现代浏览器具有直观的功能&#xff0c;使它们能够渲染更复杂和复杂的2D和3D图形&#xff0c;而无需依赖第三方插件。 你可以用纯粹的JavaScript开…

Nuxt3打包部署到Linux(node+pm2安装和运行步骤+nginx代理)

最近&#xff0c;我们项目组的工作接近尾声&#xff0c;需要把项目部署上线。由于前端第一次使用Nuxt3框架&#xff0c;后端也是第一次部署Nuxt3项目&#xff0c;所以刚开始出现了很多问题。在我上网搜索很多教程后&#xff0c;得到了基本的流程。 1.服务器安装node.js环境 N…

Linux常用命令_文件搜索命令

文章目录 1. 文件搜索命令find2. 其他搜索命令2.1 文件搜索命令&#xff1a;locate2.2 文件搜索命令&#xff1a;which2.3 文件搜索命令&#xff1a;whereis2.4 文件搜索命令&#xff1a;grep 1. 文件搜索命令find 2. 其他搜索命令 2.1 文件搜索命令&#xff1a;locate 作为f…

c语言练习题30:判断一个数是否为2^n

判断一个数是否为2^n 思路&#xff1a;2^n中只有一个1故可以通过n&(n-1)是否为0来判断。 代码&#xff1a;

Android 之 WindowManager (窗口管理服务)

本节引言&#xff1a; 本节给大家带来的Android给我们提供的系统服务中的——WindowManager(窗口管理服务)&#xff0c; 它是显示View的最底层&#xff0c;Toast&#xff0c;Activity&#xff0c;Dialog的底层都用到了这个WindowManager&#xff0c; 他是全局的&#xff01;该类…

用MFC打开外部程序

在MFC&#xff08;Microsoft Foundation Classes&#xff09;中&#xff0c;你可以使用ShellExecute函数来打开Notepad并加载指定的文件。ShellExecute函数是Windows API的一部分&#xff0c;它可以执行与操作系统相关的操作&#xff0c;例如打开文件、运行程序等。 以下是在M…

VBJSON报错:缺少:语句结束

项目中使用JSON库VBJSON时报错&#xff1a; 编译错误&#xff1a;缺少&#xff1a;语句结束 cJSONScript和cStringBuilder报相同的错误&#xff0c;都在第一行: VERSION 1.0 CLASS 研究了半天没啥结果&#xff0c;之前使用这个库的时候没有什么问题&#xff0c;所以判定是当前…

51WORLD李熠:地球克隆计划就像攀登珠峰

提起数字化这个词&#xff0c;相信大家早已耳熟能详。然而数字化世界的意义是什么&#xff1f;它又给我们带来了什么&#xff1f;是让我们的真实世界更加美好&#xff1f;还是让我们沉迷于虚拟世界&#xff1f; 对于以上这些问题&#xff0c;51WORLD创始人兼CEO李熠给出的答案是…

基于Java+SpringBoot+Vue前后端分离医院资源管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

阿里云将关停代销业务

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 阿里云自从逐渐分拆独立之后&#xff0c;做了很多调整。最近它又做了一个大动作&#xff1a;据DoNews消息&#xff0c;阿里云将会在今年9月30日之前&#xff0c;全面关停代销业务。 这件事实际上…

21.图的应用

目录 一. 最小生成树 &#xff08;1&#xff09;普里姆&#xff08;Prim&#xff09;算法 &#xff08;2&#xff09;克鲁斯卡尔&#xff08;Kruskal&#xff09;算法 二. 最短路径 &#xff08;1&#xff09;Dijkstra(迪杰斯特拉)算法 &#xff08;2&#xff09;Floyd(弗…

Pygame编程(1)初始化和退出模块

初始化和退出模块 pygame使用基础流程 初始化模块设置主屏窗口程序主循环&#xff08;处理键盘、鼠标、游戏杆、触摸屏等事件&#xff09;退出模块终止程序 import sys import pygame from pygame.locals import *# 1.初始化模块 pygame.init()# 2.设置主屏窗口 display pyg…

【精品】基于VUE3的 电商详情 图片显示模块

效果 组件 <template><div class"goods-imgs"><div class"imgs-show"><img :src"mainImage" alt"大图" /></div><ul class"img-thumbnail"><li v-for"(item, index) in image…