【TI毫米波雷达笔记】MMwave毫米波雷达API配置及驱动(以IWR6843AOP为例)
MMWave API(位置处于BSS)可以被DSS和MSS调用
通过Mailbox进行数据通信
毫米波雷达接口
#include < ti/control/mmwave/mmwave.h>
#include
首先搞清楚 mmwave时雷达射频整体 每秒发送很多frame(帧)
frame下面有chirp 比如96个chirp
所以当发送开始时 会连续发送96个chirps 然后接收数据 再处理
如图为chirp的时序图
雷达工作原理是上电-发送chirps-帧结束-处理-上电循环
一个Frame,首先是信号发送,比如96个chirp就顺次发出去,然后接收回来,混频滤波,ADC采样,这些都是射频模块的东西。射频完成之后,FFT,CFAR,DOA这些就是信号处理的东西。然后输出给那个结构体,就是当前帧获得的点云了。
在射频发送阶段 一个frame发送若干个chirp 也就是上图左上角
第一个绿色点为frame start 第二个绿色点为frame end
其中发送若干chirps(小三角形)
chirps的个数称为numLoops(代码中 rlFrameCfg_t
结构体)
在mmwave studio上位机中 则称为 no of chirp loops
frame end 到 周期结束的时间为计算时间 称为inter frame period
frame start到循环结束的时间称为framePeriodicity(代码中 rlFrameCfg_t
结构体)
在mmwave studio上位机中 则称为 Periodicity
如下图frame配置部分
在inter frame Periodicity时间内(比如这里整个周期是55ms)
就是用于计算和处理的时间 一定比55ms要小
如果chirps很多的话 那么计算时间就会减小
如果是处理点云数据 则只需要每一帧计算一次点云即可
计算出当前帧的xyz坐标和速度 以及保存时间戳
/* Wait for BSS powerup */
if (SOC_waitBSSPowerUp(socHandle, &errCode) < 0)
{
/* Debug Message: */
System_printf ("Debug: SOC_waitBSSPowerUp failed with Error [%d]\n", errCode);
return 0;
}
Mailbox_init(MAILBOX_TYPE_MSS);
除了初始化SOC外 还需要调用SOC_waitBSSPowerUp
和Mailbox_init
MMWave_init
配置结构体 MMWave_InitCfg
domain指定运行位置
MMWave_InitCfg initCfg;
initCfg.domain = MMWave_Domain_MSS;
initCfg.socHandle = MMWave_Global_Params.handle.socHandle;
initCfg.eventFxn = MMWave_eventFxnCallback; //事件回调
initCfg.linkCRCCfg.useCRCDriver = 0U; //1开启CRC 0关闭CRC
initCfg.linkCRCCfg.crcChannel = CRC_Channel_CH1; //CRC通道1
initCfg.cfgMode = MMWave_ConfigurationMode_FULL; //全部模式 也可以设置成最小全部模式
initCfg.executionMode = MMWave_ExecutionMode_ISOLATION; //MSS和DSS不通讯 如果需要 则换个模式
//以下全是回调
initCfg.cooperativeModeCfg.cfgFxn = MMWave_cfgFxnCallback;
initCfg.cooperativeModeCfg.closeFxn = MMWave_closeFxnCallback;
initCfg.cooperativeModeCfg.openFxn = MMWave_openFxnCallback;
initCfg.cooperativeModeCfg.startFxn = MMWave_startFxnCallback;
initCfg.cooperativeModeCfg.stopFxn = MMWave_stopFxnCallback;
/* Initialize and setup the MMWave Control module */
MMWave_Global_Params.handle.MMWave_handle = MMWave_init (&initCfg, &errCode);
if (MMWave_Global_Params.handle.MMWave_handle == NULL)
{
/* Error: Unable to initialize the MMWave control module */
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: MMWave Control Initialization failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
return;
}
在MSS+DSS协作模式下工作时,毫米波同时在MSS和DSS上执行。每个域都注册一个回调函数,如果对等域执行等效操作,则由毫米波模块调用该函数。
这样在配置时 会自动进行传参 使两个部分同步
MMWave_sync
/* Synchronization: This will synchronize the execution of the control module
* between the domains. This is a prerequiste and always needs to be invoked. */
//同步
if (MMWave_sync (MMWave_Global_Params.handle.MMWave_handle, &errCode) < 0)
{
/* Error: Unable to synchronize the MMWave control module */
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: MMWave Control Synchronization failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
return;
}
直接调用MMWave_sync
MMWave_execute
在执行上面两步以后需要调用MMWave_execute
这个函数需要在上下文一直调用 所以建立一个死循环线程
这里priority 越大 优先级越高 越先响应
/*****************************************************************************
* Launch the MMWave control execution task
* - This should have a higher priroity than any other task which uses the
* MMWave control API
*****************************************************************************/
//这里是开了一个线程循环调用
Task_Params_init(&taskParams);
taskParams.priority = 5;
taskParams.stackSize = 3*1024;
MMWave_Global_Params.task.MMWaveCtrl = Task_create(Ctrl_MMWave, &taskParams, NULL);
void Ctrl_MMWave(UArg arg0, UArg arg1)
{
int32_t errCode;
MMWave_ErrorLevel errorLevel;
int16_t mmWaveErrorCode;
int16_t subsysErrorCode;
while (1)
{
/* Execute the MMWave control module: */
if (MMWave_execute (MMWave_Global_Params.handle.MMWave_handle, &errCode) < 0)
{
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: MMWave control execution failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
}
}
}
MMWave_open
MMWave_OpenCfg openCfg;
openCfg.freqLimitLow = 600U; //低频限制
openCfg.freqLimitHigh = 640U; //高频限制
openCfg.chCfg.rxChannelEn = 0x000F; //开启四个RX
openCfg.chCfg.txChannelEn = 0x0007; //开启四个TX
openCfg.chCfg.cascading = 0x0000; //不开启级联
openCfg.chCfg.cascadingPinoutCfg = 0; //直接给0
openCfg.lowPowerMode.lpAdcMode = 0x0000; //Regular ADC mode
openCfg.adcOutCfg.fmt.b2AdcBits = 2; //16bit
openCfg.adcOutCfg.fmt.b8FullScaleReducFctr = 0; //16bit只能为0
openCfg.adcOutCfg.fmt.b2AdcOutFmt = 2; //Complex with Image band
openCfg.defaultAsyncEventHandler = MMWave_DefaultAsyncEventHandler_MSS;
openCfg.disableFrameStartAsyncEvent = false;
openCfg.disableFrameStopAsyncEvent = false;
openCfg.useCustomCalibration = false; // 无自定义校准 false表示默认启用所有校准
openCfg.customCalibrationEnableMask = 0x0;
openCfg.calibMonTimeUnit = 1; //一帧一次校准
/*
MMWave_CalibrationData calibrationData;
memset ((void*)&calibrationCfg, 0 , sizeof(MMWave_CalibrationCfg));
calibrationData.ptrCalibData->calibChunk
calibrationData.ptrPhaseShiftCalibData->PhShiftcalibChunk
*/
/* Open the mmWave module: */
if (MMWave_open (MMWave_Global_Params.handle.MMWave_handle, &openCfg, NULL, &errCode) < 0)
{
/* Error: decode and Report the error */
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: mmWave Open failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
}
这里是配置频段 RX、TX使能个数、采样位数等
对应mmwave studio:
MMWave_config
这里是配置frame
MMWave_CtrlCfg ctrlCfg;
ctrlCfg.dfeDataOutputMode = MMWave_DFEDataOutputMode_FRAME;
ctrlCfg.u.frameCfg.profileHandle[0]=MMWave_Global_Params.handle.profileHandle[0];
ctrlCfg.u.frameCfg.profileHandle[1]=NULL;
ctrlCfg.u.frameCfg.profileHandle[2]=NULL;
ctrlCfg.u.frameCfg.profileHandle[3]=NULL;
ctrlCfg.u.frameCfg.frameCfg.chirpStartIdx = 0;
ctrlCfg.u.frameCfg.frameCfg.chirpEndIdx = 2;
ctrlCfg.u.frameCfg.frameCfg.numLoops = 96;
ctrlCfg.u.frameCfg.frameCfg.numFrames = 0;
ctrlCfg.u.frameCfg.frameCfg.numAdcSamples = 96;
ctrlCfg.u.frameCfg.frameCfg.framePeriodicity = 11000000; //55ms
ctrlCfg.u.frameCfg.frameCfg.triggerSelect = 0x0001; //软件API触发
ctrlCfg.u.frameCfg.frameCfg.numDummyChirpsAtEnd = 0;
ctrlCfg.u.frameCfg.frameCfg.frameTriggerDelay = 0;
/*
//frame模式不用配
ctrlCfg.u.continuousModeCfg.cfg.startFreqConst
ctrlCfg.u.continuousModeCfg.cfg.txOutPowerBackoffCode
ctrlCfg.u.continuousModeCfg.cfg.txPhaseShifter
ctrlCfg.u.continuousModeCfg.cfg.digOutSampleRate
ctrlCfg.u.continuousModeCfg.cfg.hpfCornerFreq1
ctrlCfg.u.continuousModeCfg.cfg.hpfCornerFreq2
ctrlCfg.u.continuousModeCfg.cfg.rxGain
ctrlCfg.u.continuousModeCfg.cfg.vcoSelect
ctrlCfg.u.continuousModeCfg.dataTransSize
*/
//ctrlCfg.u.advancedFrameCfg.profileHandle = //NULL; //frame模式不用配
/* Configure the mmWave module: */
if (MMWave_config (MMWave_Global_Params.handle.MMWave_handle, &ctrlCfg, &errCode) < 0)
{
/* Error: Report the error */
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: mmWave Config failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
}
如果需要配置profile和chirp 则需要调用MMWave_addProfile
和MMWave_addChirp
注意 chirp是在profile之下的 而profile是在mmwave之下的(就像mmwave的句柄在soc之下)
所以配置frame时:
ctrlCfg.u.frameCfg.profileHandle[0]=MMWave_Global_Params.handle.profileHandle[0];
这里的profile句柄就是MMWave_addProfile
返回的 而chirp的句柄在MMWave_addChirp
的返回中
并且MMWave_addChirp
的第一个参数就是MMWave_addProfile
的返回值(profile的句柄)
MMWave_addProfile
的第一个参数则为MMWave_init
的返回值(mmwave的句柄)
那么配置的先后关系就可以列出来了(其实不用在意 只要配了就行 另外 句柄要用全局变量 但是按顺序配置可以方便从上往下读代码)
rlProfileCfg_t profileCfg;
rlChirpCfg_t chirpCfg;
memset ((void*)&profileCfg, 0 , sizeof(rlProfileCfg_t));
memset ((void*)&chirpCfg, 0 , sizeof(rlChirpCfg_t));
profileCfg.profileId = 0;
profileCfg.pfVcoSelect = 0x02; //内置 VCO2 选择60-64GHz
profileCfg.pfCalLutUpdate = 0x00; //校准
profileCfg.startFreqConst = 0x58E3A1CD; //60GHz
profileCfg.idleTimeConst = 0x2710; //100us
profileCfg.adcStartTimeConst = 0x258; //6us
profileCfg.rampEndTime = 0x1770; //60us
profileCfg.txOutPowerBackoffCode = 0; //全为0
profileCfg.txPhaseShifter = 0; //全为0
profileCfg.freqSlopeConst = 0x05E7; //54.713 MHz/us
profileCfg.txStartTime = 0; //0us
profileCfg.numAdcSamples = 96; //96
profileCfg.digOutSampleRate = 0x0B86; //2950ksps
profileCfg.hpfCornerFreq1 = 0; //175K
profileCfg.hpfCornerFreq2 = 0; //350K
profileCfg.txCalibEnCfg = 0xFFFF; //不适用于IWR6843 ES 1.0
profileCfg.rxGain = 0x68; //40dB/34dB
MMWave_Global_Params.handle.profileHandle[0] = MMWave_addProfile(MMWave_Global_Params.handle.MMWave_handle,&profileCfg,&errCode);
if(MMWave_Global_Params.handle.profileHandle[0] == NULL)
{
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: mmWave profileCfg failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
}
chirpCfg.chirpStartIdx=0;
chirpCfg.chirpEndIdx=0;
chirpCfg.profileId=0;
chirpCfg.startFreqVar=0;
chirpCfg.freqSlopeVar=0;
chirpCfg.idleTimeVar=0;
chirpCfg.adcStartTimeVar=0;
chirpCfg.txEnable=(1<<0);
//TDM模式 用for循环配置三次 每次的chirpStartIdx chirpEndIdx均不同 分别为00 11 22 另外 打开的TX也不同 分别为TX0 TX1 TX2
//这三个chirp配置都属于同一个profileHandle下
for(i=0;i<3;i++)
{
chirpCfg.chirpStartIdx=i;
chirpCfg.chirpEndIdx=i;
chirpCfg.txEnable=(1<<i);
MMWave_Global_Params.handle.chirpHandle[i] = MMWave_addChirp(MMWave_Global_Params.handle.profileHandle[0],&chirpCfg,&errCode);
if(MMWave_Global_Params.handle.chirpHandle[i] == NULL)
{
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: mmWave chirpCfg %d failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
}
}
//然后下面再是MMWave_config 函数和配置
然后下面再是MMWave_config
函数和配置
MMWave_start
这里就是开启测量了 同时定义了校准和运行模式
MMWave_CalibrationCfg calibrationCfg;
memset ((void *)&calibrationCfg, 0, sizeof(MMWave_CalibrationCfg));
calibrationCfg.dfeDataOutputMode = MMWave_DFEDataOutputMode_FRAME;
calibrationCfg.u.chirpCalibrationCfg.enableCalibration = true;
calibrationCfg.u.chirpCalibrationCfg.enablePeriodicity = true;
calibrationCfg.u.chirpCalibrationCfg.periodicTimeInFrames = 10; //每10帧一次校准
//calibrationCfg.u.contCalibrationCfg.enableOneShotCalibration //frame模式不用配
/* Start the mmWave module: The configuration has been applied successfully. */
if (MMWave_start(MMWave_Global_Params.handle.MMWave_handle, &calibrationCfg, &errCode) < 0)
{
/* Error/Warning: Unable to start the mmWave module */
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: mmWave Start failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
/* datapath has already been moved to start state; so either we initiate a cleanup of start sequence or
assert here and re-start from the beginning. For now, choosing the latter path */
}
毫米波雷达错误代码可以用MMWave_decodeError
函数来获取
传入的第一个参数为errCode 而后面三个其实都是返回值
比如:
int32_t errCode;
MMWave_ErrorLevel errorLevel;
int16_t mmWaveErrorCode;
int16_t subsysErrorCode;
if (MMWave_start(MMWave_Global_Params.handle.MMWave_handle, &calibrationCfg, &errCode) < 0)
{
/* Error/Warning: Unable to start the mmWave module */
MMWave_decodeError (errCode, &errorLevel, &mmWaveErrorCode, &subsysErrorCode);
System_printf ("Error: mmWave Start failed [Error Level: %d Error code: %d Subsystem: %d]\n",errorLevel,mmWaveErrorCode, subsysErrorCode);
/* datapath has already been moved to start state; so either we initiate a cleanup of start sequence or
assert here and re-start from the beginning. For now, choosing the latter path */
}
最后皆可以通过mmWaveErrorCode
来获取调用函数的问题
其他模块的错误代码基本地址不一样 但是也大同小异 查其他模块的手册就可以了