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

news2024/11/27 0:17:09

文章目录

  • 一、介绍超声波测距模块HC_SR04
  • 二、模块框图
  • 三、模块编写
    • 1. 测距信号源
    • 2. 距离计算
    • 3. 数码管模块
    • 4. 顶层模块
  • 四、实验现象
  • 总结


一、介绍超声波测距模块HC_SR04

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

该模块的时序图如下:
在这里插入图片描述
在这里插入图片描述
我们在编写代码的时候,想要发出测距命令,需要先保持触发信号输入(trig引脚)为低电平,然后保持大于10us的高电平,再变成低电平即可(时序图第一行所示)。

发出测距命令后,回响信号输出(echo引脚)会保持一段时间的高电平,这个高电平的持续时间与距离有关。我们在FPGA编写代码测量高电平持续时间,然后将时间转化为距离即可。

经过测试,得到以下结论:
1、发送测距的时候,每个脉冲之间的间隔不要过近,我用的间隔是300ms,即每300ms测一次距离,也可以根据需要修改。
2、接收端高电平时间与距离的关系式是:距离(cm)= 高电平持续时间(us)x 0.034cm / 2 (除以2是因为持续时间是往返时间,除以2才是单程时间)

二、模块框图

我们需要设计以下模块:
1、测距信号源模块,输入时钟与复位,每隔300ms输出15us高电平。

2、距离计算模块,输入时钟、复位与回响信号echo,输出距离(cm)

3、数据显示模块,将得到的距离可视化,我用的是2个1位数码管模块(小脚丫自带两个1位共阴极数码管)

4、顶层模块

框图如下:
在这里插入图片描述

三、模块编写

1. 测距信号源

在此模块,写一个计时周期为300us的循环计数器,当计数器值小于15时输出高电平,其他时候输出低电平即可。
代码如下:

module trigger_send #(
    parameter TIME_1S = 12_000_000
) (
    input   clk ,
    input   rst_n   ,
    output  trigger
);

//1us生成
wire clk_1us;
PLL UPLL(
	.inclk0 (clk),
	.c0 (clk_1us)
);

reg [25:0] cnt_1us;
always @(posedge clk_1us or negedge rst_n) begin
    if (!rst_n) begin
        cnt_1us <= 20'd0;
    end
    else if (cnt_1us == 20'd300_000 - 1)begin
        cnt_1us <= 20'd0;
    end
	 else begin
        cnt_1us <= cnt_1us + 1'b1;
    end
end

assign trigger = cnt_1us < 15 ? 1'b1 : 1'b0;

endmodule

2. 距离计算

这个模块输入了HC_SR04的回响引脚,要做的就是计算它的高电平持续时间,并转化为距离数据输出。

这里持续时间的单位用us最合适,因此同样生成一个1us时钟,用这个时钟监测回响信号的上升沿与下降沿。检测到上升沿,就每过一个时钟周期就把计时器数值加1(可以自己设置上限,表示最大检测距离);等检测到下降沿,就把计时器的数据保存起来,然后把计时器清空准备下次计时。

拿到保存好的计时后,使用上文提到的公式计算出距离输出。

代码如下:

module data_rec #(
    parameter TIME_1S = 12_000_000
) (
    input   clk ,//系统时钟
    input   rst_n   ,//复位
    input   rec_data    ,//回响,早知道取名echo了
    output  [11:0] distance	//计算好的距离
);
//锁相环生成1us周期时钟,因为后面的计时单位全是1us,这样方便
wire clk_1us;
PLL UPLL(
	.inclk0 (clk),
	.c0 (clk_1us)
);

//给回响信号打拍,检测上升沿下降沿
reg rec_data2;
reg rec_data3;
wire rec_negedge;
wire rec_posedge;
assign rec_negedge = (!rec_data2) && rec_data3;
assign rec_posedge = rec_data2 && (!rec_data3);
always @(posedge clk_1us or negedge rst_n) begin
    if (!rst_n) begin
        rec_data2 <= 1'b0;
    end
    else begin
        rec_data2 <= rec_data;
    end
end
always @(posedge clk_1us or negedge rst_n) begin
    if (!rst_n) begin
        rec_data3 <= 1'b0;
    end
    else begin
        rec_data3 <= rec_data2;
    end
