基于fpga的单线激光雷达数据处理
激光雷达:
首先来给大家稍微介绍以下激光雷达,激光雷达,即Light Detation and ranging,它相比于其他雷达,优点非常明确,包括 1)、具有极高的分辨率;
2)、抗干扰能力强;
3)、获取的信息量丰富;
4)、全天时工作;
最近一段时间有幸接触到镭神LS01C型单线激光雷达,LS01C型激光雷达是深圳市镭神智能系统公司研发的一款低成本二维扫描测距产品。该激光雷达可实现6米范围内的360°二维平面扫描,产生空间的平面点云地图用于地图绘制、机器人自主定位导航、智能设备壁障等应用。
激光测距采用激光三角测距系统,三角测距原理可参考
http://blog.csdn.net/xiangz_csdn/article/details/53814290
LSLIDAR通讯参数:
波特率:230400bps;
校验位:NONE;
数据位:8bits;
停止位:1bits;
数据格式:十六进制。
首先接触雷达,我从数据通信入手,通过uart串口发送启动指令(0xA5 0x2C 0xE1 0xAA 0xBB 0xCC 0xDD
)和停止指令(0xA5 0x25 0xE1 0xAA 0xBB 0xCC 0xDD
)来控制雷达运行和停止。采用两种方法来控制雷达运行状态:(1)、将启动和停止指令预存在程序中,然后和FPGA板子的开关相结合,通过开关来控制雷达;
(2)、采用串口助手来发送指令控制雷达运行和停止。
接下来贡上两种程序代码:
一、预存指令:
分为四个模块:分频模块clkdiv.v、发送模块uarttx.v、测试模块(存指令模块)test_tx_r.v、顶层模块top_tx_r.v
module clkdiv(clk, clkout); //分频模块 input clk; output clkout; reg clkout; reg [15:0] cnt; always @(posedge clk) begin //板子时钟为100MHZ,采用16倍波特率进行采样,计算得分频系数为27 if(cnt == 16'd13) begin clkout <= 1'b1; cnt <= cnt + 16'd1; end else if(cnt == 16'd27) begin clkout <= 1'b0; cnt <= 16'd0; end else begin cnt <= cnt + 16'd1; end end endmodule
module uarttx(clk, datain, wrsig, idle, tx);//发送模块 input clk; input [7:0] datain; //并行输入8位数据 input wrsig; //输入控制位,上升沿有效 output idle;//输出标志位 output tx; //串行输出数据reg idle, tx; reg send; reg wrsigbuf, wrsigrise; reg presult; //发送校验 reg[7:0] cnt; parameter paritymode = 1'b0; always @(posedge clk) //判断wrsig的上升沿 begin wrsigbuf <= wrsig; wrsigrise <= (~wrsigbuf) & wrsig; end always @(posedge clk) begin if (wrsigrise && (~idle)) //wrsig为上升沿且处于空闲状态发送数据begin send <= 1'b1; //进行发送 end else if(cnt == 8'd152) //8位数据发送完毕begin send <= 1'b0; end end always @(posedge clk) begin if(send == 1'b1) begin case(cnt) 8'd0: //发送起始位 begin tx <= 1'b0; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd16: //发送第一位 begin tx <= datain[0]; presult <= datain[0]^paritymode; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd32: //发送第二位 begin tx <= datain[1]; presult <= datain[1]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd48: //发送第三位 begin tx <= datain[2]; presult <= datain[2]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd64: //发送第四位 begin tx <= datain[3]; presult <= datain[3]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd80: //发送第五位 begin tx <= datain[4]; presult <= datain[4]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd96: //发送第六位 begin tx <= datain[5]; presult <= datain[5]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd112: //发送第七位 begin tx <= datain[6]; presult <= datain[6]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd128: //发送第八位 begin tx <= datain[7]; presult <= datain[7]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd144: //发送停止位 begin tx <= 1'b1; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd152: begin tx <= 1'b1; idle <= 1'b0;// 处于空闲状态,可以发数据 cnt <= cnt + 8'd1; end default: begin cnt <= cnt + 8'd1; end endcase end else begin tx <= 1'b1; cnt <= 8'd0; idle <= 1'b0; end end endmodule
module testuart(clk, dataout,wrsig,rst,key_mov,key_stop); input clk,rst; input key_mov;//开始开关 input key_stop;//停止开关 output[7:0] dataout; output wrsig; //发送指令标志位 reg [7:0] dataout; reg wrsig; reg [16:0] cnt; always @(posedge clk or negedge rst ) beginif(!rst)begindataout<= 0;cnt <=0;end else begin if(key_mov==1'b1)//运行开关闭合有效beginif(cnt <= 1779) //一组指令周期数begin //发送开始指令case(cnt)16'd254: begindataout <= 8'hA5;wrsig <= 1'b1; cnt <= cnt + 16'd1;end16'd508: begindataout <= 8'h2C;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd762: begindataout <= 8'hE1;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1016: begindataout <= 8'hAA;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1270: begindataout <= 8'hBB;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1524: begindataout <= 8'hCC;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1778: begindataout <= 8'hDD;wrsig <= 1'b1; cnt <= cnt + 16'd1;enddefault:beginwrsig <= 1'b0; cnt <= cnt + 16'd1;endendcaseendelse begin wrsig <= 1'b0; cnt <= 16'd0; end end else if(key_stop==1'b1)//停止开关闭合begin if(cnt <= 1779) begin //发送停止指令case(cnt)16'd254: begindataout <= 8'hA5;wrsig <= 1'b1; cnt <= cnt + 16'd1;end16'd508: begindataout <= 8'h25;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd762: begindataout <= 8'hE1;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1016: begindataout <= 8'hAA;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1270: begindataout <= 8'hBB;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1524: begindataout <= 8'hCC;wrsig <= 1'b1; cnt <= cnt + 16'd1; end16'd1778: begindataout <= 8'hDD;wrsig <= 1'b1; cnt <= cnt + 16'd1;enddefault:beginwrsig <= 1'b0; cnt <= cnt + 16'd1;endendcaseendelse begin wrsig <= 1'b0; cnt <= 16'd0; end end elsebegin wrsig <= 1'b0; cnt <= 16'd0; end end end endmodule
module uarttx(clk, datain, wrsig, idle, tx);//发送模块 input clk; input [7:0] datain; //并行输入8位数据 input wrsig; //输入控制位,上升沿有效 output idle;//输出标志位 output tx; //串行输出数据reg idle, tx; reg send; reg wrsigbuf, wrsigrise; reg presult; //发送校验 reg[7:0] cnt; parameter paritymode = 1'b0; always @(posedge clk) //判断wrsig的上升沿 begin wrsigbuf <= wrsig; wrsigrise <= (~wrsigbuf) & wrsig; end always @(posedge clk) begin if (wrsigrise && (~idle)) //wrsig为上升沿且处于空闲状态发送数据begin send <= 1'b1; //进行发送 end else if(cnt == 8'd152) //8位数据发送完毕begin send <= 1'b0; end end always @(posedge clk) begin if(send == 1'b1) begin case(cnt) 8'd0: //发送起始位 begin tx <= 1'b0; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd16: //发送第一位 begin tx <= datain[0]; presult <= datain[0]^paritymode; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd32: //发送第二位 begin tx <= datain[1]; presult <= datain[1]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd48: //发送第三位 begin tx <= datain[2]; presult <= datain[2]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd64: //发送第四位 begin tx <= datain[3]; presult <= datain[3]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd80: //发送第五位 begin tx <= datain[4]; presult <= datain[4]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd96: //发送第六位 begin tx <= datain[5]; presult <= datain[5]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd112: //发送第七位 begin tx <= datain[6]; presult <= datain[6]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd128: //发送第八位 begin tx <= datain[7]; presult <= datain[7]^presult; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd144: //发送停止位 begin tx <= 1'b1; idle <= 1'b1; //处于忙状态 cnt <= cnt + 8'd1; end 8'd152: begin tx <= 1'b1; idle <= 1'b0;// 处于空闲状态,可以发数据 cnt <= cnt + 8'd1; end default: begin cnt <= cnt + 8'd1; end endcase end else begin tx <= 1'b1; cnt <= 8'd0; idle <= 1'b0; end end endmodule
二、通过串口助手来发送:
分频模块和上面的一样,此处不再呈上;
module top(clk,rx,tx,idle); input clk,rx; output tx,idle;wire tx,idle; wire clkout,rdsig; wire [7:0] dataout;clkdiv clkdiv_inst(.clk(clk),.clkout(clkout));uarttx uarttx_inst(.clk(clkout), .datain(dataout), .wrsig(rdsig), .idle(idle), .tx(tx));uartrx uartrx_inst(.clk(clkout), .rx(rx), .dataout(dataout), .rdsig(rdsig));endmodule
module uartrx(clk, rx, dataout, rdsig); input clk; //采样时钟 input rx; //UART 数据输入 output dataout; //接收数据输出 output rdsig; reg[7:0] dataout; reg rdsig; reg [7:0] cnt; reg rxbuf, rxfall, receive; parameter paritymode = 1'b0; reg presult, idle; always @(posedge clk) //检测线路的下降沿 begin rxbuf <= rx; rxfall <= rxbuf & (~rx); end always @(posedge clk) begin if (rxfall && (~idle)) //检测到线路的下降沿并且原先线路为空闲,启动接收数据进程 begin receive <= 1'b1; end else if(cnt == 8'd152) //接收数据完成 begin receive <= 1'b0; end end always @(posedge clk) begin if(receive == 1'b1) begin case (cnt) 8'd0: begin idle <= 1'b1; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd24: //接收第 0 位数据 begin idle <= 1'b1; dataout[0] <= rx; presult <= paritymode^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd40: //接收第 1 位数据 begin idle <= 1'b1; dataout[1] <= rx; presult <= presult^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd56: //接收第 2 位数据 begin idle <= 1'b1; dataout[2] <= rx; presult <= presult^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd72: //接收第 3 位数据 begin idle <= 1'b1; dataout[3] <= rx; presult <= presult^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd88: //接收第 4 位数据 begin idle <= 1'b1; dataout[4] <= rx; presult <= presult^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd104: //接收第 5 位数据 begin idle <= 1'b1; dataout[5] <= rx; presult <= presult^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd120: //接收第 6 位数据 begin idle <= 1'b1; dataout[6] <= rx; presult <= presult^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd136: //接收第 7 位数据 begin idle <= 1'b1; dataout[7] <= rx; presult <= presult^rx; cnt <= cnt + 8'd1; rdsig <= 1'b0; end 8'd144: begin idle <= 1'b1; cnt <= cnt + 1'b1; rdsig <= 1'b1; end default: begin cnt <= cnt + 8'd1; end endcase end else begin cnt <= 8'd0; idle <= 1'b0; rdsig <= 1'b0; end end endmodule
module uarttx(clk, datain, wrsig, idle, tx); input clk; //UART 时钟 input [7:0] datain; //需要发送的数据 input wrsig; //发送命令,上升沿有效 output idle; //线路状态指示,高为线路忙,低为线路空闲 output tx; //发送数据信号 reg idle, tx; reg send; reg wrsigbuf, wrsigrise; reg presult; reg[7:0] cnt; //计数器 parameter paritymode = 1'b0; //检测发送命令是否有效 always @(posedge clk) begin wrsigbuf <= wrsig; wrsigrise <= (~wrsigbuf) & wrsig; end always @(posedge clk) begin if (wrsigrise && (~idle)) //当发送命令有效且线路为空闲时,启动新的数据发送进程 begin send <= 1'b1; end else if(cnt == 8'd152) //一帧资料发送结束 begin send <= 1'b0; end end always @(posedge clk) begin if(send == 1'b1) begin case(cnt) //产生起始位 8'd0: begin tx <= 1'b0; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd16: begin tx <= datain[0]; //发送数据 0 位 presult <= datain[0]^paritymode; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd32: begin tx <= datain[1]; //发送数据 1 位 presult <= datain[1]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd48: begin tx <= datain[2]; //发送数据 2 位 presult <= datain[2]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd64: begin tx <= datain[3]; //发送数据 3 位 presult <= datain[3]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd80: begin tx <= datain[4]; //发送数据 4 位 presult <= datain[4]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd96: begin tx <= datain[5]; //发送数据 5 位 presult <= datain[5]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd112: begin tx <= datain[6]; //发送数据 6 位 presult <= datain[6]^presult; idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd128: begin tx <= datain[7]; //发送数据 7 位 presult <= datain[7]^presult; idle <= 1'b1; cnt <= cnt + 10'd1; end 8'd144: begin tx <= 1'b1; //发送停止位 idle <= 1'b1; cnt <= cnt + 8'd1; end 8'd152: begin tx <= 1'b1; idle <= 1'b0; //一帧资料发送结束 cnt <= cnt + 8'd1; end default: begin cnt <= cnt + 8'd1; end endcase end else begin tx <= 1'b1; cnt <= 8'd0; idle <= 1'b0; end end endmodule
串口通信是熟悉板子的入门练习,可以深刻理解发送数据的方式,以及波特率的含义和计算。
转载于:https://www.cnblogs.com/hit-yhj/p/6695366.html
基于fpga的单线激光雷达数据处理相关推荐
- 享誉业界学界的2022年SuperComputing(SC22)又要来了,基于FPGA的硬件数据处理加速器值得关注
11月13-18日,全球极具影响力的高性能计算专业会议"International Conference on High-performance Computing, Networking, ...
- 202- K7 +C6678学习资料:基于TI DSP TMS320C6678、Xilinx K7 FPGA XC7K325T的高速数据处理核心板
基于TI DSP TMS320C6678.Xilinx K7 FPGA XC7K325T的高速数据处理核心板 一.板卡概述 该DSP+FPGA高速信号采集处理板由我公司自主研发,包含一片TI DSP ...
- 读论文之《基于 FPGA 的并行全比较排序算法》
为什么介绍这种排序算法:最近在独立编写霍夫曼编码的verilog HDL设计程序,其中用到了排序模块,对一组数据进行排序,苦寻几天,最终找到了这个全新的适合硬件实现的排序算法,分享与此,以空间换时间的 ...
- 基于 FPGA 的并行全比较排序算法,topK
以空间换时间的并行排序算法. https://blog.csdn.net/Reborn_Lee/article/details/80469391 并行全比较排序算法介绍 排序是一种重要的数据运算,传统 ...
- 一种基于FPGA硬件求解对数的简化方法
本文研究了一种运用FPGA进行数据处理的方法,包括:提取输入数据的高log2M个比特位的数据,作为高有效位,根据预先设置的目标函数的计算表格,查找所述高有效位对应的目标函数值y(n)以及高有效位+1对 ...
- 基于FPGA的深度卷积神经网络的加速器设计
英文论文链接:http://cadlab.cs.ucla.edu/~cong/slides/fpga2015_chen.pdf 翻译:卜居 转载请注明出处:http://blog.csdn.net/k ...
- 基于fpga的直流电机vhdl+论文+开题报告+(csdn免费下载)
下载资料链接 摘要 直流电机是日常生活中常见的一种能量转换装置,它应用广泛,功能强大,在生产生活中占据着重要位置.直流电机的控制方法多种多样,控制系统的组成更是五花八门.本文将采用现场可编辑门阵列FP ...
- 基于FPGA的DDS信号发生器
基于FPGA的DDS信号发生器 两个礼拜前就像写这个文档了,但是一直鸽到现在,主要是人摆了.还有个技术上的原因是,我想用串口屏显示波形,在串口调试助手上返回的数据是对的,但是发到串口屏上啥反应 ...
- 单线激光雷达原理深度解析
单线激光雷达是指激光源发出的线束是单线的雷达,具有三角测距及TOF激光雷达之分,主要以机器人领域应用居多.其扫描速度快.分辨率强.可靠性高,与多线激光雷达相比,单线激光雷达在角频率及灵敏度上反应更快捷 ...
最新文章
- 马斯克要办大学上了热搜
- 深度学习中多层全连接网络的梯度下降法及其变式
- Verilog基本语法初学
- san框架计数的textarea
- FPGA+NIOS2 Verilog+C 实现一个计算器
- 苹果ipadwps_ipad可以用wps吗?
- tcp的简单使用实例一
- php mysql 平均分_平均评级计算mysql php
- NHibernate剖析:Mapping篇之Mapping-By-Code(1):概览
- vue使用 xterm_为什么我坚持使用xterm
- 随想录(上位机客户端的编写)
- springboot-shiro-cas-redis集成session共享,权限共享
- hack the box(5985 WinRM)
- 发光学类毕业论文文献包含哪些?
- matplotlib is required for plotting.
- 【论文笔记】A survey on security and privacy of federated learning(综述)
- 微信 昵称带 表情存入mysql数据库
- Bypass disable_function【CTFHUB】
- Java(老白再次入门) - 入门概述
- 将dblp中的文件导入到endnote中