目录

一、MS1003时间测量芯片简介

二、MS1003管脚及说明

三、驱动配置及说明

四、MS1003寄存器配置图 

五、驱动代码及注释

MS1003宏定义代码及注释:

MS1003初始化代码及注释:

MS1003开始测量函数代码及注释:

MS1003读数据函数代码及注释:

六、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~


一、MS1003时间测量芯片简介

        MS1003是一款高精度时间测量芯片(TDC),具有ps级的时间分辨率(1ps时间内光飞行0.3mm),是MS1002的升级版,有更高的精度和更小的封装,配置方式也更丰富,适用于激光雷达、激光测距和脉冲间隔测量。

        MS1003主要特点:

自动测量START到STOP之间的时间间隔,无需再配置寄存器

在非校准模式下,可以测量(小于配置的预期脉冲数)内的任意数量的脉冲

双通道单精度模式测量最小时间分辨率46ps (光在1ps时间飞行0.3毫米)

单通道双精度模式测量最小时间分辨率23ps

◼ 非校准单精度测量范围 14ns(0ns)16μs

非校准双精度测量范围 16ns(0ns)16μs

校准单精度测量范围 14ns(0ns)4μs

校准双精度测量范围 16ns(0ns)2μs

10ns 最小脉冲间隔,双通道最多可接收 20 个脉冲

4 线 SPI 通信接口

二、MS1003管脚及说明

三、驱动配置及说明

        本例程使用MS1003时间测量芯片来进行激光飞行时间的测量,进而实现激光测距的功能,根据数据手册可知,根据最大测量距离的不同,有两种配置思路。

        第一种测量思路是开启ALU单元校准功能,当MS1003开启ALU校准输出后,从START信号到STOP信号之间最大的测量时间会被限制在4us(单精度测量),1us时间内激光飞行距离约为300M,4us就是1200M,考虑到激光反射是来回的路程,所以最大测量距离就被限制在了600M。

        另一种配置思路是不开启内部ALU单元校准,读出数据之后进行手动校准,这样可以将测量时间延长到16us,理想状态下,测量距离能达到2400米,本例程将展示第二种方式的驱动配置。

四、MS1003寄存器配置图 

        此图示配置MS1003为双精度测量,非校准模式,生成CAL校准值,每次测量接收10个STOP通道1的激光脉冲回波,开启中断,测量溢出时间为最大测量时间(16μs),溢出时间到后就会将状态寄存器溢出标志位置1,此时可以正常读取输出寄存器中的数据。

         MS1003的官方文档中流程图有些问题,在发送校准指令之后不需要等待中断,可以直接读取MS1003产生的校准值,在配置的时候要注意。以下是MS1003的配置流程图:

五、驱动代码及注释

        把MS1003配置为非校准模式双精度测量,开启测量结束后自动产生校准值,同时开启高速时钟和中断产生,但是关闭ALU校准值计算。在开始测量之前,向MS1003发送开始校准指令,等待1ms之后,读取MS1003中产生的CAL校准值,然后使用这个校准值来进行测量数据校准,这个校准值存储在特定的结果寄存器中,套用对应的测量时间计算公式,可以进行手动校准测量值,最大测量距离2400M,仅STOP通道1可用。这些内容在代码中都有体现。

        非校准模式测量时间计算参数说明:

        RES_X:Stop通道结果寄存器读取到的24位整数;

        RES_Tref:在初始化后,向MS1003发送校准指令,读取到的24位校准值;

        Tref:外挂时钟周期;(以ps为时间单位);

        N:配置的时钟分频系数 DIV_CLKHS;

MS1003宏定义代码及注释:

#include "main.h"
#include "MS1003.h"
#include "spi.h"

#define	bit32 uint32_t
#define	bit16 uint16_t
#define	bit8  uint8_t


//MS1003_NSS片选操作宏定义
#define MS1003_NSS_SET	GP21_NSS_GPIO_Port->BSRR = (uint32_t)GP21_NSS_Pin
#define MS1003_NSS_CLR	GP21_NSS_GPIO_Port->BRR = (uint32_t)GP21_NSS_Pin

//MS1003_RST复位操作宏定义
#define MS1003_RST_SET   HAL_GPIO_WritePin(RSTN_TDC_GPIO_Port, RSTN_TDC_Pin, GPIO_PIN_SET)
#define MS1003_RST_CLR   HAL_GPIO_WritePin(RSTN_TDC_GPIO_Port, RSTN_TDC_Pin, GPIO_PIN_RESET)

