CY8CKIT-062S2-AI开发板上的雷达芯片型号为BGT60TR13C,属于1T3R(1发3收)配置的雷达芯片,由于其有多个接收端,可以实现对物体的定位、手势识别、速度追踪等功能。雷达芯片中集成射频前端(Radio Frequency Front-end)、模拟基带(Analog Base Band)、模数转换器(ADC)、锁相环(PLL)、缓存器(FIFO)等实现雷达射频模拟信号的模数转换、信号过滤等功能。

芯片提供SPI接口和MCU通讯,MCU程序通过SPI接口配置雷达芯片寄存器的值,改变雷达的工作模式;从FIFO寄存器中读取采集的反射雷达信号数据,通过对其进行处理,判断雷达的工作空间中的物体信息。
1 示例程序演示
雷达芯片属于复杂的传感器芯片,查看BGT60TR13C的数据手册可知,该芯片的寄存器数量多大95个,手动配置芯片对于新手来说是做不到的。

CY8CKIT-062S2-AI开发板的示例程序中提供雷达存在检测的示例程序用于演示雷达芯片的使用,使用ModusToolbox的Project Creator创建该示例基于命令行的工程。选择目标IDE为命令行,根据提示选择开发板对应的BSP。

在示例选择界面选择传感器分类下的XENSIV_60GHz_Radar_Presence_Detection,创建该示例程序。

打开modus-shell命令行窗口,切换工作目录到示例文件夹中,modus-shell中的路径类似Linux的文件系统,切换盘符到D盘时,需要输入cd /cygdrive/d实现切换。

进入工作目录后,通过make指令即可对工程进行配置,完整的make指令使用可以查看《ModusToolbox tools packages user guide》中对build system的说明。

在命令行中输入make build构建和编译工程。
连接到开发板烧录程序时,可以使用make qprogram进行烧录,该指令跳过编译过程进行烧录操作。使用命令行进行工程管理时,相比集成的IDE环境有更多的选项选择,指令的运行速度也更快。
程序烧录完成后,通过串口工具监视开发板的输出信息。将雷达放置到显示器上部,在雷达的探测区域内移动,可以看到检测到不同位置信息后的输出。当区域内无人时,没有输出(可以从输出log中的tick信息判断相关)。区域内再次有人时,探测到目标并输出相关信息。

2 雷达芯片配置
雷达芯片的介绍网站为
https://www.infineon.com/cms/en/product/sensor/radar-sensors/radar-sensors-for-iot/60ghz-radar/bgt60tr13c/
英飞凌的Radar Development Kit用于配置雷达芯片的工作模式,发出调频波的参数以及采样周期。其中配套的bgt60-configurator-cli命令行工具可以将以JSON文件表示的雷达配置信息转换为相关的寄存器值列表。

bgt60-configurator-cli命令行工具的使用示例可以参考以下链接中的使用说明。
https://infineon.github.io/sensor-xensiv-bgt60trxx/html/index.html
在安装路径的Infineon\Tools\Radar-Development-Kit\3.6.5\assets\software文件夹中,可以找到tools.zipo的压缩包,其中就有bgt60-configurator-cli命令行工具,将其解压出来即可使用。

以下雷达配置为示例程序中配置BGT60TR13C雷达工作在10Hz扫描频率的配置。
{
"device_config": {
"fmcw_single_shape": {
"rx_antennas": [3],
"tx_antennas": [1],
"tx_power_level": 31,
"if_gain_dB": 60,
"lower_frequency_Hz": 61020098000,
"upper_frequency_Hz": 61479902000,
"num_chirps_per_frame": 16,
"num_samples_per_chirp": 128,
"chirp_repetition_time_s": 7e-05,
"frame_repetition_time_s": 100e-3,
"sample_rate_Hz": 2330000
}
}
}
使用以下指令,可以生成上述文件对应的雷达寄存器列表。
./bgt60-configurator-cli -c BGT60TR13C_radar_low_framerate_config.json -o presence_radar_settings.h

3 ModusToolbox工程库添加和使用
使用ModusToolbox的Project Creator创建一个空工程。

在工程的library manager中添加用于串口重定向的组件和雷达传感器驱动的组件。

