当前位置:首页 > 新闻资讯 > FPGA之家动态 >

FPGA零基础学习之Vivado-超声波驱动设计

时间:2024-07-29      来源:网络搜集 关于我们 0

大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。“煮酒言欢”进入IC技术圈,这里有近100个IC技术公众号。

大侠好,欢迎来到FPGA技术江湖。本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。

系统性的掌握技术开发以及相关要求,对个人就业以及职业发展都有着潜在的帮助,希望对大家有所帮助。本次带来Vivado系列,超声波驱动设计。话不多说,上货。

超声波驱动设计

作者:李西锐  校对:陆辉

一、简介

声音是我们日常生活中不可缺少的一种信号,在传递信息的同时,也在生活中的各个领域有较多的应用。根据声音的频率,我们将声音大致划分为三个阶段,人耳的听力范围,一般在20Hz~20000Hz之间。低于这个范围,我们称之为次声波;高于这个范围,称之为超声波。超声波的应用比较广泛,比如:超声波检查、超声波碎石、超声波清洗、超声波测速、超声波测距等等。此次我们就来研究一下它的其中一项应用:超声波测距。

我们用到的试验模块为HC-SR04超声波模块,它的测量距离在2cm~400cm之间。测量精度在3mm左右。模块包含了超声波的发射器、接收器和控制电路。超声波发射器在启动后会发出固定频率的方波,用声波去测量距离,不需要我们接触被测物体,在空间上使得我们测距变得方便很多。

二、工作原理

1、采用IO口TRIG触发测距,给至少10us的高电平信号,测量周期建议在60ms以上,以防止发射的信号对回响信号造成影响。

2、模块会自动发送8个40Khz的方波信号,接收器自动检测是否有回响信号返回。

3、有信号返回时,通过IO口ECHO输出一个高电平信号,高电平持续的时间就是方波从发射到返回的时间。测量距离=(高电平时间*声速(340m/s))/2;

在此需要我们注意的事,发射器是自动发送方波信号的,而且会自动检测是否有信号返回,这让我们省去了一大部分工作,使得测量变得简单。其次,在计算测量距离时,我们要将计算出来的结果除以2,因为我们测得的时间是往返的时间,也就是双倍的路程。

三、实物图

电气参数

五、超声波时序图

在时序图中,我们可以看出,我们需要生成一个周期至少为60ms,且高电平维持时间至少为10us的一个触发信号。

六、实验要求

此次设计,要求能够正常驱动模块,计算出的距离,计算其平均值以保证准确性。数码管上显示出距离,单位为m,精确到mm。并且,蜂鸣器能够根据距离响出不同频率的报警声音,距离越近,响声频率越频繁。

七、设计框架

八、设计实现

在计算回响信号的时间时,我们可以检测回响信号的上升沿和下降沿来作为计时器的开始和结束。在我们计算出距离之后,可以每三个数据计算一次平均值。然后将数据输出给其他模块。

首先,我们新建工程。

选择新建文件,然后先新建顶层文件

按照我们所画框架写入顶层端口。

重复上述新建文件的过程,新建ultrasonic_driver文件,代码如下:

1 module ultrasonic_driver(2 3 input wire clk,4 input wire rst_n,5 input wire echo,6 output reg trig,7 output reg [11:0] distance,8 output reg data_valid9 );10 11 parameter t = 3_000_000;12 13 reg [21:0] cnt;14 reg state;15 reg echo_r, echo_rr;16 reg [20:0] echo_cnt;17 reg [20:0] cnt_temp;18 wire [11:0] d_r;19 reg [35:0] temp;20 reg data_valid_r;21 22 always @ (posedge clk) echo_r <= echo;23 always @ (posedge clk) echo_rr <= echo_r;24 25 always @ (posedge clk, negedge rst_n)26 begin27 if(rst_n == 1b0)28 cnt <= 22d0;29 else if(cnt == t - 1)30 cnt <= 22d0;31 else32 cnt <= cnt + 1b1;33 end34 35 always @ (posedge clk, negedge rst_n)36 begin37 if(rst_n == 1b0)38 trig <= 1b0;39 else if(cnt < 1000)40 trig <= 1b1;41 else42 trig <= 1b0;43 end44 45 always @ (posedge clk, negedge rst_n)46 begin47 if(rst_n == 1b0)48 begin49 echo_cnt <= 21d0;50 state <= 1d0;51 data_valid_r <= 1b0;52 echo_cnt <= 21d0;53 end54 else55 case(state)56 1d0 : begin57 if(echo_r & (~echo_rr))58 state <= 1d1;59 else60 begin61 state <= 1d0;62 data_valid_r <= 1b0;63 end64 end65 1d1 : begin66 if((~echo_r) & echo_rr)67 begin68 state <= 1d0;69 echo_cnt <= 21d0;70 cnt_temp <= echo_cnt;71 data_valid_r <= 1b1;72 end73 else74 begin75 state <= 1d1;76 echo_cnt <= echo_cnt + 1b1;77 cnt_temp <= cnt_temp;78 end79 end80 endcase81 end82 83 assign d_r = cnt_temp * 34 / 10_000;84 85 always @ (posedge clk, negedge rst_n)86 begin87 if(rst_n == 1b0)88 temp <= 36d0;89 else if(data_valid_r)90 temp <= {temp[23:0],d_r};91 else92 temp <= temp;93 end94 95 always @ (posedge clk) data_valid <= data_valid_r;96 97 always @ (posedge clk, negedge rst_n)98 begin99 if(rst_n == 1b0)100 distance <= 12d0;101 else if(data_valid)102 distance <= (temp[35:24] + temp[23:12] + temp[11:0]) / 3;103 else104 distance <= distance;105 end106107 endmodule

