ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于VHDL的FPGA倒车雷达设计与实现

基于VHDL的FPGA倒车雷达设计与实现 简介基于VHDL的倒车雷达完整工程面向FPGA、数字逻辑课程设计及嵌入式开发学习者针对倒车时视野受限、易碰撞的安全痛点提供从超声波测距到蜂鸣器报警的完整数字电路实现方案。项目核心由VHDL编写涵盖分频器、计数器、发声控制等模块从进程与状态机设计到引脚约束均有迹可循适合作为课程设计或毕设参考。压缩包共含490个文件以.vhd源文件、.tdf/.bdf工程设计文件、.qsf/.qpf工程配置文件、.sof/.pof器件下载文件为主体辅以编译报告、readme说明及大量.bak备份便于逐版本理解设计调试过程资源包整体仅6.88MB下载后即可用Quartus打开复用。该资源已有102人学习使用。除完整源码外还能从frediv、voice、selfcount等文件命名快速定位分频、发声、计数功能模块对学习VHDL层次化设计很有价值尤其适合需要动手实践FPGA项目的读者。 相信很多电子相关专业的学生和嵌入式入门者都做过或者正在做这样一个课题基于VHDL的倒车雷达。这个项目我认为是数字逻辑和FPGA入门阶段性价比很高的一道题它把分频、状态机设计、计数器、动态扫描显示、外部接口时序这些核心知识点全部串起来了做完一遍你对VHDL的掌握程度会有一个比较明显的提升。这篇文章我就以我自己做这个项目的完整流程为例从方案选型、原理拆解、代码实现到板级调试踩坑把整个细节都讲清楚配套源码我也做了整理后面会给出获取方式方便你直接拿去跑。先说下这个项目能做什么利用超声波传感器HC-SR04测距把测到的距离换算成厘米在四位数码管上显示同时根据距离分档触发蜂鸣器报警。整个过程全部在FPGA内部用VHDL逻辑实现不依赖软核处理器。所以它不仅是一个倒车雷达演示更是一套完整的数字系统设计训练。1. 项目整体设计思路为什么用VHDL做倒车雷达1.1 方案选型FPGAVHDL 相比单片机的优势我第一次考虑这个题目的时候第一反应是倒车雷达用51单片机做不是更简单吗确实市面上大量课程设计都是STC89C52加HC-SR04代码几十行就能跑还能加LCD1602显示。但“简单”的另一面是很多东西被固件库和顺序执行的C语言掩盖了你看不到时序到底怎么对齐的计数器怎么溢出的状态怎么迁移的。用FPGA做所有逻辑都得你自己搭这是两种完全不同的思维模式。FPGA方案的核心优势在于并行性和精确时序控制。超声波测距本质是“发脉冲-等回波-数时间”这个时间测量精度直接决定了距离精度。单片机靠定时器中断中断响应延迟本身就存在不确定性而FPGA直接用硬件计数器在系统时钟下计数时钟沿一到就锁存确定性要高得多。此外数码管动态扫描、蜂鸣器报警这些任务在FPGA里面是并行模块互不干扰不像单片机那样要来回切换任务。从学习角度讲用VHDL实现倒车雷达能逼你掌握这几件事异步信号同步化处理、有限状态机设计方法、模块化层次化设计思想、时序仿真与板级调试的差异。这些是后面做通信接口、图像处理、甚至SoC设计都要用到的基础功。1.2 系统总体框架与模块划分整个系统的顶层结构就五大块分频模块、超声波测距控制模块、距离计算与BCD转换模块、数码管动态扫描模块、蜂鸣器报警模块。有些设计还会加一个按键模块用来切换显示模式这个属于锦上添花核心逻辑不变。我画框图的时候习惯按照数据流方向来组织分频时钟 - 测距控制状态机 - 计数器 - 距离计算 - BCD转换 - 数码管驱动报警模块单独挂在测距结果后面。这种结构的好处是每个模块的单向依赖非常清晰调试的时候可以直接在仿真波形里追踪一条数据链从产生到显示的完整路径。顶层接口我定义如下clk系统时钟50MHz或100MHz具体看板子rst_n异步复位低有效trig输出到HC-SR04的触发脉冲echo来自HC-SR04的回波电平输入seg_data_o、seg_sel_o数码管段选和位选信号buzzer_o蜂鸣器驱动输出这里有个细节蜂鸣器分有源和无源两种。有源蜂鸣器内部带振荡源高电平就响无源蜂鸣器需要一定频率的方波驱动。我用的板子是无源蜂鸣器所以报警模块里还加了一个分频生成约2kHz方波的逻辑这个后面讲代码的时候会体现。2. 核心模块原理与关键代码实现2.1 分频器设计从开发板时钟得到可用基准系统时钟一般是50MHz周期20ns。测距控制需要微秒级别的时序直接拿50MHz计数做延时比较繁琐所以第一步是做个分频得到1MHz的时钟也就是时钟周期1us这样后面所有延时和计数都以us为单位逻辑会清爽很多。分频的VHDL实现很简单就是对系统时钟计数计数到24就翻转输出得到约1.0417MHz误差很小更严谨的做法是计数到25产生一个脉冲使能信号。我在实际代码里用的是“时钟使能”方式而不是真正分频出独立时钟因为FPGA里面随意分频出时钟会产生额外的时钟域时序约束麻烦。使能方式的好处是主时钟还是50MHz但每50个周期产生一个1MHz脉冲测距模块在这个脉冲使能下计数既能产生us精度又避免了跨时钟域问题。代码如下process(clk, rst_n) begin if rst_n 0 then cnt_50 (others 0); en_1m 0; elsif rising_edge(clk) then if cnt_50 49 then cnt_50 (others 0); en_1m 1; else cnt_50 cnt_50 1; en_1m 0; end if; end if; end process;这里要提醒一下en_1m是一个高有效一个时钟周期的脉冲不是电平所以使用它的模块只能在使能脉冲到来时动作一次这样才能保证计时单位确实是1us。2.2 超声波测距时序HC-SR04的完整通信协议HC-SR04这个传感器几乎成了学习板标配通信时序非常标准只要照着数据手册来就不会错主机给Trig引脚拉高至少10us传感器内部自动发出8个40kHz超声波脉冲。传感器检测到回波后把Echo引脚拉高高电平持续时间就是从发射到接收的往返时间。距离 Echo高电平时间(us) / 58单位厘米。为什么是58因为声音在空气中的速度约340m/s往返时间除以2得到单程时间再乘声速换算成厘米后大约是每us对应0.017cm即1 / 58 cm每us。主控部分要做的核心就是周期性产生10us的Trig脉冲然后测量Echo高电平持续了多长时间。这放在FPGA里就是用状态机加计数器。状态机我设计了四个状态IDLE、TRIG、WAIT_ECHO、COUNTING。IDLE状态下等待下一次测量周期到来TRIG状态下拉高Trig持续10个us然后进入WAIT_ECHO等待Echo变高一旦Echo为高就进入COUNTING状态用1MHz时钟脉冲计数直到Echo变低锁存计数值返回IDLE。这里有个非常关键的细节Echo信号是外部输入来自传感器模块必须做同步处理否则很容易出现亚稳态导致偶尔计数跳变。我在代码里用两级寄存器对echo做了打拍同步process(clk, rst_n) begin if rst_n 0 then echo_d1 0; echo_d2 0; elsif rising_edge(clk) then echo_d1 echo; echo_d2 echo_d1; end if; end process;后面所有逻辑都用echo_d2不要直接用原始的echo。这个习惯能帮你省掉大量奇怪的“灵异bug”。2.3 距离计算与数码管动态显示计数值得到后接下来就是算距离并显示。距离换算公式是距离(cm) 计数值(us) / 58。直接用除法器会比较消耗资源我的做法是查表或者用移位近似的思路。58不是一个2的整数次幂但可以先除以64再修正误差在可接受范围。更简单的做法是做一个除以58的组合逻辑除法器VHDL里用循环减法实现代码也不长process(count_raw) variable remain : integer range 0 to 20000; variable result : integer range 0 to 20000; begin remain : count_raw; result : 0; while remain 58 loop remain : remain - 58; result : result 1; end loop; distance_buf result; end process;实际测下来这种迭代除法在50MHz下对于20000以内的被除数一次组合逻辑计算时间完全够用不需要做成多周期。得到距离值之后要送到数码管显示。四位数码管常见配置是共阴极动态扫描原理很简单同一时刻只点亮一位轮流点亮每一位利用视觉暂留让人觉得四个位同时亮。刷新频率至少做到50Hz以上我一般做1kHz扫描也就是每位亮1ms这样亮暗循环下来完全看不到闪烁。数码管的驱动核心是两个部分位选信号和段选信号。位选决定了当前点亮哪一位段选决定了这位显示什么数字。BCD转七段码用case语句实现注意共阴极数码管要点亮段码对应位为1。2.4 报警阈值分档蜂鸣器驱动逻辑倒车雷达的报警逻辑一般分三档方便模拟真实场景。我设定的阈值是距离范围报警模式大于100cm不报警30cm~100cm慢速间断响小于30cm持续快速响慢速间断响的实现思路是从距离值推断障碍物越近蜂鸣器响的频率越高。比如100cm时每秒钟响200ms停800ms30cm时响500ms停500ms。这个需要用报警模块里的计数器分出一个1kHz或500Hz的基础节拍再根据距离阈值控制占空比。无源蜂鸣器这边还额外需要一个载波信号。我用系统时钟分频出2kHz方波当报警使能有效时把2kHz方波送到蜂鸣器引脚报警使能无效时输出低电平。这样逻辑上就是“使能门控载波”实现起来非常直白。3. 实操过程与工程搭建要点3.1 开发环境与新建工程软件方面我用的是Quartus Prime搭配ModelSim做仿真这两个工具算是Intel FPGA开发的标准组合。如果你用的是Xilinx的板子那就是Vivado加Vivado SimulatorVHDL代码本身基本可以移植差异主要在工程的引脚约束文件格式。新建工程的时候有几点注意顶层实体名建议直接叫car_radar避免中文路径工程路径不能有空格和中文。芯片型号选择要和你手里的板子一致否则引脚分配和编译综合会有问题。综合设置里语言版本选VHDL-2008因为后面很多便利写法在2008版本里才支持。把所有模块都写了之后顶层例化关系如下clk_div_en产生1MHz使能脉冲hc_sr04_ctrl测距状态机输出计数值distance_calc计数值转距离seg_driverBCD转七段码动态扫描buzzer_ctrl阈值判断输出蜂鸣器控制信号3.2 仿真验证这一步千万别跳过我见过不少同学代码写完直接下板子结果显示乱跳或者蜂鸣器乱响这时候调试极其痛苦。正确做法是先做仿真把每个模块单独仿真一遍再顶层联合仿真。仿真主要看三个信号trig、echo、count_out。Testbench里面我模拟HC-SR04行为检测到trig变高后等10us再拉高echo模拟回声延迟。比如我要模拟50cm距离那么echo高电平应该持续约2900us因为58 * 50 2900us。我拿ModelSim跑完波形后重点确认trig脉冲宽度是不是正好10us周期是不是符合设定echo拉高期间count_out增加echo拉低后count_out保持距离换算结果是不是接近输入的模拟距离这几个点验证通过基本就能下板了。仿真能过滤掉90%的逻辑错误板级调试主要集中在接口和时序约束上。3.3 引脚约束与板级调试记录下板之前要分配引脚。每个开发板的引脚定义不一样我用的板子上HC-SR04的Trig接在FPGA的某个普通IOEcho接在另一个IO数码管段选用了8个引脚位选用了4个引脚蜂鸣器1个引脚。在Quartus里用Pin Planner分配或者直接写SDC文件两种方式都行。这里必须强调Echo输入引脚要检查开发板原理图确认有没有外部下拉或上拉电阻这会影响空闲状态的电平判断。HC-SR04模块本身是5V供电的如果FPGA是3.3V的IO电平Echo输出高电平是5V直接接入FPGA IO会存在电平不匹配问题。处理方法有两种用分压电阻把5V降到3.3V或者买3.3V供电版本的超声波模块。我第一次做的时候忽略了这个问题导致Echo信号在FPGA中被钳位测距值偏大。后来加了一个1k和2k的分压电阻才解决。板级调试时最常遇到的现象就是距离显示值倒着走越靠近障碍物数值越小这是对的但如果数值随机跳变优先检查Echo信号有没有毛刺其次检查Trig信号是不是被其他信号干扰。可以写个最简单的测距模块只测一个数然后停下用示波器或逻辑分析仪看Echo波形这样能快速定位问题。4. 常见问题与排查技巧实录4.1 Echo信号毛刺导致计数值异常超声波模块的Echo输出在发射瞬间会有一次短暂的拉高现象这个不是真实的回波但逻辑上它也会触发计数状态机导致计数从很微小的值开始。症状就是距离显示偶尔跳到一个极大的值或极小值不稳定。解决办法有两个层面。硬件层面在Echo引脚加一个RC滤波比如10k电阻串联再并一个0.1uF电容到地把窄毛刺滤掉。软件层面在状态机里加一个“最小有效脉宽判断”只有Echo高电平持续超过比如100us才认为是有效回波否则忽略。我最终是两层都加了效果最稳定。4.2 数码管显示闪烁或者亮度不均动态扫描最容易犯的错误是刷新频率太低。如果系统时钟是50MHz每位数码管亮1ms扫描周期就是4ms刷新率250Hz理论上人眼看不到闪烁。但实际上如果位选切换和段选数据更新之间存在竞争也就是旧数据还没消失就切了位选就会出现拖影。正确的驱动顺序是先送段选数据稳定一小段时间几十纳秒即可再切换位选数据稳定期间关闭所有位。这种“先数据后扫描”的顺序可以避免显示残影。另外段选驱动电流如果不均匀也会导致某些数字明显偏暗这个可以通过调整段选限流电阻来均衡。调试的时候我习惯把刷新周期放慢到100ms左右观察每一位是否正常点亮逐位确认无误后再加快到正常速度这样比较容易定位是哪一位的硬件问题还是驱动逻辑问题。4.3 测距误差偏大或者测量盲区倒车雷达一般有2cm左右的误差是比较合理的如果偏差很大先检查传感器安装方向和障碍物表面。超声波对平滑硬表面的反射最好对海绵、布料这类吸音材料反射很弱测量距离会偏大这属于物理限制不是代码问题。还有一个常见坑温度影响声速。0℃时声速约331m/s30℃时约349m/s相差5%左右。代码里按340m/s算在温差大的环境下自然有误差。要求高的话可以加个温度传感器做声速补偿但这属于扩展功能课程设计阶段不做也完全没问题。另外要注意测量盲区。HC-SR04的盲区大概2cm左右也就是说障碍物离传感器太近反而测不到。倒车雷达的真实使用场景中2cm盲区是可以接受的但如果你显示“0cm”或者乱码别愣着先确认是不是进入盲区了。4.4 编译报错与资源占用问题VHDL编译报错最多的两类一是std_logic_vector长度不匹配比如把一个8位的信号赋值给16位信号二是Process里信号和变量混用。我给的源码里已经把这些坑都处理干净了但你自己改代码的时候很容易再踩。还有一点当计数器宽度不够时综合工具会报warning而不是error但下板后表现就是距离超过某个值就溢出。我设计时把计数器定在16位最大能计时65535us对应距离约1129cm足够倒车雷达使用。如果你测量的距离更远需要扩到17位或18位。资源占用方面这个工程逻辑单元大概占用几百个LE几乎任何入门级FPGA都能轻松跑起来不用担心资源不够。我用的是EP4CE6E22C8综合后利用率不到10%。5. 项目扩展与一点心得体会这个项目做完之后如果还想折腾有几个方向性价比很高。一是把显示从数码管改成LCD1602或者OLED能显示更多信息比如“距离: 1.25m”这种带小数点的数据这就需要增加字符库和总线时序模块。二是加一个旋转扫描机制用一个步进电机带动超声波传感器转起来配合角度信息就能模拟真实的倒车雷达多区域扫描效果。三是在FPGA内部做均值滤波对连续多次测量结果取平均能进一步抑制噪声这在真实产品里是必须的。源码打包版本我做了详细的注释顶层模块和各子模块一一对应还附带了一个ModelSim的Testbench示例你把整个文件夹拷贝到本地用Quartus直接打开就能跑不需要额外配置。获取方式放在文章末尾的资源说明里了。最后说点自己的体会。做FPGA项目尤其像倒车雷达这种带外部传感器的项目花在代码上的时间其实只占一半剩下的一半基本都耗在“信号为什么不对”这种问题上。我建议你养成一个习惯每次遇到奇怪的信号问题先用逻辑分析仪或者示波器看实际波形再回看仿真波形对照绝大多数问题都能通过这一步定位到是接口时序问题还是内部逻辑问题。真正的调试能力就是在这一次次对照中练出来的。本文还有配套的精品资源点击获取
返回列表