【案例】超声波测距系统设计

news/2024/12/28 11:17:32/

1.1 总体设计

1.1.1 概述

学习了明德扬至简设计法和明德扬设计规范,本人用FPGA设计了一个测距系统。该系统采用超声波进行测量距离再在数码管上显示。在本案例的设计过程中包括了超声波的驱动、三线式数码管显示等技术。经过逐步改进、调试等一系列工作后,最终完成了此设计,并进行上板验证,下面将完整的设计记录与大家分享。

1.1.2 设计目标

此系统将实时显示前方障碍与装置之间的距离。

1.1.3 系统结构框图

系统结构框图如下所示:
在这里插入图片描述

1.1.4 模块功能

hc_sr04模块实现功能:
该模块通过控制触发信号trig(10us的TTL)使内部循环发出8个40KHZ脉冲即驱动超声波,接收回响信号echo,通过echo得到距离。

显示模块实现功能:
该模块完成了对所测距离通过数码管对其显示。

1.1.5顶层信号
在这里插入图片描述

1.1.6顶层代码

module top(
clk ,
rst_n ,
echo ,

trig   ,
sel,seg
);input               clk     ;
input               rst_n   ;
input               echo    ;output              trig    ;wire    [3:0]       s_g     ;wire    [3:0]       s_s     ;wire    [3:0]       s_b     ;wire    [3:0]       s_q     ;output  [7:0]       sel     ;output  [7:0]       seg     ;hc_sr04 hc_sr04_1(.clk      (clk)   ,.rst_n    (rst_n) ,.echo     (echo)  ,.trig     (trig)  ,.s_g      (s_g ),.s_s      (s_s ),.s_b      (s_b ),.s_q      (s_q ) 
);seg_disp u_seg_disp(.clk         (clk  ),.rst_n       (rst_n),.segment_data({s_q,s_b,s_s,s_g}),.segment     (seg  ),.seg_sel     (sel  ) 
);endmodule

1.2 hc_sr04模块设计

1.2.1 接口信号
在这里插入图片描述

1.2.2 设计思路

我们只需要提供一个短期的10uS脉冲触发信号trig,该模块内部将发出8个40kHz周期电平并检测回波,一旦检测到有回波信号则输出回响信号,回响信号echo是一个脉冲的宽度成正比的距离变量,可通过发射信号到收到的回响信号时间间隔可以计算得到距离。建议测量周期为60ms以上,以防止发射信号对回响信号的影响,这里我们采用的是1s测量一次。

时钟计数器cnt0:用于计算 1 秒的时钟个数,加一条件为1,表示一直计数;结束条件为数到 TIME_1S ,表示数到 1 秒就清零。

距离计数器 h_cnt:用于计算flag为高电平的宽度的时间,如果flag为1,h_cnt就加一;每完成1秒计数后h_cnt就变为0,此外h_cnt等于h_cnt。

模块时序图
在这里插入图片描述

1.2.3 参考代码