end

//计时启动标志,上升沿启动,下降沿结束
reg flag;
always @(posedge clk_1us or negedge rst_n) begin
    if (!rst_n) begin
        flag <= 1'b0;
    end
    else if (rec_posedge)begin
        flag <= 1'b1;
    end
    else if (rec_negedge)begin
        flag <= 1'b0;
    end
    else begin
        flag <= flag;
    end
end

//计时器数值,flag期间计数,有下降沿就清0,急了多少数就是保持了多少us,因为是用1us时钟驱动的
reg [14:0] cnt_1us;
always @(posedge clk_1us or negedge rst_n) begin
    if (!rst_n) begin
        cnt_1us <= 15'd0;
    end
    else if (rec_negedge)begin
        cnt_1us <= 15'd0;
    end
    else if (flag && cnt_1us < 15'd15_000)begin
        cnt_1us <= cnt_1us + 1'b1;
    end
    else begin
        cnt_1us <= cnt_1us;
    end
end

//因为计时器结束计时会变0,因此要用另外的变量,在它清0的时候把值保存下来
reg [14:0] high_time;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        high_time <= 15'd0;
    end
    else if (rec_negedge)begin
        high_time <= cnt_1us ;
    end
    else begin
        high_time <= high_time;
    end
end

//计算距离,Verilog不能直接用浮点数,就这样实现乘以0.017
//为什么不是0.034看前面
reg [11:0] distance_buf;
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        distance_buf <= 12'd0;
    end
    else begin
        distance_buf <= high_time * 17 / 1000;
    end
end
assign distance = distance_buf;

endmodule

3. 数码管模块

距离模块的distance就是测到的距离,你拿去数码管输出,串口打印都可以。我的小脚丫自带两个1位的共阴极数码管,就用它们来显示,毕竟自己在面包板上给数码管插线插电阻还是挺麻烦的。

用的时候取出测的距离的十位个位分别给两个模块就行。

1位七段式共阴极数码管十进制显示模块如下:

module nixietube_1 (
    input   clk,
    input   rst_n,
    input   [3:0]   din, //输入0-9
    output  drive_out, //使能
    output  [6:0]   _dig, //输出数码管
    output  dot_out //小数点要亮吗
);
//dot小数点输出
assign dot_out = 1'b0;

//使能,阴极为0
assign drive_out = 1'b0;

//dig段选输出
parameter   ZER = 7'b0111111,
            ONE = 7'b0000110,
            TWO = 7'b1011011,
            THR = 7'b1001111,
            FOU = 7'b1100110,
            FIV = 7'b1101101,
            SIX = 7'b1111101,
            SEV = 7'b0000111,
            EIG = 7'b1111111,
            NIN = 7'b1101111;
            
reg [6:0]   dig;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        dig <= ZER;
    end
    else begin
        case (din)
            0 : dig <= ZER;
            1 : dig <= ONE;
            2 : dig <= TWO;
            3 : dig <= THR;
            4 : dig <= FOU;
            5 : dig <= FIV;
            6 : dig <= SIX;
            7 : dig <= SEV;
            8 : dig <= EIG;
            9 : dig <= NIN;
            default : dig <= ZER;
        endcase
    end
end

assign _dig = dig;

endmodule

4. 顶层模块

module Ultrasound  (
    input   clk,
    input   rst_n,
    input   rec_data    ,
    output  trigger ,
    output  [6:0]   dig1,
	 output  [6:0]   dig2,
    output  dot1,
	 output  dot2,
	 output  drive1,
	 output  drive2
); 
    trigger_send u_trigger_send(
        .clk (clk),
        .rst_n (rst_n),
        .trigger (trigger)
    );

    wire [11:0] distance;
    data_rec u_data_rec(
        .clk (clk),
        .rst_n (rst_n),
        .rec_data (rec_data),
        .distance (distance)
    );
		
	 nixietube_1 u_nixietube_1(
        .clk (clk),
        .rst_n (rst_n),
        .din    ((distance/10)%10),
        ._dig (dig1),
        .dot_out (dot1),
		  .drive_out (drive1)
    );
	 
	 nixietube_1 u_nixietube_2(
        .clk (clk),
        .rst_n (rst_n),
        .din    ((distance/1)%10),
        ._dig (dig2),
        .dot_out (dot2),
		  .drive_out (drive2)
    );

endmodule  

引脚设置的时候,两个数码管,时钟按照小脚丫的原理图来设置,trig与echo自己设置,复位键可以用它自带的按钮。

四、实验现象

在这里插入图片描述

总结

超声波模块主要是要将模块时序搞清楚,建立测距信号源模块,距离计算模块,数据显示模块。

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

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

相关文章

第一章:简单的C程序设计基础

一、C语言词汇 在C语言中使用的词汇分为&#xff1a;关键字、标识符、常量、运算符、分隔符、注释符等。 1.1关键字 1.2标识符 在程序中使用的变量名或函数名等统称为标识符&#xff1b;标识符的命名规则如下&#xff1a; &#xff08;C语言区分大小写&#xff09; 不能是关…

一个简单的基于C/S模型的TCP通信实例

1 TCP协议 1.1 概念 TCP是一种面向连接的、可靠的协议&#xff0c;有点像打电话&#xff0c;双方拿起电话互通身份之后就建立了连接&#xff0c;然后说话就行了&#xff0c;这边说的话那边保证听得到&#xff0c;并且是按说话的顺序听到的&#xff0c;说完话挂机断开连接。也…

2023 华为 Datacom-HCIE 真题题库 08--含解析

单项选择 1.[试题编号&#xff1a;190385] &#xff08;单选题&#xff09;以下关于BGP/MPLSIPVPN路由交互的描述&#xff0c;错误的是哪一项? A、PE与CE之间交互的是IPv4路由信息 B、出口PE可以通过BGP、IGP或静态路由的方式向远端CE发送IPv4路由 C、入口PE将从CE接收到的I…

数组(1)

文章目录 目录1. 一维数组的创建和初始化1.1 一维数组的创建1.2 一维数组的初始化 2. 一维数组的使用3. 一维数组在内存中的存储4. 二维数组的创建和初始化4.1 二维数组的创建4.2 二维数组的初始化 5. 二维数组的使用6. 二维数组在内存中的存储7. 数组越界8. 数组作为函数参数 …

chatgpt赋能python:Python自动填表单:提高工作效率的好帮手

Python 自动填表单&#xff1a;提高工作效率的好帮手 在现代社会中&#xff0c;表单已成为我们日常工作中不可或缺的一部分。填表单虽然看似简单&#xff0c;但是时间一长&#xff0c;不仅会影响工作效率&#xff0c;还会带来心理负担。幸运的是&#xff0c;Python 自动填表单…

Linux-0.11 boot目录bootsect.s详解

Linux-0.11 boot目录bootsect.s详解 模块简介 bootsect.s是磁盘启动的引导程序&#xff0c;其概括起来就是代码的搬运工&#xff0c;将代码搬到合适的位置。下图是对搬运过程的概括&#xff0c;可以有个印象&#xff0c;后面将详细讲解。 bootsect.s主要做了如下的三件事: 搬…

doris---Rollup

Rollup 3.5.1基本概念 通过建表语句创建出来的表称为 Base 表&#xff08;Base Table,基表&#xff09; 在 Base 表之上&#xff0c;我们可以创建任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的&#xff0c;并且在物理上是独立存储的。 Rollup表的好处&#xff…

C#调用FreeSpire.PDF获取PDF文档中使用的字体

除了图片之外&#xff0c;电子文件中使用的字体都必须要在本机中安装才能正常查看文字&#xff08;word缺少字体的话会自动使用相似或默认字体&#xff09;&#xff0c;要想知道电子文件中使用的字体&#xff0c;可以将电子文件转换为PDF文件&#xff08;如果是打印成PDF的话&a…

chatgpt赋能python:Python收集数据在SEO中的重要性

Python 收集数据在 SEO 中的重要性 随着互联网的发展&#xff0c;搜索引擎对于用户获取信息的重要性日益增加。SEO&#xff08;搜索引擎优化&#xff09;一直是每个网站必须考虑的问题。Python 收集数据在 SEO 中可以发挥重要的作用&#xff0c;帮助网站提高排名。下面我们来详…

Solidity拓展:数学运算过程中数据长度溢出的问题

在数学运算过程中假如超过了长度则值会变成该类型的最小值&#xff0c;如果小于了该长度则变成最大值 数据上溢 uint8 numA 255; numA;uint8的定义域为[0,255]&#xff0c;现在numA已经到顶了&#xff0c;numA会使num变成0(由于256已经超过定义域&#xff0c;它会越过256&…

结构体 --- C语言

目录 1.结构体的声明 2.结构体变量的定义和初始化 3.结构体成员访问 4.结构体传参 1.结构体的声明 结构是一些值的集合&#xff0c;这些称为成员变量&#xff0c;结构的每个成员可以是不同类型的变量。 而数组是一组类型相同的元素的集合。 生活中的描述 人&#xff1a;名…

测试C#分词工具jieba.NET(续1:提取关键词及并行分词)

jieba.NET支持通过两种算法提取文本关键词&#xff1a;TF-IDF算法和TextRank算法&#xff0c;关于这两种算法的介绍详见参考文献10-11&#xff0c;在jieba.NET中对应的类为TfidfExtractor和TextRankExtractor&#xff0c;这两个分词都都支持调用ExtractTags和ExtractTagsWithWe…

文件上传至公有云Nos及对接CDN

项目开发中&#xff0c;需要将图片文件上传至网易公有云的Nos,并且结合CDN做加速服务&#xff0c;记录一下开发过程。流程图&#xff1a; 1. 文件上传到公有云Nos 网易对象存储服务&#xff08;Netease Object Storage&#xff0c;简称NOS&#xff09;是网易数帆提供的高可用…

pycharm环境下打开Django内置的数据库Sqlite出错问题解决

问题描述 在数据库库文件中写入一条记录后&#xff0c;在pycharm的terminal终端下执行查看表的命令出错 执行语句为&#xff1a; 连接数据库报错 python manage.py dbshell CommandError: You appear not to have the sqlite3 program installed or on your path. Error:…

JavaScript之DOM基础

1. 初识DOM DOM: 文档对象模型 是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。 w3c已经定义了一系列的DOM接口&#xff0c;通过这些DOM接口可以改变网页的内容&#xff0c;结构和样式。 DOM树&#xff1a;文档&#xff1a;一个页面就是一个文档, DOM中使用d…

Android逆向猿人学2022年app比赛第四题grpc与Protobuf使用(步步验证)

教程 前言一、起步二、抓包三、分析四、验证五、HOOK借鉴 前言 前面2-3题和第一题解题思路基本上一样的&#xff0c;这里就不出教程了&#xff0c;这篇文章比较繁琐&#xff0c;基本上描述了我做这题的思路&#xff0c;有很多走不通的地方也有对应的方法&#xff0c;所以会比较…

linux网络初探

linux网络 1.1查看本机ip IP地址 IP地址网络地址主机地址&#xff0c;网络地址&#xff08;网络号&#xff09;相同的主机为本地网络中的主机&#xff0c;可以直接相互通信&#xff0c;而网络地址不同的主机为远程网络中的主机&#xff0c;相互通信必须通过本地网关&#xf…

Flutter Windows开发环境搭建教程与学习资料推荐

Windows应用软件开发有很多框架可以选择&#xff0c;例如比较流行的Electron、Qt、CEF、WPF、WinForm、MFC、DuiLib、SOUI等等。Flutter是近几年流行的全平台应用开发框架&#xff0c;可以进行Android、IOS、Web、MacOS、Windows、Linux等平台的应用软件开发。 一、Flutter介绍…

启动U盘制作工具Rufus 4.0.2035

Rufus是是一款小巧实用免费开源的帮助格式化和创建可启动USB闪存驱动器的工具&#xff0c;如USB钥匙/软盘、记忆棒等&#xff0c;可快速制作linux系统或者win启动u盘&#xff0c;可快速的将ISO镜像文件制作成可引导启动的USB启动盘&#xff0c;支持ISO镜像、GPT和UEFI&#xff…

设置参考文献编号与文中插入引用的具体步骤

目录 一、前言 二、操作步骤 &#xff08;一&#xff09;参考文献设置编号 &#xff08;二&#xff09;文章中引用参考文献方式 一、前言 本教程使用的软件是WPS 二、操作步骤 &#xff08;一&#xff09;参考文献设置编号 1.把引用文献的这个编号全部删掉 2.右键点击段…