ModusToolbox中使用这种"train model"(火车模型)的模式来管理工程组件,组件以git仓库和版本标签的方式添加到工程管理中,是个不错的选择。
在程序中添加以下代码初始化串口重定向模块,使用printf函数打印信息。
#include "cy_retarget_io.h"
cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);
Makefile文件中的配置变量是管理ModusToolbox工程的一部分,在Makefile中的DEFINES变量中添加CY_RETARGET_IO_CONVERT_LF_TO_CRLF可以在工程中使用\n表示\r\n,提高代码的兼容性。
4、雷达测试模式
创建board_resource.h头文件,并添加开发板LED、雷达芯片引脚、参数的宏。
#ifndef BOARD_RESOURCE_H
#define BOARD_RESOURCE_H
#define USER_LED1 CYBSP_USER_LED1
#define USER_LED2 CYBSP_USER_LED2
/* Interrupt priorities */
#define GPIO_INTERRUPT_PRIORITY (7)
#define XENSIV_BGT60TRXX_CONF_IMPL
#define XENSIV_BGT60TRXX_SPI_FREQUENCY (25000000UL)
#define PIN_XENSIV_BGT60TRXX_SPI_SCLK CYBSP_RSPI_CLK
#define PIN_XENSIV_BGT60TRXX_SPI_MOSI CYBSP_RSPI_MOSI
#define PIN_XENSIV_BGT60TRXX_SPI_MISO CYBSP_RSPI_MISO
#define PIN_XENSIV_BGT60TRXX_SPI_CSN CYBSP_RSPI_CS
#define PIN_XENSIV_BGT60TRXX_IRQ CYBSP_RSPI_IRQ
#define PIN_XENSIV_BGT60TRXX_RSTN CYBSP_RXRES_L
#endif
使用以下雷达配置JSON配置文件(使用其他配置会报错,以下配置经测试可以运行测试模式)生成对应的寄存器列表头文件
{
"device_config": {
"fmcw_single_shape": {
"rx_antennas": [1],
"tx_antennas": [1],
"tx_power_level": 31,
"if_gain_dB": 60,
"lower_frequency_Hz": 61020098000,
"upper_frequency_Hz": 61479902000,
"num_chirps_per_frame": 1,
"num_samples_per_chirp": 128,
"chirp_repetition_time_s": 7e-05,
"frame_repetition_time_s": 5e-3,
"sample_rate_Hz": 2330000
}
}
}
./bgt60-configurator-cli -c BGT60TR13C_radar_low_framerate_config.json -o radar_test_settings.h
将得到的头文件复制到工程的source文件夹中,Makefile在构建工程师会自动检索文件并加入到编译过程中。
定义雷达Chirp帧率和数据大小相关的宏
#ifndef RADAR_CONFIG_REG_LIST_H
#define RADAR_CONFIG_REG_LIST_H
//#include "presence_radar_settings.h"
#include "board_resource.h"
/*
* [url=/u/DEF]@DEF[/url] NUM_SAMPLES_PER_FRAME
* Number of samples per frame
* @note: Number of samples per frame
*/
#define NUM_SAMPLES_PER_FRAME (XENSIV_BGT60TRXX_CONF_NUM_SAMPLES_PER_CHIRP *\
XENSIV_BGT60TRXX_CONF_NUM_CHIRPS_PER_FRAME *\
XENSIV_BGT60TRXX_CONF_NUM_RX_ANTENNAS)
/*
* @def NUM_CHIRPS_PER_FRAME
* Number of chirps per frame
* @note: Number of chirps per frame
*/
#define NUM_CHIRPS_PER_FRAME XENSIV_BGT60TRXX_CONF_NUM_CHIRPS_PER_FRAME
/*
* @def NUM_SAMPLES_PER_CHIRP
* Number of samples per chirp
* @note: Number of samples per chirp
*/
#define NUM_SAMPLES_PER_CHIRP XENSIV_BGT60TRXX_CONF_NUM_SAMPLES_PER_CHIRP
#endif
定义用于存储雷达数据帧的缓存和数据就绪中断处理的变量和函数
static volatile bool data_available = false;
/* Allocate enough memory for the radar dara frame. */
static uint16_t frame[NUM_SAMPLES_PER_FRAME];
static void xensiv_bgt60trxx_mtb_interrupt_handler(void *args, cyhal_gpio_event_t event);
/* Interrupt handler to react on sensor indicating the availability of new data */
#if defined(CYHAL_API_VERSION) && (CYHAL_API_VERSION >= 2)
void xensiv_bgt60trxx_mtb_interrupt_handler(void *args, cyhal_gpio_event_t event)
#else
void xensiv_bgt60trxx_mtb_interrupt_handler(void *args, cyhal_gpio_irq_event_t event)
#endif
{
CY_UNUSED_PARAMETER(args);
CY_UNUSED_PARAMETER(event);
data_available = true;
}
雷达芯片BGT60TR13C和PSoC6 MCU的接口为SPI,定义对应的接口类型对象,并调用相关的函数对外设进行初始化。
#if defined (CY_USING_HAL)
#include "cyhal.h"
#endif
#include "cybsp.h"
#include <inttypes.h>
#include "xensiv_bgt60trxx_mtb.h"
#include "board_resource.h"
#include "radar_test_settings.h"
#include "radar_config_reg_list.h"
static cyhal_spi_t spi_obj;
static xensiv_bgt60trxx_mtb_t bgt60_obj;
static int32_t init_sensor(void)
{
if (cyhal_spi_init(&spi_obj,
PIN_XENSIV_BGT60TRXX_SPI_MOSI,
PIN_XENSIV_BGT60TRXX_SPI_MISO,
PIN_XENSIV_BGT60TRXX_SPI_SCLK,
NC,
NULL,
8,
CYHAL_SPI_MODE_00_MSB,
false) != CY_RSLT_SUCCESS)
{
printf("[MSG] ERROR: cyhal_spi_init failed\n");
return -1;
}
/* Reduce drive strength to improve EMI */
Cy_GPIO_SetSlewRate(CYHAL_GET_PORTADDR(PIN_XENSIV_BGT60TRXX_SPI_MOSI), CYHAL_GET_PIN(PIN_XENSIV_BGT60TRXX_SPI_MOSI), CY_GPIO_SLEW_FAST);
Cy_GPIO_SetDriveSel(CYHAL_GET_PORTADDR(PIN_XENSIV_BGT60TRXX_SPI_MOSI), CYHAL_GET_PIN(PIN_XENSIV_BGT60TRXX_SPI_MOSI), CY_GPIO_DRIVE_1_8);
Cy_GPIO_SetSlewRate(CYHAL_GET_PORTADDR(PIN_XENSIV_BGT60TRXX_SPI_SCLK), CYHAL_GET_PIN(PIN_XENSIV_BGT60TRXX_SPI_SCLK), CY_GPIO_SLEW_FAST);
Cy_GPIO_SetDriveSel(CYHAL_GET_PORTADDR(PIN_XENSIV_BGT60TRXX_SPI_SCLK), CYHAL_GET_PIN(PIN_XENSIV_BGT60TRXX_SPI_SCLK), CY_GPIO_DRIVE_1_8);
/* Set the data rate to 25 Mbps */
if (cyhal_spi_set_frequency(&spi_obj, XENSIV_BGT60TRXX_SPI_FREQUENCY) != CY_RSLT_SUCCESS)
{
printf("[MSG] ERROR: cyhal_spi_set_frequency failed\n");
return -1;
}
/* Wait LDO stable */
(void)cyhal_system_delay_ms(5);
if (xensiv_bgt60trxx_mtb_init(&bgt60_obj,
&spi_obj,
PIN_XENSIV_BGT60TRXX_SPI_CSN,
PIN_XENSIV_BGT60TRXX_RSTN,
test_register_list, // default config with macro settings
XENSIV_BGT60TRXX_CONF_NUM_REGS) != CY_RSLT_SUCCESS)
{
printf("[MSG] ERROR: xensiv_bgt60trxx_mtb_init failed\n");
return -1;
}
if (xensiv_bgt60trxx_mtb_interrupt_init(&bgt60_obj,
NUM_SAMPLES_PER_FRAME,
PIN_XENSIV_BGT60TRXX_IRQ,
GPIO_INTERRUPT_PRIORITY,
xensiv_bgt60trxx_mtb_interrupt_handler,
NULL) != CY_RSLT_SUCCESS)
{
printf("[MSG] ERROR: xensiv_bgt60trxx_mtb_interrupt_init failed\n");
return -1;
}
return 0;
}
在主函数中初始化SPI外设和雷达,使能雷达芯片的测试模式,并对数据进行校验输出。
int main(void)
{
cy_rslt_t result;
/* Initialize the device and board peripherals */
result = cybsp_init();
/* Board init failed. Stop program execution */
if (result != CY_RSLT_SUCCESS)
{
CY_ASSERT(0);
}
cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX, CY_RETARGET_IO_BAUDRATE);
/* Enable global interrupts */
__enable_irq();
printf("CY8CKIT-062S2-AI Radar Sensor Test!\r\n");
init_sensor();
/* Enable sensor data test mode. The data received on antenna RX1 will be overwritten by
a deterministic sequence of data generated by the test pattern generator */
if (xensiv_bgt60trxx_enable_data_test_mode(&bgt60_obj.dev, true) != XENSIV_BGT60TRXX_STATUS_OK)
{
CY_ASSERT(0);
}
if (xensiv_bgt60trxx_start_frame(&bgt60_obj.dev, true) != XENSIV_BGT60TRXX_STATUS_OK)
{
CY_ASSERT(0);
}
uint32_t frame_idx = 0;
uint16_t test_word = XENSIV_BGT60TRXX_INITIAL_TEST_WORD;
for (;;)
{
/* Wait for the radar device to indicate the availability of the data to fetch. */
while (data_available == false);
data_available = false;
if (xensiv_bgt60trxx_get_fifo_data(&bgt60_obj.dev, frame,
NUM_SAMPLES_PER_FRAME) == XENSIV_BGT60TRXX_STATUS_OK)
{
/* Check received data */
for (int32_t sample_idx = 0; sample_idx < NUM_SAMPLES_PER_FRAME; ++sample_idx)
{
if (test_word != frame[sample_idx])
{
printf("Frame %" PRIu32 " error detected. "
"Expected: %" PRIu16 ". "
"Received: %" PRIu16 "\n",
frame_idx, test_word, frame[sample_idx]);
CY_ASSERT(0);
}
// Generate next test_word
test_word = xensiv_bgt60trxx_get_next_test_word(test_word);
}
}
printf("Frame %" PRIu32 " received correctly\n", frame_idx);
frame_idx++;
}
}
程序烧录到开发板的输出log如下。

5. 总结
英飞凌ModusToolbox中与开发板相关的例程丰富,且配有详细的说明。创建空工程、添加库组件的功能简单易用,程序便于移植。