在完成测距时,输出一个valid信号,这个信号要作为后续我们保存数据以及计算平均值的标志信号。

数码管代码如下:

1 module seven_tube_driver(2 3 input wire clk,4 input wire rst_n,5 input wire [11:0] data, 6 7 output reg [5:0] sel,8 output wire [7:0] seg9 );10 11 parameter t = 50000;12 13 reg [15:0] cnt;14 reg [3:0] show_data;15 reg [7:0] seg_r;16 17 always @ (posedge clk, negedge rst_n)18 begin19 if(rst_n == 1b0)20 cnt <= 16d0;21 else if(cnt == t - 1)22 cnt <= 16d0;23 else24 cnt <= cnt + 1b1;25 end26 27 always @ (posedge clk, negedge rst_n)28 begin29 if(rst_n == 1b0)30 sel <= 6b111_110;31 else if(cnt == t - 1)32 sel <= {sel[4:0],sel[5]};33 else34 sel <= sel;35 end36 37 always @ (*)38 begin39 case(sel)40 6b111_110 : show_data = 4hf;41 6b111_101 : show_data = 4hf;42 6b111_011 : show_data = data/1000;43 6b110_111 : show_data = data/100;44 6b101_111 : show_data = data/10;45 6b011_111 : show_data = data;46 default : show_data = 4d0;47 endcase48 end49 50 always @ (*)51 begin52 case(show_data)53 4d0 : seg_r = 8b1100_0000;54 4d1 : seg_r = 8b1111_1001;55 4d2 : seg_r = 8b1010_0100;56 4d3 : seg_r = 8b1011_0000;57 4d4 : seg_r = 8b1001_1001;58 4d5 : seg_r = 8b1001_0010;59 4d6 : seg_r = 8b1000_0010;60 4d7 : seg_r = 8b1111_1000;61 4d8 : seg_r = 8b1000_0000;62 4d9 : seg_r = 8b1001_0000;63 default: seg_r = 8d0;64 endcase65 end66 67 assign seg = (sel == 6b111_011) ? (seg_r & 8b0111_1111) : seg_r;68 69 endmodule

第67行的作用是为了在显示时,显示一个小数点,这样数码管显示的数值单位就为米,精确度为毫米。

在蜂鸣器模块中,蜂鸣器的响声为嘀嘀响声我们可以根据距离的大小,让蜂鸣器响声的快慢作出改变。

我们根据距离改变计数器的最大计数次数,以达到两次“嘀嘀”响声的时间间隔发生变化。

写好代码之后,我们做一下仿真,代码如下:

1 `timescale 1ns / 1ps2 3 module ultrasonic_tb;4 5 reg clk;6 reg rst_n;7 reg echo;8 wire trig;9 wire [5:0] sel;10 wire [7:0] seg;11 wire beep;12 13 defparam ultrasonic_inst.ultrasonic_driver_inst.t = 3000;14 15 initial begin16 clk = 1b0;17 rst_n = 1b0;18 echo = 1b0;19 #105;20 rst_n = 1b1;21 #1000;22 23 repeat(10) begin24 @ (negedge trig);25 #1002;26 echo = 1b1;27 #20000;28 echo = 1b0;29 end30 #10000;31 $stop;32 end33 34 always #10 clk = ~clk;35 36 ultrasonic ultrasonic_inst(37 .clk (clk ),38 .rst_n (rst_n ),39 .echo (echo ),40 .trig (trig ),41 .sel (sel ),42 .seg (seg ),43 .beep (beep )44 );45 46 endmodule

仿真图如下:

从图中我们可以看出,距离在多次采样之后达到了稳定值。由于我们仿真时间给的较短,所以距离的数值不大,但是已经足够看出结果。

- End -

福利】:QQ交流群173560979,进群备注名字+学校/企业。

淘宝店铺:https://shop588964188.taobao.com

论坛网址:www.sxznfpga.com

叁芯智能FPGA课程

FPGA技术江湖广发江湖帖

无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有,QQ微信双选,FPGA技术江湖打造最纯净最专业的技术交流学习平台。

FPGA技术江湖微信交流群

加群主微信,备注姓名+公司/学校+岗位/专业进群

FPGA技术江湖QQ交流群

备注姓名+公司/学校+岗位/专业进群


注明:本内容来源网络,不用于商业使用,禁止转载,如有侵权,请来信到邮箱:429562386ⓐqq.com 或联系本站客服处理,感谢配合!

用户登陆

    未注册用户登录后会自动为您创建账号

提交留言