利用FPGA实现超声测距(Verilog HDL)

设计要求

  • 利用Altera DE2-115开发板和某宝的HC-SR04超声波测距模块实现测距功能
  • 显示结果包括三位整数及两位小数
  • 距离小于10cm时点亮一个LED

超声波原理:

HC-SR04超声波测距模块可提供 2cm-400cm的非接触式距离感测功能,测距精度可达高到 3mm;模块包括超声波发射器、接收器与控制电路。图1为HC-SR04外观,其基本工作原理为给予此超声波测距模块一触发信号后模块发射超声波,当超声波投射到物体而反射回来时,模块输出一回响信号,以触发信号和回响信号间的时间差,来判定物体的距离。图2为模块时序图。
利用FPGA实现超声测距(Verilog HDL)_第1张图片

图1 HC-SR04超声波测距模块实物图

利用FPGA实现超声测距(Verilog HDL)_第2张图片

图2 HC-SR04超声波测距模块时序图

以上时序图表明只需要提供一个10uS 以上脉冲触发信号,该模块内部将发出8 个40kHz 周期电平并检测回波。一旦检测到有回波信号则输出回响信号。回响信号的脉冲宽度与所测的距离成正比。由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。

公式:uS/58=厘米或者uS/148=英寸;或是:距离=高电平时间*声速(340M/S)/2;建议测量周期为60ms 以上,以防止发射信号对回响信号的影响。于是基于FPGA的电路实现主要包括触发信号产生、回响信号计时两个模块。

电路框图

图3 电路框图


基于FPGA的各模块实现

1. 触发信号产生模块

通过此模块产生一个周期为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
    end
end
endmodule

2. 回响信号计时模块

通过此模块计算回响信号高电平持续的时间,单位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;  //检测posedge
assign finish = ~echo_reg1&echo_reg2; //检测negedge
reg[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
    end
end

always@(curr_state)
begin
    case(curr_state)
    S0:next_state <= S1;
    S1:next_state <= S2;
    S2:next_state <= S0;
    endcase
end

assign dis_count = dis_reg * 100 / 58; // 距离,乘100取小数部分

endmodule

3. 顶层电路

各模块之间的连接

信号名 类型 信号描述
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--GPIO11
wire 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.1
assign d[3:0]   = dis%10;       // 0.01
assign 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

你可能感兴趣的:(FPGA,VerilogHDL)