HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为HC-SR04外观,其基本工作原理为给予此超声波测距模块一触发信号后模块发射超声波,当超声波投射到物体而反射回来时,模块输出一回响信号,以触发信号和回响信号间的时间差,来判定物体的距离。图2为模块时序图。
图1 HC-SR04超声波测距模块实物图
图2 HC-SR04超声波测距模块时序图
以上时序图表明只需要提供一个10uS 以上脉冲触发信号,该模块内部将发出8 个40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。
公式:uS/58=厘米或者uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为60ms 以上,以防止发射信号对回响信号的影响。于是基于FPGA的电路实现主要包括触发信号产生、回响信号计时两个模块。
图3 电路框图
通过此模块产生一个周期为1s的触发信号,10us高电平,999990us低电平
信号名 | 类型 | 信号描述 |
---|---|---|
clk_1m | Input | 1MHz时钟输入,一个上升沿1us |
rst | Input | 复位信号 |
trig | Output | 触发信号 |
模块代码:
module TrigSignal(clk_1m, rst, trig); //产生10us的触发信号input clk_1m, rst;output trig;reg trig;reg[19:0] count;// 模1000 000计数器always@(posedge clk_1m, negedge rst)begin if (~rst) count <= 0; else begin if (9 == count) begin trig <= 0; count <= count + 1; end else begin if (1000000 == count) begin trig <= 1; count <= 0; end else count <= count + 1; end endendendmodule
通过此模块计算回响信号高电平持续的时间,单位us
信号名 | 类型 | 信号描述 |
---|---|---|
clk_1m | Input | 1MHz时钟输入,一个上升沿1us |
rst | Input | 复位信号 |
echo | Input | 回响信号 |
dis_count | Output | 高电平持续时间 |
模块代码:
module PosCounter(clk_1m, rst, echo, dis_count); // 检测回波高电平持续时间input clk_1m, rst, echo;output[19:0] dis_count;parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10; // 状态定义 S0:闲置, S1:开始测距计数, S2:结束测距计数reg[1:0] curr_state, next_state;reg echo_reg1, echo_reg2;assign start = echo_reg1&~echo_reg2; //检测posedgeassign finish = ~echo_reg1&echo_reg2; //检测negedgereg[19:0] count, dis_reg;wire[19:0] dis_count; //测距计数always@(posedge clk_1m, negedge rst)begin if(~rst) begin echo_reg1 <= 0; echo_reg2 <= 0; count <= 0; dis_reg <= 0; curr_state <= S0; end else begin echo_reg1 <= echo; // 当前 echo_reg2 <= echo_reg1; // 后一个 case(curr_state) S0:begin if (start) // 检测到上升沿 curr_state <= next_state; //S1 else count <= 0; end S1:begin if (finish) // 检测到下降沿 curr_state <= next_state; //S2 else begin count <= count + 1; end end S2:begin dis_reg <= count; // 缓存计数结果 count <= 0; curr_state <= next_state; //S0 end endcase endendalways@(curr_state)begin case(curr_state) S0:next_state <= S1; S1:next_state <= S2; S2:next_state <= S0; endcaseendassign dis_count = dis_reg * 100 / 58; // 距离,乘100取小数部分endmodule
各模块之间的连接
信号名 | 类型 | 信号描述 |
---|---|---|
clk_50m | Input | 50MHz时钟输入 |
rst | Input | 复位信号 |
Trig | Output | 触发信号 |
Echo | Input | 回响信号 |
Led | Output | 距离小于10cm点亮LED |
Distance | Output | 距离 |
模块代码:
module sonic_detect(clk_50m, rst, Trig, Echo, Led, distance);input clk_50m, rst, Echo;output Trig, Led;output[34:0] distance; // 5位十进制*7段译码// Vcc--GPIO10// Gnd--GPIO11wire clk_1m;wire[19:0] dis; // 回波高电平持续时间us wire[19:0] d; // 距离(单位cm),5位十进制,包括两位小数Clk_1M u0(.clk_out(clk_1m), .clk_in(clk_50m), .rst(1)); // 50分频TrigSignal u1(.clk_1m(clk_1m), .rst(rst), .trig(Trig));PosCounter u2(.clk_1m(clk_1m), .rst(rst), .echo(Echo), .dis_count(dis));assign d[19:16] = dis/10000; // 百位assign d[15:12] = dis/1000%10; // 十位assign d[11:8] = dis/100%10; // 个位assign d[7:4] = dis/10%10; // 0.1assign d[3:0] = dis%10; // 0.01assign Led =((d[19:16] < 1)&(d[15:12] < 1)) ? 1 : 0;translator u3(.in(d[19:16]), .out(distance[34:28])); // 七段译码translator u4(.in(d[15:12]), .out(distance[27:21]));translator u5(.in(d[11:8]), .out(distance[20:14]));translator u6(.in(d[7:4]), .out(distance[13:7]));translator u7(.in(d[3:0]), .out(distance[6:0]));endmodule
联系客服