加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 一、简介
    • 二、工作原理
    • 三、实物图
    • 四、电气参数
    • 五、超声波时序图
    • 六、实验要求
    • 七、设计框架
    • ​八、设计实现
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

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

2023/10/18
3213
阅读需 16 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

作者:李西锐  校对:陆辉

大侠好,欢迎来到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 == 1'b0)28         cnt <= 22'd0;29       else if(cnt == t - 1)30         cnt <= 22'd0;31       else32         cnt <= cnt + 1'b1;33     end34 35     always @ (posedge clk, negedge rst_n)36     begin37       if(rst_n == 1'b0)38         trig <= 1'b0;39       else if(cnt < 1000)40         trig <= 1'b1;41       else42         trig <= 1'b0;43     end44 45     always @ (posedge clk, negedge rst_n)46     begin47       if(rst_n == 1'b0)48         begin49           echo_cnt <= 21'd0;50           state <= 1'd0;51           data_valid_r <= 1'b0;52           echo_cnt <= 21'd0;53         end54       else55         case(state)56           1'd0  :  begin57                   if(echo_r & (~echo_rr))58                     state <= 1'd1;59                   else60                     begin61                       state <= 1'd0;62                       data_valid_r <= 1'b0;63                     end64                 end65           1'd1  :  begin66                   if((~echo_r) & echo_rr)67                     begin68                       state <= 1'd0;69                       echo_cnt <= 21'd0;70                       cnt_temp <= echo_cnt;71                       data_valid_r <= 1'b1;72                     end73                   else74                     begin75                       state <= 1'd1;76                       echo_cnt <= echo_cnt + 1'b1;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 == 1'b0)88         temp <= 36'd0;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 == 1'b0)100        distance <= 12'd0;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 == 1'b0)20      cnt <= 16'd0;21    else if(cnt == t - 1)22      cnt <= 16'd0;23    else24      cnt <= cnt + 1'b1;25    end26    27    always @ (posedge clk, negedge rst_n)28    begin29    if(rst_n == 1'b0)30      sel <= 6'b111_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      6'b111_110  : show_data = 4'hf;41      6'b111_101  : show_data = 4'hf;42      6'b111_011  : show_data = data/1000;43      6'b110_111  : show_data = data/100%10;44      6'b101_111  : show_data = data/10%10;45      6'b011_111  : show_data = data%10;46      default : show_data = 4'd0;47    endcase48    end49    50    always @ (*)51    begin52    case(show_data)53      4'd0  : seg_r = 8'b1100_0000;54      4'd1  : seg_r = 8'b1111_1001;55      4'd2  : seg_r = 8'b1010_0100;56      4'd3  : seg_r = 8'b1011_0000;57      4'd4  : seg_r = 8'b1001_1001;58      4'd5  : seg_r = 8'b1001_0010;59      4'd6  : seg_r = 8'b1000_0010;60      4'd7  : seg_r = 8'b1111_1000;61      4'd8  : seg_r = 8'b1000_0000;62      4'd9  : seg_r = 8'b1001_0000;63      default:  seg_r = 8'd0;64    endcase65    end66    67    assign seg = (sel == 6'b111_011) ? (seg_r & 8'b0111_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 = 1'b0;17      rst_n = 1'b0;18      echo = 1'b0;19      #105;20      rst_n = 1'b1;21      #1000;22      23      repeat(10) begin24      @ (negedge trig);25      #1002;26      echo = 1'b1;27      #20000;28      echo = 1'b0;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

仿真图如下:

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

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
EP4CE55F23C8 1 Intel Corporation Field Programmable Gate Array, 3491 CLBs, 472.5MHz, 55856-Cell, PBGA484, 23 X 23 MM, 1 MM PITCH, FBGA-484
$1086.23 查看
XC7A200T-3FFG1156E 1 AMD Xilinx Field Programmable Gate Array, 16825 CLBs, 1412MHz, 215360-Cell, CMOS, PBGA1156, FBGA-1156
$527.73 查看
EP2C50F484I8N 1 Intel Corporation Field Programmable Gate Array, 3158 CLBs, 402.5MHz, 50528-Cell, CMOS, PBGA484, LEAD FREE, FBGA-484
暂无数据 查看

相关推荐

电子产业图谱

任何技术的学习就好比一个江湖,对于每一位侠客都需要不断的历练,从初入江湖的小白到归隐山林的隐世高人,需要不断的自我感悟自己修炼,让我们一起仗剑闯FPGA乃至更大的江湖。