赞
踩
DE2-E115 FPGA开发板 + Quartus + Modelsim
学习并掌握HC_SR04模块的使用
使用DE2开发板驱动HC_SR04模块,并将所测得数据显示到开发板上的数码管。
超声波原理:
HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为HC-SR04外观,其基本工作原理为给予此超声波测距模块触发信号后模块发射超声波,当超声波投射到物体而反射回来时,模块输出回响信号,以触发信号和回响信号间的时间差,来判定物体的距离。
数码管显示驱动在之前已经做过,这里不再赘述。
信号名 | 端口类型 | 端口位宽 | 功能说明 |
---|---|---|---|
Clk | I | 1 | 系统时钟,50MHz |
Rst_n | I | 1 | 系统复位,低有效 |
echo | I | 1 | 超声波模块回响信号,高电平持续时间/2即代表测试距离 |
trig | O | 1 | 超声波模块触发测试信号 |
data_o | O | 19 | 测得距离,单位厘米,保留三位小数 |
本设计未涉及状态机。
见章节2.2
/*================================================*\ Filename ﹕ Author ﹕ Description ﹕产生周期为1us的时钟信号 Called by ﹕ Revision History ﹕ mm/dd/202x Revision 1.0 Email﹕ Company﹕ \*================================================*/ module clk_div( input wire Clk , //system clock 50MHz input wire Rst_n , //reset ,low valid output wire clk_us // ); //Parameter Declarations parameter CNT_MAX = 19'd50;//1us的计数值为 50 * Tclk(20ns) //Interrnal wire/reg declarations reg [5:00] cnt ; //Counter wire add_cnt ; //Counter Enable wire end_cnt ; //Counter Reset //Logic Description always @(posedge Clk or negedge Rst_n)begin if(!Rst_n)begin cnt <= 'd0; end else if(add_cnt)begin if(end_cnt)begin cnt <= 'd0; end else begin cnt <= cnt + 1'b1; end end else begin cnt <= cnt; end end assign add_cnt = 1'b1; assign end_cnt = add_cnt && cnt >= CNT_MAX - 19'd1; assign clk_us = end_cnt; endmodule
/*================================================*\ Filename ﹕ Author ﹕ Description ﹕超声波触发测距模块 波形周期300ms,前10us高电平 Called by ﹕ Revision History ﹕ mm/dd/202x Revision 1.0 Email﹕ Company﹕ \*================================================*/ module hc_sr_trig( input wire clk_us , //system clock 1MHz input wire Rst_n , //reset ,low valid output wire trig //触发测距信号 ); //Parameter Declarations parameter CYCLE_MAX = 19'd300_000; //Interrnal wire/reg declarations reg [18:00] cnt ; //Counter wire add_cnt ; //Counter Enable wire end_cnt ; //Counter Reset //Logic Description always @(posedge clk_us or negedge Rst_n)begin if(!Rst_n)begin cnt <= 'd0; end else if(add_cnt)begin if(end_cnt)begin cnt <= 'd0; end else begin cnt <= cnt + 1'b1; end end else begin cnt <= cnt; end end assign add_cnt = 1'b1; assign end_cnt = add_cnt && cnt >= CYCLE_MAX - 9'd1; assign trig = cnt < 15 ? 1'b1 : 1'b0; endmodule
/*================================================*\ Filename ﹕ Author ﹕ Description ﹕超声波检测距离模块 本模块理论测试距离 2cm~510cm 输出结果保留两位小数 Called by ﹕ Revision History ﹕ mm/dd/202x Revision 1.0 Email﹕ Company﹕ \*================================================*/ module hc_sr_echo( input wire Clk , //clock 50MHz input wire clk_us , //system clock 1MHz input wire Rst_n , //reset ,low valid input wire echo , // output wire [18:00] data_o //检测距离,保留3位小数,*1000实现 ); /* S(um) = 17 * t --> x.abc cm */ //Parameter Declarations parameter T_MAX = 16'd60_000;//510cm 对应计数值 //Interrnal wire/reg declarations reg r1_echo,r2_echo; //边沿检测 wire echo_pos,echo_neg; // reg [15:00] cnt ; //Counter wire add_cnt ; //Counter Enable wire end_cnt ; //Counter Reset reg [18:00] data_r ; //Logic Description //如果使用clk_us 检测边沿,延时2us,差值过大 always @(posedge Clk or negedge Rst_n)begin if(!Rst_n)begin r1_echo <= 1'b0; r2_echo <= 1'b0; end else begin r1_echo <= echo; r2_echo <= r1_echo; end end assign echo_pos = r1_echo & ~r2_echo; assign echo_neg = ~r1_echo & r2_echo; always @(posedge clk_us or negedge Rst_n)begin if(!Rst_n)begin cnt <= 'd0; end else if(add_cnt)begin if(end_cnt)begin cnt <= cnt; end else begin cnt <= cnt + 1'b1; end end else begin //echo 低电平 归零 cnt <= 'd0; end end assign add_cnt = echo; assign end_cnt = add_cnt && cnt >= T_MAX - 1; //超出最大测量范围则保持不变,极限 always @(posedge Clk or negedge Rst_n)begin if(!Rst_n)begin data_r <= 'd2; end else if(echo_neg)begin data_r <= (cnt << 4) + cnt; end else begin data_r <= data_r; end end //always end assign data_o = data_r >> 1; endmodule
/*================================================*\ Filename ﹕tb_hc_sr.v Author ﹕Adolph Description ﹕超声波驱动测试文件 Called by ﹕ Revision History ﹕ mm/dd/202x Revision 1.0 Email﹕ Company﹕ \*================================================*/ `timescale 1ns/1ns //仿真系统时间尺度定义 `define clk_period 20 //时钟周期参数定义 module tb_hc_sr(); //激励信号定义 reg Clk ; reg Rst_n ; reg echo; // //响应信号定义 wire trig ; wire [6:0] hex1 ; wire [6:0] hex2 ; wire [6:0] hex3 ; wire [6:0] hex4 ; wire [6:0] hex5 ; wire [6:0] hex6 ; wire [6:0] hex7 ; wire [6:0] hex8 ; //实例化 HC_SR04_TOP HC_SR04_TOP( /*input */.Clk (Clk ), //system clock 50MHz /*input */.Rst_n (Rst_n ), //reset ,low valid /*input */.echo (echo ), // /*output */.trig (trig ), //触发测距信号 /*output [6:0] */.hex1 (hex1 ), // -共阳极,低电平有效 /*output [6:0] */.hex2 (hex2 ), // - /*output [6:0] */.hex3 (hex3 ), // - /*output [6:0] */.hex4 (hex4 ), //连接符 /*output [6:0] */.hex5 (hex5 ), //cm - /*output [6:0] */.hex6 (hex6 ), //cm - /*output [6:0] */.hex7 (hex7 ), //cm - /*output [6:0] */.hex8 (hex8 ) //熄灭 ); //产生时钟 initial Clk = 1'b0; always #(`clk_period / 2) Clk = ~Clk; //产生激励 initial begin Rst_n = 1'b0; echo = 1'b0; #(`clk_period * 20 + 3); Rst_n = 1'b1; #(`clk_period * 20); wait(HC_SR04_TOP.hc_sr_driver.hc_sr_trig.cnt == 240); echo = 1'b1;//测试超声波信号发送完成,echo拉高 #(50 * `clk_period * 2500 + 7); echo = 1'b0; #(`clk_period * 200); $stop(2); end endmodule
经测,所测距离与实际距离一致,模块功能基本实现。
但是,本设计仅能测试4~249cm范围的距离,应是设计中echo模块的问题,留待后来人解决,所使用的数码管驱动为8位7段数码管,其内涉及到函数的使用,诸君若不曾接触,可细品一二。
贴代码的目的只是为了方便理解,如若成为CV战士,则失去了学习的意义,望诸君能有所收获。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。