目录
1. 超声波模块介绍
引脚说明:
接口 | 作用 |
V(VCC) | 5V供电 |
G(GND) | 接地 |
E(Echo) | 接收引脚 |
T(Trig) | 触发引脚 |
超声波模块是一种常用的测距技术,它利用声波来测量物体的距离。下面是工作原理:
-
发射超声波信号:通过给Trig提供10us的TTL,能够触发超声波模块产生高频的声波信号。
-
目标物体的反射:当声波遇到目标物体时,一部分声波会被目标物体反射回来。
-
接收超声波信号:在接收到反射回来的声波信号是,Echo会输出低电平。
因此,通过计算Echo引脚的高电平时间,再利用音速便可计算出实际距离。
计算公式:
2. Verilog实现
具体实现代码如下:
2.1 时间检测模块
`timescale 1ns / 1ps
//
module PosCounter(clk, reset, echo, echo_time); // 检测回波高电平持续时间
input clk;
input reset;
input echo;
output [40:0] echo_time;//回响信号持续时间
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;//两个回响信号寄存器
reg [19:0] count, dis_reg;
reg [40:0] reg_echo_time; //echo回响信号输出时间
wire start;
wire finish;
assign start = echo_reg1&~echo_reg2; //检测posedge
assign finish = ~echo_reg1&echo_reg2; //检测negedge
always@(posedge clk)
begin
if(reset==1)
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
end
end
always@(curr_state)
begin
case(curr_state)
S0:next_state <= S1;
S1:next_state <= S2;
S2:next_state <= S0;
endcase
end
always@(posedge clk)
begin
reg_echo_time=(dis_reg*8);//返回echo时间(ns)
end
assign echo_time=reg_echo_time;
endmodule
逻辑:
- 根据当前状态进行状态转移和计数操作:
- S0:闲置状态,如果检测到回波信号上升沿,则转移到下一个状态S1,否则计数器清零。
- S1:开始测距计数状态,如果检测到回波信号下降沿,则转移到下一个状态S2,否则计数器加一。
- S2:结束测距计数状态,将计数结果存入距离寄存器,并将计数器清零,然后转移到闲置状态S0。
- 通过状态寄存器和下一个状态逻辑生成下一个状态。
- 在时钟的上升沿,根据计数结果计算回波信号的高电平持续时间,并将结果存入
reg_echo_time
寄存器。 - 将
reg_echo_time
赋值给输出端口echo_time
。
2.2 触发模块
`timescale 1ns / 1ps
//10us触发信号
module Trig_Signal(
input clk, //系统自身时钟
input reset,
output trig
);
reg reg_trig;
reg [25:0] jishu_cnt;
parameter a=12500000;//100ms
always@(posedge clk)
begin
if(reset==1'b1)
begin
reg_trig<=0;
jishu_cnt<=0;
end
else if(jishu_cnt==((a/2)-1))
begin
jishu_cnt<=0;
reg_trig<=~reg_trig;
end
else jishu_cnt=jishu_cnt+1;
end
assign trig=reg_trig;
endmodule
用于产生一个持续时间为10微秒(10us)的触发信号。
在时钟的上升沿触发时,根据计数器jishu_cnt
的值进行处理。如果复位信号为1,将触发信号寄存器reg_trig
和计数器jishu_cnt
清零。否则,如果计数器达到了(a/2)-1
的值,表示已经过了10微秒的一半时间,此时将计数器和触发信号寄存器取反。这样就实现了一个周期为10微秒的触发信号。
2.3 测距模块
`timescale 1ns / 1ps
module juli_detect(clk, reset, Trig, Echo,distance);
input clk;
input reset;
input Echo;
output Trig;
output [15:0]distance; // 距离(单位MM),5位十进制,包括两位小数
wire [20:0] ec_time; // 回波高电平持续时间ns
Trig_Signal u1(.clk(clk),.reset(reset),.trig(Trig));//分频出10hz信号
PosCounter u2(.clk(clk), .reset(reset),.echo(Echo),.echo_time(ec_time));
reg [15:0] distance_reg;
assign distance=distance_reg;
always@(posedge clk)
begin
distance_reg=(340*ec_time/1000000)/2;//mm
end
endmodule
实例化Trig_Signal
模块,生成的触发信号Trig
用于触发超声波模块发送出去。
实例化PosCounter
模块,测量回波信号的高电平持续时间,将结果保存在ec_time
中。
根据高电平持续时间ec_time
计算出相应的距离值,并将结果存储在寄存器distance_reg
中。
具体结构如下: