
玩毫米波雷达的老哥应该都有过这种经历板子上的跑分demo跑得挺欢串口里距离、速度、角度数据一帧一帧往外蹦看起来一切正常。可真到了自己要复现论文、做手势识别、整微多普勒特征的时候才发现芯片DSP算好的那些目标点云根本不够用——你拿不到底层ADC采样很多算法压根没有发挥空间。IWR6843搭配DCA1000EVM这套组合就是TI官方提供的抓取原始中频信号的标准方案。我这次用IWR6843ISK和DCA1000EVM在60GHz频段下把从硬件接线、mmWave Studio配置到MATLAB解析的整条链路完整跑了一遍顺手把解析代码整理出来了这篇文章就是完整还原。适合刚接触毫米波雷达、想自己动手处理原始ADC数据而不是只会点开demo看输出结果的同学参考。先说清楚整个过程不需要额外射频硬件只要一块IWR6843系列评估板、一块DCA1000EVM、一根网线和一台装了MATLAB的电脑。文章里所有步骤都是我这段时间实际操作验证过的包括我踩过的坑和调试过程里总结的排查经验不是那种只给结论不给过程的复制粘贴教程。1. 这套方案解决什么问题以及为什么推荐自己抓原始数据1.1 串口输出的目标点云和DCA1000抓到的原始数据有什么区别IWR6843这颗60GHz毫米波雷达芯片片上是自带处理链路的。配置好之后芯片内部会完成ADC采样、距离FFT、多普勒FFT、CFAR检测、角度估计最后通过UART口把一帧一帧的目标点云发出来。你拿到手的就是类似“距离3.5米、速度1.2米每秒、角度-10度”这种已经被封装好的结果。这种模式对快速验证车载或工业测距测速场景足够用了但问题也很明显。芯片内部算法是固定流程CFAR阈值、聚类参数、多普勒补偿这些都已经固化在固件里你改不了底层细节。一旦你的应用比较特殊比如要做手势识别、呼吸心跳检测、人体步态分析、微多普勒特征提取或者想在特定场景下定制一套检测策略就需要拿到最原始的ADC数据自己从第一级FFT开始处理。DCA1000EVM干的事情就是把IWR6843芯片内部ADC采样后的中频数据通过LVDS接口实时搬运到电脑上。这颗采集板本身不做信号处理它只负责高速数据采集、缓存和以太网传输。配合TI官方的mmWave Studio软件你能拿到一个包含原始帧数据的bin文件。后面所有信号处理工作都在你自己手里了。所以如果你只是想知道目标在哪串口输出完全够用但如果你想让雷达“看到”的东西变得更可控、更细粒度那就没法绕过DCA1000这套原始数据采集方案。1.2 为什么选MATLAB而不是Python或者C处理雷达数据语言选择其实挺主观。我自己用MATLAB是因为做算法原型迭代的时候实在太方便了。bin文件读进来之后一个fft函数就能把距离维处理掉imagesc直接画热图调试周期以分钟计。你用C当然也能做但光是把数据读出来、维度排列正确、再画个图就得折腾半天人很容易在重复劳动里失去耐心。Python的numpy、scipy是MATLAB的强力竞争对手如果你用惯了Python生态也可以把本文的MATLAB逻辑平移过去核心思想完全一样。但说实话在雷达信号处理这个领域MATLAB的社区积累和现成工具箱确实更厚实TI官方很多参考示例也都是MATLAB写的遇到问题对答案也更容易。还有一点值得提MATLAB的fread函数默认按小端字节序读取数据而DCA1000导出的bin文件正好就是小端格式这省掉了手动处理字节序的麻烦。新手第一次接触雷达数据的时候大量时间都耗在“为什么读出来的数全是乱的”这种问题上选MATLAB至少能少踩一个坑。2. 硬件连线、软件环境和那些容易踩的坑2.1 需要的物料和连接顺序物料清单其实很简单IWR6843ISK评估板一块或者IWR6843AOP也可以核心区别在AOP是把天线封装在芯片里ISK是外置天线DCA1000EVM数据采集板一块5V/3A直流电源适配器一个给DCA1000供电micro USB线一根连DCA1000到电脑烧录和配置用网线一根DCA1000通过以太网把数据传到电脑装了mmWave Studio和MATLAB的电脑连接顺序也是有讲究的。先把IWR6843ISK插到DCA1000EVM的60pin连接器上这个排插没有防呆设计插的时候要仔细对齐插反了不会立刻冒烟但芯片会异常发热数据更是完全采不到。然后把5V电源接到DCA1000的电源口上电后DCA1000会通过排针给IWR6843板卡供电所以这时候千万不要再插IWR6843板子自己的USB供电口两个电源同时供电非常容易出问题。最后再把DCA1000的USB线和网线都插到电脑上。有个细节需要注意IWR6843ISK板子上的SOP跳线必须拨到Functional Mode对应SOP0/SOP1/SOP2三位二进制是010。很多朋友第一次玩DCA1000用的还是之前刷固件时候的SOP配置结果在mmWave Studio里怎么都连不上折腾半天才发现是跳线没改回来。2.2 软件环境配置串口、IP、mmWave Studio版本软件这块推荐用mmWave Studio 2.1.0版本新版本界面和功能都和本文描述一致。MATLAB版本建议R2020a以上FFT和矩阵运算用基础模块就够工具箱不是硬性要求当然装了Signal Processing Toolbox会更顺手。驱动安装好之后在设备管理器里应该能看到两个XDS110相关的串口一个是XDS110 Class Auxiliary Port另一个是XDS110 Class UART Port。如果看不到这两个端口多半是驱动没装好回TI官网重新装XDS110驱动就行。DCA1000和电脑之间的以太网连接是很多人没搞明白的重点。DCA1000的网口默认IP地址是192.168.33.30所以电脑的有线网卡需要设置成静态IP比如192.168.33.180子网掩码255.255.255.0默认网关可以不填。设置完之后先在命令行里ping一下192.168.33.30能ping通再继续往下走。ping不通就检查网线连接、Windows防火墙是否拦了。软件配置方面还有一个小经验如果电脑同时连着WiFi和有线网记得把天线识别到的网络优先级调整一下或者临时禁用WiFi否则数据流经过的路由选择会有问题容易造成UDP丢包。实际采集的时候我习惯把不用的网络全部禁用只保留有线网卡。3. 数据采集mmWave Studio参数配置与bin文件格式解析3.1 一次实用的chirp配置参数打开mmWave Studio连接硬件后会进入Sensor Config和DCA1000两个配置区。Sensor Config就是配置雷达前端的参数包括chirp的起始频率、调频斜率、采样点数等。以下这组参数是我实际用的用来做室内人员走动检测效果和后续MATLAB处理都比较理想参数示例值说明Start Frequency60 GHzIWR6843的工作频段起点Frequency Slope60 MHz/μs调频斜率决定距离分辨率和最大测距范围Idle Time5 μschirp之间的空闲时间Ramp End Time60 μs单个chirp的持续时间Samples per Chirp128每个chirp内ADC采集的采样点数Chirps per Frame64每帧包含的chirp数量Frame Period100 ms帧周期LVDS Lane2使用2路LVDS通道RX Chain2打开2个接收通道这里面的参数选择不是随便拍的它们之间是有计算关系的。调频带宽斜率×有效调频时间60MHz/μs×60μs3.6GHz距离分辨率c/(2×带宽)3×10⁸/(2×3.6×10⁹)≈4.17cm。也就是说这套配置理论最小能分辨4公分的距离差。ADC采样率10MHz下最大不模糊距离c×fs/(2×斜率)3×10⁸×10⁷/(2×60×10¹²)25m做室内应用完全够用。多普勒维度的计算也一样。一个chirp周期idleTimerampTime65μs最大不模糊速度λ/(4×chirp周期)5mm/(4×65μs)≈19.2m/s差不多相当于69km/h对室内人体运动绰绰有余。速度分辨率λ/(2×chirp数×chirp周期)5mm/(2×64×65μs)≈0.6m/s也就是说速度相差小于0.6m/s的两个目标在热图上会融在一起。这些参数要心里有数不然采完数据用MATLAB画图发现距离轴对不上或者速度轴方向反了都不知道问题出在哪。3.2 bin文件到底长什么样参数配置好之后在mmWave Studio里设置DCA1000的工作模式点Arm Latch再点Trigger Frame采集完成之后会生成一个bin格式的原始数据文件。这个文件的结构本身不复杂但对于刚接触的人来说第一眼看到就是一坨二进制完全不知道从哪里下手。我直接说结论。bin文件最前面是128字节的header信息这里面包含文件标识Magic Word、帧编号、时间戳这类元数据。Magic Word的前两个16位整数是固定的0x7081和0x7FED可以作为校验文件是否有效的依据。对普通数据处理来说这128字节可以整体跳过。header之后才是真正的ADC数据区。数据区按照“帧→chirp→lane→sample”四层嵌套的先后顺序存储。以常见的2-lane配置为例一帧数据内部先存第一个chirp里lane0的全部采样点再存这个chirp里lane1的全部采样点然后接着存第二个chirp的数据依此类推。而每个采样点因为是复数格式拆成I和Q两个16位有符号整数I在前Q在后整体是小端字节序排列。所以如果你知道采集帧数numFrames、每帧chirp数numChirpsPerFrame、每个chirp采样数numADCSamples那么整个数据区包含的复数采样点总数就是numLanes×numADCSamples×numChirpsPerFrame×numFrames。算这个数的意义在于你可以用文件大小反推验证自己配置的参数和实际数据是否吻合很多采集异常都是在这个环节暴露出来的。3.3 数据分帧分chirp的解析逻辑接下来说一下我在MATLAB里实际的解析顺序。读取文件时先用fread把所有int16读进来然后跳过开头的64个int16128字节剩下的数据就是ADC采样序列。把序列按照“奇数是I偶数是Q”的方式拆开组成一个复数数组。这就得到了一个很长的一维复数数组它把所有帧、所有chirp、所有lane的数据首尾相接排在一起。解析的关键一步是把这一长串数据重新组织成四维数组维度顺序是numADCSamples×numChirps×numLanes×numFrames。听起来抽象但代码实现起来只要几个reshape。唯一容易翻车的地方是lane的顺序不同版本的DCA1000固件或不同配置下lane0和lane1的排列顺序可能会反过来。如果后面FFT出来的热图有明显异常先到这一步检查lane顺序别急着改后面的算法。header信息里有个小坑值得单独提醒DCA1000在数据文件开头放的128字节按uint16算是64个但如果你直接按uint8读数据就得跳过128个字节。很多人按uint16读却跳过了128个16位整数等于跳了256字节整个数据错位后面怎么处理都白搭。我建议统一用int16读跳64个值简洁而且不容易出错。4. MATLAB解析代码读文件、重排、距离-多普勒处理4.1 读取并重排原始数据下面这段函数是我实际在用的解析代码兼容常见的2-lane配置。把参数替换成你自己采集时配置的数值基本可以直接拿去用。function adc parseDCA1000(fileName, numLanes, numADCSamples, numChirps, numFrames) % 将DCA1000的bin文件解析为四维复数数组 % 输出维度: numADCSamples x numChirps x numLanes x numFrames fid fopen(fileName, rb); if fid -1 error(打不开文件检查路径和文件名); end raw fread(fid, inf, int16); fclose(fid); % 跳过128字节header按int16计为64个值 raw raw(65:end); % 期望的复数采样点总数 expected numLanes * numADCSamples * numChirps * numFrames; if length(raw) expected * 2 error(数据长度不足检查采集参数是否与实际文件一致); end raw raw(1:expected*2); % 拆成I/Q组成复数数组 iq complex(raw(1:2:end), raw(2:2:end)); frameSize numADCSamples * numChirps * numLanes; adc zeros(numADCSamples, numChirps, numLanes, numFrames); for f 1:numFrames frameIQ iq((f-1)*frameSize 1 : f*frameSize); if numLanes 2 % 每个chirp内: 先lane0全部采样再lane1全部采样 tmp reshape(frameIQ, numLanes, numADCSamples * numChirps); tmp tmp.; adc(:,:,:,f) reshape(tmp, numADCSamples, numChirps, numLanes); else % 单lane直接reshape adc(:,:,1,f) reshape(frameIQ, numADCSamples, numChirps); end end end这个函数的处理逻辑分三块。第一块读文件和跳header第二块按照I/Q交替的顺序还原复数采样点第三块按照帧、chirp、lane的嵌套顺序重新排列。这里我特意把重排过程一帧一帧循环来处理而不是一次性对整个数组做巨型reshape虽然循环稍微慢了一点但好处是内存占用低出问题也容易定位。如果采集的帧数特别大这个循环结构还能直接改成只处理其中某几帧灵活性高很多。4.2 距离FFT和多普勒FFT数据解析成四维数组之后信号处理就干净利落了。距离FFT沿着第一维对每个chirp的128个采样点做多普勒FFT沿着第二维对一帧内的64个chirp做。%% 参数设置 numADCSamples 128; numChirps 64; numFrames 50; numLanes 2; slope 60e12; % 调频斜率 Hz/s fs 10e6; % ADC采样率 Hz idleTime 5e-6; % idle time s rampTime 60e-6; % ramp time s fc 60e9; % 起始频率 Hz c0 3e8; Tc idleTime rampTime; lambda c0 / fc; %% 解析bin文件 adc parseDCA1000(record.bin, numLanes, numADCSamples, numChirps, numFrames); fprintf(数据维度: %d x %d x %d x %d\n, size(adc)); %% 距离维FFT加窗压低旁瓣 winR hamming(numADCSamples); rangeFFT fft(adc .* winR, numADCSamples, 1); %% 多普勒维FFT同样加窗 winD hamming(numChirps); dopFFT fft(rangeFFT .* reshape(winD, 1, numChirps, 1, 1), numChirps, 2); dopFFT fftshift(dopFFT, 2);这里为什么要加窗因为FFT处理有限长度信号不加窗时间频谱会有比较严重的旁瓣泄漏。一个强目标旁边会拖出一串虚假的峰值弱目标很容易被淹没。加汉明窗基本是雷达信号处理的标配操作代价是距离分辨率略微变差但对多数应用场景来说换来的旁瓣抑制效果更值。多普勒FFT之后还做了一次fftshift这步的目的是把零频分量挪到频谱中心。不shift的话速度轴是从最小负速度到最大正速度排列的不好看也容易算错。4.3 距离-多普勒热图可视化处理完FFT最后一步就是出图。距离轴和速度轴的换算在前面已经说过这里直接落成代码%% 坐标轴换算 rangeRes c0 / (2 * slope * rampTime); rangeAxis (0:numADCSamples-1) * rangeRes; dopRes lambda / (2 * numChirps * Tc); dopAxis (-numChirps/2 : numChirps/2-1) * dopRes; %% 幅度热图 rdMap squeeze(mean(abs(dopFFT).^2, 4)); % 多帧平均 figure; imagesc(dopAxis, rangeAxis, 10*log10(rdMap.)); axis xy; xlabel(速度 (m/s)); ylabel(距离 (m)); title(Range-Doppler Map); colorbar;imagesc里面为什么要把矩阵转置因为MATLAB的imagesc要求数据矩阵的第一维对应y轴第二维对应x轴。我们的rdMap维度是numADCSamples×numChirps对应的是距离维和速度维但画图时希望横轴是速度、纵轴是距离所以必须转置也就是rdMap.。很多新手在这一步没转置图片的横纵轴完全反了还以为是数据解析有问题折腾半天。关于幅度做不做多帧平均看你的场景。如果目标是移动的人单帧热图就能看到亮点多帧平均反而会把快速移动的目标拖糊。如果是静态场景想压低噪声平均几帧效果很好。我这版代码用的是平均因为用静态金属板做验证时平均出来的热图背景更干净便于检查算法链路是否正确。5. 常见问题与排查技巧总结5.1 数据解析乱了先查字节序和多lane顺序我在调试过程中遇到过几次“热图一团糟、完全看不出目标”的情况每次都是踩在同一类坑上。最典型的两种一是跳过header的字节数搞错了数据整体错位二是lane顺序反了导致多普勒维出现类似频闪的条纹。遇到这种情况我的排查顺序是固定的。先验证文件大小和期望数据量是否一致。然后画一个chirp的距离维FFT单帧谱看看有没有明显的峰值。如果单chirp谱正常但多普勒热图乱重点怀疑lane顺序。如果单chirp谱也是乱的先回头检查header跳没跳对再检查I/Q拆分逻辑。还有一个经验处理任何雷达数据之前先在场景正前方放一个金属板或者金属三角锥距离大概1到2米。这样你心里有预期知道峰值应该出现在哪个距离。如果热图上目标峰值不在预想位置甚至根本找不到你第一时间就知道是数据处理有问题而不是在怀疑采集环境。5.2 MATLAB内存不足DCA1000采集的bin文件大小取决于帧数帧数一多数据量迅速膨胀。按我们前面那组参数算一帧数据128×64×2×4字节等于64KB看起来不大但如果一次采几千帧文件也有几百兆。MATLAB读进来解析成complex double的数组之后内存占用又要翻好几倍几十帧没问题几百上千帧就很容易把内存撑爆。我实际用的办法是不需要一次处理全部帧时不要整个文件读进内存。要么在parseDCA1000函数里只读取指定区间帧要么用memmapfile做内存映射按片段访问数据。对于绝大多数算法验证场景先取前50帧或者前100帧跑通流程确认结果正确再决定要不要上全量大文件。一次采集、分块处理内存问题基本能绕开。5.3 mmWave Studio连不上、采不到数据连接类问题占了新手问题的一半以上。mmWave Studio点Connect没反应首先看SOP跳线是不是Functional Mode然后看设备管理器里两个串口是否存在再ping一下192.168.33.30通不通。三步排查下来基本能定位90%的问题。有一次我怎么都连不上最后发现是电脑防火墙把DCA1000的端口拦了。把防火墙临时关掉以后连接和数据采集立刻正常。另外网线质量也很关键普通劣质网线在长时间高速传输时会有丢包导致采集到的帧数跟预期对不上。我后来换了一根超五类网线问题就再没出现过。5.4 典型问题速查表现象可能原因解决办法数据读出来全是0LVDS连接不良或配置没生效重新插拔IWR6843与DCA1000重启mmWave Studio重新Arm热图只在速度0处有亮点场景中是静止目标或DC分量过强做多帧均值相消/MTI或检查是否有静态强杂波距离谱峰值在最后一个距离bin距离维采样率不足导致混叠降低ADC采样率或增大调频斜率重新评估最大测距多普勒热图出现规律条纹lane顺序反了或I/Q拆分错误交换lane顺序重新验证数据排列速度数值明显不对参数设置和脚本不一致核对chirp周期、chirp数、起始频率是否与mmWave Studio一致mmWave Studio连接失败SOP跳线错误/防火墙/网卡IP配置问题按SOP、串口、ping顺序逐一排查采集时UDP丢包严重网卡问题或网络干扰禁用WiFi关闭防火墙更换网线降低数据率这套排查表基本覆盖了DCA1000和IWR6843组合在数据采集和解析阶段的高频问题。真遇到怪问题建议先把mmWave Studio生成的控制日志打开看看里面会记录UDP包计数、配置下发状态等关键信息很多时候答案就藏在日志里。我个人的习惯是拿到bin文件后第一件事不是急着做完整的多普勒处理而是先只取一个chirp做距离维FFT确认距离谱上的峰值符合场景预期再继续往后走。这个习惯帮我省掉了大量无效排查时间有时候你以为的算法问题实际只是第一步的文件名读错或者数据顺序反了。另外后续如果你想让这套流程更快可以把距离FFT和多普勒FFT换成GPU加速的MATLAB代码或者移植到C配合fftw库核心逻辑不变但实时性会提升一大截。