简介:基于 STM32 控制 BGT24MTR11 毫米波雷达芯片的完整示例工程,面向嵌入式开发、雷达信号处理与短距离测距应用学习者,覆盖从 GPIO/SPI 接口配置、ADC 采集 I/Q 正交信号到 FFT 频谱分析和目标距离计算的全流程。BGT24MTR11 作为高性能毫米波雷达传感器,其 I/Q 输出包含目标距离、速度和角度信息,本工程有助于快速理解这类雷达在汽车防碰撞、工业自动化等场景中的实现方法。压缩包共有 637 个文件、约 14MB,主要包含 C 源码、H 头文件、汇编启动文件、IAR 链接配置文件以及 CubeMX 初始化文件(.ioc/.mxproject),其中 C 源码 347 个、头文件 116 个,辅以 44 个链接配置文件;源码中可见基于 STM32F4 HAL 库的定时器、I2C 等驱动,以及 CMSIS-DSP 库中的 FFT 相关源文件,可在 IAR EWARM 中直接打开工程调试。项目按 Src、Inc、Drivers 分层组织,目录结构清晰,适合对照学习代码逻辑与排错思路,也便于基于现有工程快速移植到其他应用场景。目前已有 1662 人学习,适合需要上手雷达数据采集与 FFT 测距的开发者参考。 第一次把BGT24MTR11这颗24GHz雷达收发器和STM32连在一起时,我最关心的问题只有一个:怎么用最简单的代码让它输出“有人/没人”的判断。查了一圈资料,发现这芯片和常见的温湿度传感器完全不是一个路子——它不是靠I2C/SPI连续读寄存器,而是输出一个模拟中频信号,交给MCU去解算。这篇文章就记录我用STM32控制BGT24MTR11做运动检测的完整过程,从硬件接法、信号调理、STM32采样代码,到实测数据和踩坑记录都会讲到。适合有STM32基础、但第一次接触毫米波雷达的嵌入式开发者。
1. 先弄清楚BGT24MTR11到底是颗什么芯片
1.1 内部框图与三句话拆解
BGT24MTR11是英飞凌推出的24GHz ISM频段雷达收发前端,内部集成了VCO压控振荡器、功率放大器PA、低噪声放大器LNA、混频器,核心功能可以三句话说明白:芯片产生24GHz连续波从天线发射出去,回波信号经LNA放大后与本振混频,最终从IF引脚输出一个频率很低的模拟信号。这个IF信号的频率和幅度里包含了目标的运动速度、距离、反射面积等信息。
和常见的24GHz雷达模块(比如RCWL-0516这类)不同,BGT24MTR11不带完整的信号处理链,不输出“有人/没人”的数字电平,它只负责射频收发和下变频。想要得到具体的判断结果,后端必须接MCU对IF信号做采样和分析。这正是STM32的用武之地。
1.2 三种工作模式怎么选
根据数据手册,BGT24MTR11支持三种工作模式:
- 自动模式(Automatic Mode):芯片上电后VCO由内部电路偏置控制,直接输出24GHz连续波,不需要外部给调谐电压,也不需要配置寄存器。最省事。
- 外部调谐模式(External Mode):通过VTune引脚注入模拟电压来控制VCO频率,配合外部PLL或者MCU的DAC可以产生FMCW调频连续波,实现测距功能。
- 寄存器配置模式(Register Mode):通过芯片上两线数字接口(有的资料标记为SCK/SDA,实际更接近一种简化串行接口)写入配置,可以调整分频器、输出功率等参数。
做“简单控制”,我的建议是直接用自动模式。BGT24MTR11虽然没有内部存储配置的寄存器组,但自动模式上电就能发波,对于运动检测、存在检测这类应用完全够用,能省掉一大半调试时间。等基础检测跑通了,再考虑用外部调谐模式做FMCW测距,或者用两线接口做更精细的配置。
2. 硬件接线与最简驱动电路设计
2.1 自动模式让芯片先“跑起来”
要让BGT24MTR11工作在自动模式,硬件接法非常简单:3.3V电源给VCC供电,EN使能引脚拉高,VTune引脚悬空或者接一个固定的1/2 VCC电压,RF输出TX接发射天线,RF输入RX接收天线,IF1/IF2差分输出接后端信号调理电路。
但这里有一个新手容易忽略的点——电源质量。BGT24MTR11内部VCO对电源噪声非常敏感,如果直接用STM32板子上的3.3V供电,数字电路开关噪声会耦合到VCO上,导致IF输出出现明显的杂波干扰。我在第一版测试时直接用开发板的3.3V供电,示波器上IF信号毛刺严重,后来在VCC引脚附近加了一颗10uF钽电容并联100nF陶瓷电容,把模拟电源和数字电源用0欧电阻或磁珠隔离,噪声一下子降了一个数量级。
自动模式下IF输出是差分信号,幅度很小,典型值在几毫伏到几十毫伏量级,直接进STM32的ADC根本采不到有效信号。必须对IF输出做放大和偏置处理,这部分下一节详细讲。
2.2 STM32侧接口分配与PCB布局建议
我用的是STM32F103C8T6核心板,资源足够。接口分配如下:
| STM32引脚 | 连接对象 | 功能说明 |
|---|---|---|
| PA0 | 调理后的IF信号(单端) | ADC采样输入 |
| PB0 | BGT24MTR11 EN引脚 | 控制芯片使能/关闭 |
| PA9 | 无 | 串口TX输出检测结果 |
| PA10 | 无 | 串口RX调试用 |
| PB3/PB4 | 备用 | 后续加两线接口配置用 |
需要注意PB3和PB4默认是JTAG引脚,如果要用它们做普通IO控制,需要在代码里执行JTAG关闭重映射,否则引脚电平不受控制。
PCB布局方面,如果你手上有BGT24MTR11的官方评估板或者最小系统板,直接买现成的会省很多麻烦。非要自己画板的话,记住三条原则:射频走线尽量短且阻抗控50欧;TX和RX区域用大面积地过孔围起来防止信号串扰;IF差分输出走线要尽量对称,避免两个通道相位不一致。这些细节直接决定雷达能测多远、信号有多干净。
3. STM32端的采样与运动检测实现
3.1 IF信号的特征与调理电路
自动模式下,如果有目标在雷达前方运动,IF引脚输出的是一路低频交流信号。目标径向速度越快,IF频率越高;目标越大、离天线越近,IF幅度越大。静止目标或环境静止时,IF输出基本是一条平稳的直流线。
实际电路我用的是单端方案,IF1接信号路径,IF2悬空,经过一个隔直电容去掉直流分量,再叠加到1.65V偏置电压上,送入运放放大。参考电路:
- C1: 100nF 隔直电容
- R1: 100k 偏置电阻接VCC/2
- 运放: OPA2376 或者 LMV358,单电源3.3V供电
- 放大倍数: 100倍左右(Rf/Rg = 100k/1k)
放大后的信号接到STM32的PA0,因为PA0是ADC输入引脚,同时建议在PA0对地并联一个100pF电容做简单的低通滤波,滤掉高频干扰。
这里有个细节:VCC/2的偏置电压如果直接用两个分压电阻产生,最好加一个运放缓冲或者大电容滤波,因为ADC采样瞬间会有电荷抽取,偏置电压不稳会直接影响采样结果。
3.2 ADC+DMA采样代码
软件层面,我用定时器触发ADC采样,DMA搬运数据,这样CPU不需要全程参与采样,可以省出来做数据处理和串口输出。
配置思路:TIM3定时器输出TRGO事件,触发ADC1的规则通道采样,采样率设置为10kHz,ADC转换完通过DMA把数据搬到一个环形数组里,数组长度1024,代表大约100ms的数据窗口。
// ADC+DMA初始化(HAL库版本) void radar_adc_init(void) { // 使能时钟 __HAL_RCC_ADC1_CLK_ENABLE(); __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_TIM3_CLK_ENABLE(); // ADC配置 hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; HAL_ADC_Init(&hadc1); // 通道配置 sConfig.Channel = ADC_CHANNEL_0; // PA0 sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; HAL_ADC_ConfigChannel(&hadc1, &sConfig); // 定时器触发配置:72MHz / (72-1) / (10-1) = 100kHz,再分频到10kHz htim3.Instance = TIM3; htim3.Init.Prescaler = 72 - 1; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 10 - 1; HAL_TIM_Base_Init(&htim3); TIM_MasterConfigTypeDef sMasterConfig = {0}; sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig); // DMA配置 hdma_adc.Instance = DMA1_Channel1; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; HAL_DMA_Init(&hdma_adc); __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc); HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc_buf, SAMPLE_NUM); HAL_TIM_Base_Start(&htim3); }采样数据拿到后,主要做两步:去直流和算能量。因为静止环境时ADC读数是接近偏置电压的一个常量,目标运动时才出现交流分量。用一帧数据的平均值作为直流估计,然后把每个采样点减去平均值求平方和,就得到这一帧的交流能量:
// 运动检测核心逻辑 #define SAMPLE_NUM 1024 #define MOTION_THRESHOLD 5000 uint16_t adc_buf[SAMPLE_NUM]; int radar_motion_detect(void) { uint32_t sum = 0; float mean, energy = 0; for (int i = 0; i < SAMPLE_NUM; i++) { sum += adc_buf[i]; } mean = (float)sum / SAMPLE_NUM; for (int i = 0; i < SAMPLE_NUM; i++) { float diff = (float)adc_buf[i] - mean; energy += diff * diff; } if (energy > MOTION_THRESHOLD) { return 1; } return 0; }阈值5000是我这个电路增益下调试出来的经验值,实际使用中要根据你的放大倍数和现场环境重新标定。更稳妥的做法是上电后跑几秒采集噪声底,把阈值设成噪声底能量乘一个系数比如5倍。
3.3 用定时器捕获直接测多普勒频率
有些场景不满足于“动/没动”的布尔判断,还想知道目标大概的运动速度。这时候可以给IF信号加一级比较器,把模拟信号整形成方波,然后用STM32的定时器输入捕获功能测量频率。
多普勒频率和目标速度之间的关系是:
v = fd × λ / 2
24GHz频段对应波长λ约为12.5mm,所以如果测得多普勒频率fd=100Hz,目标速度就是0.625m/s,大约2.25km/h。一个人正常步行的速度大概在1-2m/s,对应多普勒频率大约是160-320Hz,这个频率范围用定时器捕获非常合适。
定时器捕获配置我是这么做的:选择TIM4的通道1做输入捕获,上升沿触发,捕获值存入CCR寄存器。软件里用DMA读取捕获值或者直接在中断里计算相邻两个捕获值的差值,再换算成频率。100Hz到1kHz的信号采集都很稳定。
4. 实测数据、踩坑记录与调试技巧
4.1 一组实测场景数据
我在办公室走廊做了一轮实测,BGT24MTR11模块固定在一侧墙面,STM32用串口把能量值和中频信号特征打印出来。以下是一组典型的测量结果:
| 测试场景 | IF信号峰峰值 | ADC能量值 | 检测结果 |
|---|---|---|---|
| 静止环境,无人 | 约30mV(噪声底) | 800-1000 | 无触发 |
| 人员2米处慢速走过 | 约150mV | 12000 | 触发 |
| 人员5米处正常步行 | 约80mV | 4500 | 触发 |
| 人员10米处 | 约40mV | 1800 | 弱触发/不稳定 |
| 有人在3米处静止站立 | 约35mV | 1100 | 无触发 |
可以看到,运动检测在5米内效果比较可靠,超过10米就基本不可用了,这符合小尺寸天线和低发射功率的典型表现。静止站立检测不到是因为自动模式的连续波本身就是靠多普勒效应,目标静止时回波和本振混频出来的只是一个直流分量,没有频率变化,自然检测不到。
4.2 常见问题与排查速查表
调试过程中遇到问题不要慌,大部分问题都能归到下面这几类:
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| 上电后IF输出一直接近VCC或GND | 偏置电路异常或运放自激 | 断开运放,测量偏置电压是否等于VCC/2 |
| 检测距离明显偏近 | 电源纹波大、天线布局损耗 | 加强电源滤波,检查天线区域覆铜和过孔 |
| 误触发频繁 | 阈值过低、强反射体摆动 | 提高阈值,增加环境噪声标定流程 |
| 人和模块之间有玻璃隔断时检测不到 | 玻璃反射强,透射损耗大 | 改变安装位置,避免正对玻璃 |
| ADC读数稳定但能量始终跳变 | 供电波动或地线干扰 | STM32和雷达模块共地,用星型接地方式 |
排查时先用示波器看IF输出波形是最快的。没有示波器的话,可以写个小程序把ADC原始值通过串口打印到PC端,画一个简单的波形图。看多了就能建立直觉:正常噪声是比较平整的两三格跳动,有目标经过时会出现明显的正弦包络。
4.3 关于稳定性与干扰处理的个人心得
反复调试了几天,我觉得有两个问题值得单独提出来。
第一个是电源和地的处理。BGT24MTR11是射频芯片,它对电源的干净程度要求比普通传感器高得多。我在第二版电路里给雷达单独用了一路LDO输出3.3V,和STM32的数字电源完全分开,只在系统单点处共地。这样处理后,IF信号的底噪从之前的50mV降到20mV左右,检测距离也明显变远了。
第二个是环境自校准。固定的阈值在实验室环境好使,换到实际场景就不行了,因为温湿度、背景物体、供电电压都会影响噪声底。我后来加了一个上电自校准流程:系统启动后前2秒采集噪声能量,取平均值乘以系数作为动态阈值,之后进入正常检测循环。这个改动让误触发率大幅下降,强烈建议你也这么做。
另外,BGT24MTR11的上电时序也要注意。EN引脚拉高后,VCO需要一小段时间稳定,我实测大概要5ms左右。如果EN一拉高就立刻采数据,前几十个点的数据会有明显的过冲,建议给EN加一个延时再开始采样,或者在软件里丢弃前50个样本点。
5. 往这个项目上还能扩展什么
如果你的项目跑通了上面这套基础检测流程,后面能玩的方向其实挺多。
最实用的是FMCW测距。把VTune引脚接到外部PLL(比如ADF4158)或者STM32的DAC输出,施加一个三角波调谐电压,VCO频率就会跟着线性变化。回波和本振混频后的IF频率就正比于目标距离,通过FFT算出这个频率就能得到距离值。这一套做好了,BGT24MTR11可以变成一颗低成本近距离雷达测距模块。
第二个方向是低功耗检测。STM32的L0/L4系列支持低功耗模式,把BGT24MTR11做成周期性开启的雷达检测器,平时睡眠、有目标运动时唤醒,可以用电池供电做半年以上的存在检测设备。雷达的穿透性比红外好,作为房间人员检测比PIR传感器更可靠。
第三个方向是数据上报。把检测结果通过Wi-Fi模块、蓝牙或者LoRa上报到网关,做成无线联动方案。我在这个项目里加的是一颗ESP8266,检测到有人运动时通过串口发一个MQTT消息,实测延时大概20ms以内,做联动控制完全够用。
如果你也想在自家项目里用上这个方案,我的建议是先用自动模式把IF采样和运动检测跑通,再去碰FMCW和低功耗。这一步走稳了,后面的路就顺了。
本文还有配套的精品资源,点击获取