module hc_sr04(
clk ,
rst_n ,
echo ,

trig   ,
s_g    ,
s_s    ,
s_b    ,
s_q      
);parameter      DATA_W = 14  ;parameter                 TIME_1S = 50_000_000;input               clk     ;
input               rst_n   ;
input               echo    ;output              trig    ;
output[ 3:0]        s_g     ;    
output[ 3:0]        s_s     ;    
output[ 3:0]        s_b     ;    
output[ 3:0]        s_q     ;    wire                trig    ;
reg   [ 3:0]        s_g     ;    
reg   [ 3:0]        s_s     ;    
reg   [ 3:0]        s_b     ;    
reg   [ 3:0]        s_q     ;    
reg   [DATA_W-1:0]  distance;reg   [25:0]        cnt0    ;
reg   [20:0]        h_cnt   ;
reg                 echo_2  ;
reg                 echo_1  ;
wire                add_cnt0;
wire                end_cnt0;         
wire                flag_h  ;
wire                flag_l  ;always @(posedge clk or negedge rst_n)beginif(!rst_n)begincnt0 <= 0;endelse if(add_cnt0)beginif(end_cnt0)cnt0 <= 0;elsecnt0 <= cnt0 + 1'b1;end
endassign add_cnt0 = 1;       
assign end_cnt0 = add_cnt0 && cnt0 == TIME_1S - 1;assign trig = (cnt0>=500&&cnt0<1000)?1:0;always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginecho_1 <= 0;echo_2 <= 0;endelse beginecho_1 <= echo  ;echo_2 <= echo_1;end
endalways @(posedge clk or negedge rst_n)beginif(!rst_n)beginh_cnt <= 0;endelse if(add_h_cnt)beginif(end_h_cnt)h_cnt <= 0;elseh_cnt <= h_cnt + 1;endelse if(end_cnt0)beginh_cnt <= 0;end
endassign add_h_cnt = echo_2;       
assign end_h_cnt = 0 ;   always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begindistance <= 0;endelse if(add_cnt0 && cnt0 == 45_000_000-1)begindistance <= h_cnt*34/10000;end
endalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begins_g <= 0;endelse begins_g <= distance%10;end
endalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begins_s <= 0;endelse begins_s <= (distance/10)%10;end
end  always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begins_b <= 0;endelse begins_b <= (distance/100)%10;end
endalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begins_q <= 0;endelse begins_q <= (distance/1000)%10;endend

endmodule

1.3 显示模块设计

1.3.1接口信号
在这里插入图片描述

1.3.2设计思路

该模块对数码管的位选信号sel每隔1ms的时间移位一次,也就是1ms循环亮一个灯,由于1ms的频率肉眼观察不出,我们看到的就是4个灯全亮。

对输入距离distance进行求余处理,得到每一位的数据,通过case语句,让每一位数据形成段选信号,通过位选信号的控制显示在对应的数码管上。

1.3.3参考代码

module seg_disp(
clk ,
rst_n ,
segment_data,
segment ,
seg_sel
);

parameter ZERO = 8’b1100_0000 ;
parameter ONE = 8’b1111_1001 ;
parameter TWO = 8’b1010_0100 ;
parameter THREE = 8’b1011_0000 ;
parameter FOUR = 8’b1001_1001 ;
parameter FIVE = 8’b1001_0010 ;
parameter SIX = 8’b1000_0010 ;
parameter SEVEN = 8’b1111_1000 ;
parameter EIGHT = 8’b1000_0000 ;
parameter NINE = 8’b1001_0000 ;

input clk ;
input rst_n ;
input [31:0] segment_data ;
output [7:0 ] segment ;
output [7:0 ] seg_sel ;

reg [7:0 ] segment ;
reg [7:0 ] seg_sel ;
reg [10:0] delay ;
reg [3:0 ] delay_time ;
wire add_delay_time ;
wire end_delay_time ;
wire add_delay ;
wire end_delay ;
wire [3:0 ] segment_tmp ;

always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
delay <= 0;
end
else if(add_delay) begin
if(end_delay)
delay <= 0;
else
delay <= delay+1 ;
end
end
assign add_delay = 1;
assign end_delay = add_delay && delay == 2000-1 ;

always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
delay_time <= 0;
end
else if(add_delay_time) begin
if(end_delay_time)
delay_time <= 0;
else
delay_time <= delay_time+1 ;
end
end
assign add_delay_time = end_delay;
assign end_delay_time = add_delay_time && delay_time == 8-1 ;

assign segment_tmp = segment_data[(1+delay_time)*4-1 -:4];
always @(posedge clk or negedge rst_n)begin
if(rst_n==1’b0)begin
segment <= ZERO;
end
else begin
case(segment_tmp)
4’d0:segment <= ZERO;
4’d1:segment <= ONE ;
4’d2:segment <= TWO ;
4’d3:segment <= THREE;
4’d4:segment <= FOUR ;
4’d5:segment <= FIVE ;
4’d6:segment <= SIX ;
4’d7:segment <= SEVEN;
4’d8:segment <= EIGHT;
4’d9:segment <= NINE ;
default:begin
segment <= segment;
end
endcase
end
end