//MS1003_EN_STOP1通道操作宏定义
#define MS1003_EN_STOP1_SET   HAL_GPIO_WritePin(EN_STOP1_GPIO_Port, EN_STOP1_Pin, GPIO_PIN_SET)
#define MS1003_EN_STOP1_CLR   HAL_GPIO_WritePin(EN_STOP1_GPIO_Port, EN_STOP1_Pin, GPIO_PIN_RESET)

//MS1003_EN_STOP2通道操作宏定义
#define MS1003_EN_STOP2_SET   HAL_GPIO_WritePin(EN_STOP2_GPIO_Port, EN_STOP2_Pin, GPIO_PIN_SET)
#define MS1003_EN_STOP2_CLR   HAL_GPIO_WritePin(EN_STOP2_GPIO_Port, EN_STOP2_Pin, GPIO_PIN_RESET)

MS1003初始化代码及注释:

/*****************************************************************************
[函数名称]Init_MS1003
[函数功能]MS1003初始化函数
[参    数]
[备    注]
*****************************************************************************/
void Init_MS1003(void)
{

    uint8_t cmd = 0;    //命令缓存
	
	MS1003_RST_CLR;		//MS1003芯片硬件复位
	HAL_Delay(2);
	MS1003_RST_SET;
	HAL_Delay(2);
	
	cmd = RESET_CMD_MS1003;		//复位指令0x50
	
	MS1003_NSS_CLR;				//开启SPI通讯使能
	HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);	//发送复位指令
	MS1003_NSS_SET;		//关闭SPI通讯使能
	HAL_Delay(1);
	
	uint32_t RegBuffer = 0x0B1C0060;	//配置寄存器,详见MS1003寄存器配置
	uint8_t u8RegConfig[5] = {0};
	u8RegConfig[0] = WriteReg_CMD_MS1003;	//写寄存器指令
	u8RegConfig[1] = (uint8_t)(RegBuffer >> 24);
	u8RegConfig[2] = (uint8_t)(RegBuffer >> 16);
	u8RegConfig[3] = (uint8_t)(RegBuffer >> 8);
	u8RegConfig[4] = (uint8_t)(RegBuffer);
	MS1003_NSS_CLR;			//开启SPI通讯使能
	HAL_SPI_Transmit(&hspi1, u8RegConfig, 5, 400);//发送32位寄存器配置指令
	MS1003_NSS_SET;			//关闭SPI通讯使能
	
	//检查主机和MS1003的通信是否正确建立
	cmd = 0xBC;		    //读取配置寄存器的低8位
	MS1003_NSS_CLR;		//开启SPI通讯使能
	HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);    //发送校验指令
	HAL_SPI_Receive(&hspi1, &cmd, 1, 100);    //接收返回值
	MS1003_NSS_SET;		//关闭SPI通讯使能
	if(cmd == 0x60)	//返回值对比,如果初始化成功
	{
        //校准前进行初始化操作
		cmd = INIT_CMD_MS1003;
		MS1003_NSS_CLR;
		HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);	//发送初始化指令
		MS1003_NSS_SET;

		//手动获取校准值
		cmd = CAL_CMD_MS1003;    //获取开始校准命令
		MS1003_NSS_CLR;
		HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);	//发送开始校准指令
		MS1003_NSS_SET;
		HAL_Delay(1);
		uint32_t u32CAL = 1;	//赋一个默认值
		Read24BitsData_MS1003(u32CAL, CAL_VALUE_ADDR);	//获取CAL原始校准值

        //250000指的是Tref*N的值,Tref指的是时钟周期,如果外挂时钟为4Mhz,那么Tref就是250ns
        //N指的是控制寄存器配置的时钟分频系数,此例程配置为2
        //门延时时间 = 250000ps * 2(时钟分频系数) / u32CAL
		m_f32CAL = 500000.0 / u32CAL;	//获取校准值,门延时时间
	}
}

MS1003开始/停止测量函数代码及注释:

/*****************************************************************************
[函数名称]Start_Test_MS1003
[函数功能]开始测量函数
[参    数]
[备    注]
*****************************************************************************/
void Start_Test_MS1003(void)
{
	m_timer4.bStartMCUON();		//发射PWM信号驱动MS1003的START端口,开始测量
	MS1003_EN_STOP1_SET;		//开启STOP1通道的接收使能
	
    uint8_t cmd = INIT_CMD_MS1003;	//MS1003初始化指令
	MS1003_NSS_CLR;
	HAL_SPI_Transmit(&hspi1, &cmd, 1, 200);
	MS1003_NSS_SET;
}

