基于FPGA的超声波测距——UART串口输出
文章目录
- 前言
- 一、超声波模块介绍
- 1、产品特点
- 2、超声波模块的时序图
- 二、系统设计
- 1、系统模块框图
- 2、RTL视图
- 三、源码
- 1、div_clk_us(1us的分频)
- 2、产生驱动超声波的信号
- 3、串口发送模块
- 4、HC_SR04_uart(顶层文件)
- 四、效果
- 五、总结
- 六、参考资料
前言
环境:
1、Quartus18.0
2、vscode
3、板子型号:EP4CE10F17C8
4、超声波模块:HC_SR04
要求:
使用 EP4CE10F17C8开发板驱动 超声波检测模块(HC_SR04 ),并将所测得数据显示到串口助手上。
一、超声波模块介绍
1、产品特点
HC-SR04超声波测距模块可提供2cm-400cm的非接触式距离感测功能,测距精度可达高到3mm;模块包括超声波发射器、接收器与控制电路。
基本工作原理:
(1)采用IO口 TRIG触发测距,给最少10us的高电平信呈。
(⑵)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;

2、超声波模块的时序图

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

2、RTL视图

三、源码
1、div_clk_us(1us的分频)
/**************
芯片晶振为50MHZ,HC_SR04需要一个10us的以上脉冲触发信号
所以这里我们需要对系统时钟进行分频,方便我们产生10us的持续电平
**************/
module div_clk_us (input sys_clk,input sys_rst_n,output wire clk_us
);//根据晶振换算,1us只需要计数50次即可parameter [5:0] MAX_us = 6'd49;
reg [5:0] cnt;
always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)begincnt <= 6'd0;endelse if(cnt == MAX_us)begincnt <= 6'd0;endelse begincnt <= cnt + 6'd1;end
end
assign clk_us = cnt >= MAX_us;
endmodule
2、产生驱动超声波的信号
/****************
根据分频的1us时钟,产生一个持续10us的电平用于驱动HC_SR04
最好是稍微大于10us,这样稳妥一些
****************/
module trig_driver(input sys_us ,//1us时钟input sys_rst_n ,output trig //驱动超声波的信号
);parameter T = 19'd29_9999;//设置触发信号的周期,这里设置得越小,其触发越频繁,应该返回的距离更新更频繁reg [18:0] cnt;always @(posedge sys_us) begin// or negedge sys_rst_nif(!sys_rst_n)begincnt <= 19'd0;endelse if(cnt == T)begincnt <= 19'd0;endelse begincnt <= cnt + 1'd1;end
end
//15us的高电平
assign trig = (cnt <15 ) ? 1'b1 : 1'b0;//正确的,只是时间太短,观察不到,目前应该是串口问题
endmodule
3、串口发送模块
module uart_send
#(parameter CLK = 26'd50000000 , // 时钟频率parameter BAUD = 17'd115200 // 波特率
)
(input wire clk ,input wire rstn , input wire [7 : 0] data_in , // 需要发送的数据input wire flag_in , // 数据接收标志位,既发送标志位output wire tx_done , output reg UART_tx // 串口输出位
);localparam Baud_Clk = CLK/BAUD ; // 传输每个 Baud 需要的时钟数reg tx_en ; // 发送使能reg flag_bit ; // 比特标志位,采用下降沿发送reg [8 : 0] cnt_baud ; // 波特率计数器reg [3 : 0] cnt_bit ; // 比特计数器assign tx_done = cnt_bit == 4'd9 && flag_bit == 1'b1;// 发送使能always @(posedge clk or negedge rstn) beginif(!rstn) begintx_en <= 1'b0;end// 已经发送了十位 bit 并且到达下一个下降沿,输入只需要判断到数据位最后一位,输出则需要判断完整输出else if(cnt_bit == 4'd9 && flag_bit == 1'b1) begintx_en <= 1'b0;endelse if(flag_in == 1'b1) begintx_en <= 1'b1;endend// 波特计数器always @(posedge clk or negedge rstn) beginif(!rstn) begincnt_baud <= 9'd0;end// 传输完成所有波特或者使能失效,表示发送结束else if(cnt_baud == Baud_Clk - 1'b1 || tx_en == 1'b0) begincnt_baud <= 9'd0;endelse begincnt_baud <= cnt_baud + 9'd1;endendalways @(posedge clk or negedge rstn) beginif(!rstn) beginflag_bit <= 1'b0;end// 只有刚开始发送的一瞬间会产生一个时钟周期上升沿和下降沿else if(cnt_baud == 9'd1) beginflag_bit <= 1'b1;endelse beginflag_bit <= 1'b0;endend// 计数10分有效数据位always @(posedge clk or negedge rstn) beginif(!rstn) begincnt_bit <= 4'd0;end// 已经发送了十位 bit 并且到达下一个下降沿else if(cnt_bit == 4'd9 && flag_bit == 1'b1) begincnt_bit <= 4'd0;end// 使能有效,下降沿发送数据else if(flag_bit == 1'b1 && tx_en == 1'b1) begincnt_bit <= cnt_bit + 4'd1;endelse begincnt_bit <= cnt_bit;endend// 满足 RS232 协议 起始位为 0,停止位为 1,并按位输出always @(posedge clk or negedge rstn) beginif(!rstn) beginUART_tx <= 1'd1;end// 下降沿发送数据else if(flag_bit == 1'b1) begincase (cnt_bit)0: UART_tx <= 1'd0 ;1: UART_tx <= data_in[0] ;2: UART_tx <= data_in[1] ;3: UART_tx <= data_in[2] ;4: UART_tx <= data_in[3] ;5: UART_tx <= data_in[4] ;6: UART_tx <= data_in[5] ;7: UART_tx <= data_in[6] ;8: UART_tx <= data_in[7] ;9: UART_tx <= 1'd1 ;default: UART_tx <= 1'd1 ;endcaseendend
endmodule //UART_send
4、HC_SR04_uart(顶层文件)
module HC_SR04_uart(input sys_clk ,input sys_rst_n ,input echo ,input uart_rx , // 串口输入 output trig , output uart_tx //串口发送端口
);
wire clk_us;
wire [18:0] data_o_r;//待发送的数据
//时钟分频
div_clk_us div_clk_us_inst(/*input */ .sys_clk (sys_clk ),/*input */ .sys_rst_n (sys_rst_n),/*output*/ .clk_us (clk_us)
);
//产生驱动超声波信号
trig_driver trig_driver_inst(/*input */ .sys_us (clk_us),//1us时钟/*input */ .sys_rst_n (sys_rst_n),/*output*/ .trig (trig)//驱动超声波的信号
);
//对返回来的echo信号进行计算得出距离
echo_driver echo_driver_inst(/*input */ .sys_clk (sys_clk),/*input */ .sys_us (clk_us),/*input */ .sys_rst_n (sys_rst_n),/*input */ .echo (echo),/*output [18:0]*/ .data_o (data_o_r)//检测距离,保留三位小数,*1000实现
);
//初步想法是使用串口发送模块直接操作,不需要串口回环,否则需要发送到接收,接收模块再发送给发送模块,发送模块再发送给PC
uart_driver2 uart_driver2_inst(.clk (sys_clk ),.rstn (sys_rst_n),.data_in (data_o_r ),.UART_rx (uart_rx),.UART_tx (uart_tx )
);
endmodule
四、效果
FPGA串口输出测距信息
五、总结
前面写过FPGA测距的数码管显示,STM32的测距串口输出,其实这篇文章的内容之前完成过。由于前面又学习了一边串口回环,所以又敲了一遍,实现一下FPGA的串口输出。虽然做过,但是还是折腾了一天,仿真、SignalTap II 抓了一下午的信号。但这次比上一次的理解更加深刻,收获更多。
六、参考资料
1、基于FPGA的超声波测距——数码管显示
2、源码:https://github.com/no1jiangjiang/HC-SR04_uart_FPGA
相关文章:
基于FPGA的超声波测距——UART串口输出
文章目录 前言一、超声波模块介绍1、产品特点2、超声波模块的时序图 二、系统设计1、系统模块框图2、RTL视图 三、源码1、div_clk_us(1us的分频)2、产生驱动超声波的信号3、串口发送模块4、HC_SR04_uart(顶层文件) 四、效果五、总结六、参考资料 前言 环境: 1、Quar…...
Python web实战之 Django 的 MVC 设计模式详解
技术栈:Python、Django、HTML、CSS、JavaScript。 概要 在 Web 开发中,MVC(Model-View-Controller)模式是一种非常常见的设计模式,它可以帮助我们更好地管理代码,提高代码的可维护性。今天就介绍如何使用 …...
Stable Diffusion VAE:改善图像质量的原理、选型与使用指南
VAE Stable Diffusion(稳定扩散)是一种用于生成模型的算法,结合了变分自编码器(Variational Autoencoder,VAE)和扩散生成网络(Diffusion Generative Network)的思想。它通过对变分自…...
maven里面没有plugins dependence问题解决
说明:今天在做Nacos、Dubbo整合的时候,在父模块中做了版本限制,出错后就又把版本控制什么都删掉,回退到最开始的状态,此时父模块下面的服务右侧的 maven里面没有plugins dependence ,然后项目全都报错。 问…...
Wi-Fi 6技术详解
1. 介绍 Wi-Fi 6,也称为802.11ax,是Wi-Fi技术的最新标准。它是对之前标准Wi-Fi 5(802.11ac)的升级和改进,旨在提供更高的速度、更大的容量、更好的性能和更高的可靠性。Wi-Fi 6技术的引入为无线网络带来了革命性的变化…...
【LeetCode】446. 等差数列划分II -- 子序列
题目链接 文章目录 1. 思路讲解1.1 dp表的创建1.2 状态转移方程1.3 使用哈希表找到k1.4 初始化1.5 返回值1.6 该题坑爹的一点 2. 代码编写 1. 思路讲解 我们要知道以某个位置为结尾的子序列的数量,可以通过它的以上一位置的为结尾的子序列的数量得知,也…...
几个似非而是的注释问题
C 语言的注释可以出现在 C 语言代码的任何地方。这句话对不对?这是我当学生时我 老师问的一个问题。我当时回答是不对。好,那我们就看看下面的例子: A ), int/*...*/i; B ), char* s"…...
【设计模式|上】创建型模式
every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 设计模式(上): 简单工厂模式工厂模式抽象工厂模式建造者模式单例模式 1. 正文 1.1 创建型(Creational Patterns) …...
【JS】类 class
【JS】类 class 定义类类的方法类继承静态方法 类(class)是用于创建对象的模板。 我们使用 class 关键字来创建一个类,类体在一对大括号 {} 中,我们可以在大括号 {} 中定义类成员的位置,如方法或构造函数。 每个类中…...
Ubuntu安装harbor(http模式)并随便上传一个
Ubuntu安装harbor(http模式) docker和harbor的介绍就免了,都不知道啥东西,还安装搞毛 先安装docker环境 不要问,软件源之类的配置,挨个梭就行 sudo apt update sudo apt install apt-transport-https ca…...
《向量数据库指南》——腾讯云向量数据库Tencent Cloud Vector DB正式上线公测!提供10亿级向量检索能力
8月1日,腾讯云向量数据库(Tencent Cloud Vector DB)已正式上线公测。在腾讯云官网上搜索“向量数据库”,就可以正式体验该产品。 腾讯云向量数据库不仅能为大模型提供外部知识库,提高大模型回答的准确性,还可广泛应用于推荐系统、文本图像检索、自然语言处理等 AI 领域。…...
1分钟解决github push/pull报错443
1.打开https://www.ipaddress.com/ 2.复制如图IP地址 3.文件夹打开C:\Windows\System32\drivers\etc,复制hosts文件,粘贴到桌面 4.在桌面用记事本打开复制过来的hosts 5.在末尾加上一行,IP写刚才复制的 6.复制桌面的hosts,粘贴回C:\Window…...
vue3学习-ref引用
模板引用 使用特殊的 refattribute 允许再特定的Dom或组件被挂在后,获取他的直接引用。 import { ref } form vue const input ref(null) <input ref"input"/>注意:只可以在组件挂载后才能访问模板引用 #如果你需要侦听一个模板引用 r…...
Docker 容器转为镜像
# 容器转成镜像并指定镜像名称与版本号 # commit 时原有容器挂载的目录是不会被写入到新的镜像中去的,数据卷相关的都不会生效 # 但是 root 目录下新建的内容会写入到新的镜像中去 $ docker commit 容器ID 新镜像名称:版本号 $ docker commit -m"描述信息"…...
阿里云服务器免费试用及搭建WordPress网站
文章目录 前言一、免费试用1、选择使用产品2、进行产品配置3、远程连接阿里云服务器①、重置实例密码②、SecureCRT 远程链接③、Workbench 远程链接二、搭建 WordPress 网站1、开放搭建 WordPress 需要的端口2、搭建 LAMP 环境①、Linux 系统升级和更新源②、安装 Apache2③、…...
整流二极管型号汇总,超齐全
整流二极管是什么二极管?查看资料可知,整流二极管是一种将交流电能转变为直流电能的半导体器件,可见整流二极管的作用重在“整流”。整流二极管主要用于各种低频半波整流电路,如需达到全波整流需连成整流桥使用。近日,…...
MongoDB 操作命令
创建database 有就切换没有创建 useMydatabase 显示数据库:show dbs显示该database下的 bson对象 show collections 显示该bson下的具体内容**mydatabase.mycollection.find()**查询该bson对象内容**且查询****mydatabase.mycollection.find({a:,b:})****或查询****…...
markdown高级写作技巧汇总
文章目录 1 代码diff2 待办事项3 图片设置宽高4 折叠5 锚点链接实现方式① Markdown 原始写法 [名称](#id)② HTML 语法 名称 6 目录树7 换行 1 代码diff 如果你做过代码 Code Review,对下面这种效果肯定很熟悉 // 数组去重 const unique (arr)>{ - return A…...
SpringBoot自动配置原理入门级理解
简单理解 spring中,我们配置一个bean有两种方式,一种是xml标签的形式,一种是通过java类的形式。那么自动装配就是通过java类的形式来配置bean。 不同的是,springboot将这些我们需要的bean提前配置好了以java类的形式存放在META-I…...
2023 08.02 小记与展望
碎碎念系列更新 算是坚持的第一个月(每个月更新一次,上次是6.29) 主要对上月工作进行总结,并对后续学习内容进行规划。 一、关于工作 7月工作主要涉及以下方面: 1、公司自研APP维护(主要是接口更新和修改…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...
Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...