always @(posedge clk or negedge rst_n)begin
if(rst_n==1’b0)begin
seg_sel <= 8’b1111_1111;
end
else begin
seg_sel <= ~(8’b1<<delay_time);
end
end

endmodule

1.4 效果和总结

上板验证效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这个设计中,使用明德扬的至简设计法,让我的思路非常清晰,逻辑非常严谨,虽然没有做到一遍成功,但在调试过程中我都比较快速的找到问题,并快速解决。对于学习FPGA的同学,我非常推荐使用明德扬至简设计法和明德扬模块进行学习和设计。

教学视频和工程源代码请移步明德扬论坛学习!

好消息!FPGA至简设计200例已更新,👉🏻学习链接:https://pan.baidu.com/s/181l9fKI8BXwR7HuAF-ok0w 提取码:yt5p

【FPGA至简设计200例】毕业设计案例由浅入深步骤性教学明德扬

温馨提示:明德扬2023推出了全新课程——逻辑设计基本功修炼课,降低学习FPGA门槛的同时,增加了学习的趣味性,并组织了考试赢积分活动

http://www.mdy-edu.com/ffkc/415.html

(点击→了解课程详情☝)


http://www.ppmy.cn/news/1213655.html

相关文章

Vue 组件+es6箭头函数+路由

一、组件 1、让网页或局部页实现复用&#xff0c;包括js&#xff08;vue&#xff09;功能 组件&#xff08;Component&#xff09;是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素&#xff0c;封装可重用的代码。在较高层面上&#xff0c;组件是自定义元素&#xff0c; …

Stm32_标准库_18_串口蓝牙模块_手机与蓝牙模块通信_控制LED灯亮灭

通过输入LED_ON和LED_OFF分别控制LED灯的亮与灭 接线&#xff1a; LED的正极接正电&#xff0c;负极接GPIOA_Pin1 蓝牙模块TXD接GPIOA_Pin3,VCC接正电&#xff0c;GND接负电 注意&#xff1a;USART2是APB1外设&#xff0c;汉字占用字节数是字符的两倍 使用&#xff1a; 手…

11.12总结

这一周主要写了个人中心的几个功能&#xff0c;资料修改&#xff0c;收货地址的创建和修改删除&#xff0c;还有主页界面和商品界面

zookeeper应用之分布式屏障

分布式系统中某些节点任务当满足某个条件时才允许继续运行&#xff0c;如果不满足则当前节点需要等待。这个时候就需要一个屏障来阻止节点的处理。ZooKeeper Barrier是ZooKeeper提供的一种用于分布式环境中实现同步和协调的机制。具体逻辑就是&#xff1a; 1、检测某个barrier…

2022年03月 Python(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 下面有关random的常用方法,描述错误的是? A: random.random()生成一个[0.0,1.0)之间的随机小数 B: random.randint(a,b)生成一个[a,b]之间的随机整数 C: random.choice(seq)从序列中…

CSS BFC是什么,应用实例

CSS BFC&#xff08;块级格式化上下文&#xff09;是一个Web页面渲染时生成的一种独立的渲染区域&#xff0c;它定义了一套渲染规则&#xff0c;用于控制块级盒子的布局和浮动元素与其他元素的交互。BFC可以避免出现一些常见的布局问题&#xff0c;提高页面的可靠性和可维护性。…

解决VSCode中文乱码问题

解决VSCode乱码问题 1.问题描述&#xff1a;2.原因分析&#xff1a;3.解决方案&#xff1a;1&#xff09;解决步骤2&#xff09;深入分析 4.总结 1.问题描述&#xff1a; 最近用vscode的时候突然发现中文字符出现乱码。在网上找了好几种方法都不行&#xff0c;用各种编码格式打…

FlinkSQL聚合函数(Aggregate Function)详解

使用场景&#xff1a; 聚合函数即 UDAF&#xff0c;常⽤于进多条数据&#xff0c;出⼀条数据的场景。 上图展示了⼀个 聚合函数的例⼦ 以及 聚合函数包含的重要⽅法。 案例场景&#xff1a; 关于饮料的表&#xff0c;有三个字段&#xff0c;分别是 id、name、price&#xff0…