/*****************************************************************************
[函数名称]Stop_Test_MS1003
[函数功能]停止测量函数
[参    数]
[备    注]
*****************************************************************************/
void MS1003::Stop_Test_MS1003(void)
{
	m_timer4.bStopMCUON();			//停止发射激光的PWM输出
	m_timer2.bStop_R_PWM();			//关闭R_PWM接收PWM输出
	MS1003_EN_STOP1_CLR;			//关闭STOP通道接收使能
}

MS1003读数据函数代码及注释:

        ps:MS1003读取状态寄存器中的STOP回波数时,会比实际回波个数多一个,所以需要在读取回波个数的基础上-1。

/*****************************************************************************
[函数名称]Run_MS1003
[函数功能]轮询是否有数值更新,调用中断处理函数
[参    数]
[备    注]在这里检查是否有MS1003中断触发,如果有,就回调处理函数
*****************************************************************************/
void Run_MS1003(void)
{
	if(m_DataIsReady == true)	//数据就绪,开始处理数据
	{
		m_DataIsReady = false;	//清空中断数据就绪标志位
		Irq_Server_MS1003();	//调用处理函数
	}
	//如果测量结束,开始数据处理算法
	
}

/*****************************************************************************
[函数名称]Irq_Server_MS1003
[函数功能]数据处理函数
[参    数]
[备    注]在这个处理函数中读取传感器数据
*****************************************************************************/
void Irq_Server_MS1003(void)
{
	uint8_t 	cmd = 0;
	int8_t 		i8Stop1Nums = 0;	//STOP通道1回波个数
	float 		f32Dist = 0; 		//测量距离值
	uint32_t 	u32TimeValue = 0;	//MS1003原始传感器数据
	uint32_t 	u32StatusREG = 0;	//状态寄存器值
	
	MS1003_EN_STOP1_CLR;		//STOP1通道关闭使能
	
	Read24BitsData_MS1003(u32StatusREG, STATE_REG);	//读取状态寄存器的值
	
	//寄存器读取到的回波个数比实际个数多1,所以要 -1 
	i8Stop1Nums = ((uint8_t)(u32StatusREG>>5) & 0x0F) - 1; //获取STOP1回波数
	
	//如果STOP通道1的脉冲个数不为0,说明接收到有效数据
	if( i8Stop1Nums > 0 )
	{
		uint8_t reg = 0;
		for(uint8_t i=0; i<i8Stop1Nums; i++)	//读取有效数据
		{
			reg = STOP1_REG+i;
			Read24BitsData_MS1003(u32TimeValue, reg);//获取u32TimeValue时间数据
			
			//将时间转换为距离,66667是光飞行1m对应的ps数
			m_f32Dist = u32TimeValue * m_f32CAL / 66667;
			//然后对校准后的数据存入设置的数据缓存中
			if(m_f32Dist > 0 && m_f32Dist < 2400)	//如果数据在有效范围内
			{
				//调用数据更新API进行更新
				m_pListener->bOnDistUpdate(m_f32Dist, true);
			}
		}
	}
	else	//如果没有接收到回波,说明当前配置有问题,需要切换模式
	{
		m_pListener->bOnDistUpdate(0, false);	//返回异常信息
	}
	cmd = INIT_CMD_MS1003;	
	MS1003_NSS_CLR;			
	HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);	//初始化MS1003
	MS1003_NSS_SET;

	MS1003_EN_STOP1_SET;	//开启MS1003的STOP1通道
}


/*****************************************************************************
[函数名称]Read24BitsData_MS1003
[函数功能]读寄存器24位
[参    数]
[备    注]
*****************************************************************************/
void Read24BitsData_MS1003(uint32_t &value, uint8_t reg)
{
	uint8_t u8RecBuf[3] = {0};
	MS1003_NSS_CLR;
	HAL_SPI_Transmit(&hspi1, &reg, 1, 200);		//发送读24bits数据指令
	HAL_SPI_Receive(&hspi1, u8RecBuf, 3, 400);	//接收24bits三字节数据
	MS1003_NSS_SET;
	value = (uint32_t)(u8RecBuf[0]<<16) | (uint32_t)(u8RecBuf[1]<<8) | (uint32_t)u8RecBuf[2];
}

/*****************************************************************************
[函数名称]HAL_GPIO_EXTI_Falling_Callback
[函数功能]中断服务程序
[参    数]无
[备    注]HAL_GPIO_EXTI_Falling_Callback中断回调函数包含在C库中
*****************************************************************************/
extern "C" 
{
	void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
	{
		switch(GPIO_Pin)		
		{
			case GPIO_PIN_2:
			{
				m_DataIsReady = TRUE;	//更新数据就绪标志位
			}	break;
			default:
				break;
		}
	}
}

六、如果这篇文章能帮助到你,请点个赞鼓励一下吧ξ( ✿>◡❛)~

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