超声波测距模块HC-SR04
1、产品特色
①典型工作用电压:5V
②超小静态工作电流:小于 5mA
③感应角度(R3 电阻越大,增益越高,探测角度越大):
R3 电阻为 392,不大于 15 度
R3 电阻为 472, 不大于 30 度
④探测距离(R3 电阻可调节增益,即调节探测距离):
R3 电阻为 392 2cm-450cm
R3 电阻为 472 2cm-700cm
⑤高精度:可达 0.3cm
⑥盲区(2cm)超近
2、接口定义
Vcc
Trig(控制端)
Echo(接收端)
Gnd
控制口发一个 10US 以上的高电平,就可以在接收口等待高电平输出。一有输出就可以开
定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距
离.如此不断的周期测,就可以达到你移动测量的值了。
1、原理
①采用 IO 触发测距,给至少10us 的高电平信号;
②模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
③有信号返回,通过 IO 输出一高电平,高电平持续的时间就是
④ 测试距离=(高电平时间*声速(340M/S))/2;
以上时序图表明你只需要提供一个10us 以上脉冲触发信号,该模块内部将发出8个40kHz周
期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的
距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。公
式:us/58=厘米或者us/148-英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为
60ms 以上,以防止发射信号对回响信号的影响。
代码部分
`timescale 1ns / 1ps
module HC_SR04(
input wire clk ,
input wire rst_n,
input wire echo ,
output wire trig ,
output wire [3:0] sel ,
output wire [7:0] seg
);
parameter CUNT_MAX =12_500_000;//00 ;//60ms=3_000_000
parameter CUNT_10US =600 ;//10us=500
// reg [ 1:0] temp;
// always @(posedge clk ) begin
// temp[0] <= echo;
// temp[1] <= temp[0];
// end
reg [30:0] cunt ;
reg [30:0] cunt_t;
wire [24:0] dis ;
reg flag ;
wire [13:0] data ;
assign trig= flag;
assign dis=(cunt_t*20)/100/58; //精度0.1厘米 /50_000_000*340 cunt_t*20*340/1000_000_000*100*1/2
assign data = (dis>=0 && dis < 9999)?dis[13:0] : 14'd9_999;
always @(posedge clk ) begin
if(!rst_n)
cunt<=0;
else begin
if(cunt==CUNT_MAX)
cunt<=0;
else
cunt<=cunt+1;
end
end
always @(posedge clk ) begin
if(!rst_n)
flag<=0;
else if(cunt>3_000_000&&cunt<6_000_000)
flag<=1;
else
flag<=0;
end
//返回的周期数
always @(posedge clk ) begin
if(!rst_n||cunt==CUNT_MAX)
cunt_t<=0;
else if(echo==1'b1)
cunt_t<=cunt_t+1;
else
cunt_t<=cunt_t;
end
seg u_seg(
/*input */. clk (clk ),
/*input */. rst_n(rst_n),
/*input wire [13:0]*/. data (dis[13:0] ),
/*output reg [3:0] */. sel (sel ),
/*output reg [7:0] */. seg (seg )
);
endmodule
数码管
`timescale 1ns / 1ps
module seg(
input clk ,
input rst_n,
input wire [13:0] data ,
output reg [3:0] sel ,///
output reg [7:0] seg
);
parameter CNT_1S =50_000_000 ;
reg [25:0] ct ;
reg [30:0] data_t ;
//
// always @(posedge clk ) begin
// if(!rst_n)
// data_t<=0;
// else if(ct==50_000_00)
// data_t<=data;
// else
// data_t<=data_t;
// end
//对1秒进行计数
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
ct<=0;
else if(ct==CNT_1S-1)
ct<=0;
else
ct<=ct+1;
end
//产生flag信号
reg flag;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
flag<=0;
else if(ct==CNT_1S-2) //0.5ms
flag<=1;
else
flag<=0;
end
//进行一个从右到左的移位
//产生一个计数器
reg [3:0] ct_sel;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
ct_sel<=0;
else if(ct_sel==4)
ct_sel<=0;
else if(ct%25000==1) //可加2个00 效果更明显
ct_sel<=ct_sel+1;
else
ct_sel<=ct_sel;
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
sel<=4'b0000;
else case (ct_sel)
0:sel<=4'b0001;
1:sel<=4'b0010;
2:sel<=4'b0100;
3:sel<=4'b1000;
default: sel<=4'b0000;//输入值不能改 比如ct_sel<=4'b0000 会报错
endcase
end
//译码
reg [13:0] num;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
num<=0;
else
case (ct_sel)
0:num<=data%10 ;
1:num<=data/10%10 ;
2:num<=data/100%10 ;
3:num<=data/1000%10 ;
default: num<=num ;
endcase
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
seg<=8'b1100_0000;
else
case(num)// hgfe dcba 0有效
0:begin
if(ct_sel==1)
seg<= 8'h40;//b0100_0000;
else
seg<= 8'hc0;//b1100_0000;
end
1:begin
if(ct_sel==1)
seg<= 8'h79;//b0111_1001;
else
seg<= 8'hf9;//b1111_1001;
end
2:begin
if(ct_sel==1)
seg<= 8'h24;//b0010_0100;
else
seg<= 8'ha4;//b1010_0100;
end
3:begin
if(ct_sel==1)
seg<= 8'h30;//b0011_0000;
else
seg<= 8'hb0;//b1011_0000
end
4:begin
if(ct_sel==1)
seg<= 8'h19;//b0001_1001;
else
seg<= 8'h99;//b1001_1001;
end
5:begin
if(ct_sel==1)
seg<= 8'h12;//b0001_0010;
else
seg<= 8'h92;//b1001_0010;
end
6:begin
if(ct_sel==1)
seg<= 8'h2;//b0000_0010;
else
seg<= 8'h82;//b1000_0010;
end
7:begin
if(ct_sel==1)
seg<= 8'h78;//b0111_1000;
else
seg<= 8'hf8;//b1111_1000;
end
8:begin
if(ct_sel==1)
seg<= 8'h0;//b0000_0000;
else
seg<= 8'h80;//b1000_0000;
end
9:begin
if(ct_sel==1)
seg<= 8'h10;//b0001_0000;
else
seg<= 8'h90;//b1001_0000;
end
default:
seg<=seg;
endcase
end
endmodule