激光测距传感器学习(STM32和MSP432P401R)
目录
模块相关介绍:
原理介绍:
功能描述:
技术参数:
实物图 :
代码介绍:
STM32版:
串口初始化:
读取数据
讲解
设置功能参数
MSP432P401R版
串口初始化:
读取数据:
模块相关介绍:
原理介绍:
基于光的时间飞行(Time of Flight)原理。它利用激光器发射一束非常短暂、高能量的激光脉冲,并通过接收器接收反射回来的光脉冲。通过测量激光脉冲从发射到接收的时间差,可以计算出被测物体与测距仪之间的距离。
具体的工作原理如下:
-
发射激光脉冲:激光测距仪中的激光器发射一束非常短暂、高能量的激光脉冲。
-
光脉冲传播:激光脉冲沿直线路径传播,朝向被测物体。
-
光脉冲反射:当激光脉冲遇到被测物体时,部分光能会被物体表面反射回来。这是因为激光脉冲遇到物体时会发生反射、散射或吸收。
-
光脉冲接收:激光测距仪中的接收器接收到反射回来的光脉冲。
-
时间测量:接收器测量从激光脉冲发射到接收的时间差,也就是激光脉冲的飞行时间。
-
距离计算:根据光在真空中的传播速度和测得的时间差,可以使用简单的公式(距离 = 速度 x 时间)计算出被测物体与激光测距仪之间的距离。
本次我所使用的是未来世界机器人的激光测距模块,你可以看成一个升级版的超声波
功能描述: 
技术参数:
实物图 :


本次讲解:通过串口发送,该模块有好几种测距输出方式,本次只介绍最基本的输出方式:主动输出
主动输出数据意义对照表:
代码介绍:
STM32版:
串口初始化:
void Usart3_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);//USART3_TX PB.10GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//USART3_RX PB.11GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入GPIO_Init(GPIOB, &GPIO_InitStructure);//对串口3通信协议进行初始化设置USART_InitStructure.USART_BaudRate = 115200; //设置波特率USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式USART_InitStructure.USART_StopBits = USART_StopBits_1; //1位停止位USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶效验USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //双向通信USART_Init(USART3, &USART_InitStructure);USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //开启接收中断 USART_Cmd(USART3, ENABLE);//对串口3收发中断设置NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断组选第二组NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //先占优先级2级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //从优先级3级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能NVIC_Init(&NVIC_InitStructure);
}
读取数据
u8 USART_RX_STA[8] = { 0 }; //接收状态标记
u8 Num = 0; //接收数据的当前位置/********************************************************************** 函数名称:Read_LaserDis* 函数功能:读取数据* 形 参:ID: 模块编号,*Data: 读取到的数据* 输 出:无* 备 注:无********************************************************************/
void Read_LaserDis(unsigned char ID, unsigned int *Data)
{ unsigned char y=0;unsigned int Receive_data [3] = { 0 }; //数据缓存区Num = 0;
///读取距离、环境质量、环境光强数值///while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, 0x57); //命令起始信号while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, ID); //ID模块编号while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);Delay_ms(2);while(1){if(USART_RX_STA[0] != 0x75) { Num = 0; } //判断帧头0x75,否者重新接收if(Num == 8){Num = 0;if(USART_RX_STA[7] == 0x07) //判断帧尾0x07,否者不赋值{Receive_data[0] = USART_RX_STA[1];Receive_data[0] <<= 8;Receive_data[0] |= USART_RX_STA[2]; *Data = Receive_data[0]; //距离Receive_data[1] = USART_RX_STA[3];Receive_data[1] <<= 8;Receive_data[1] |= USART_RX_STA[4];*(Data+1) = Receive_data[1]; //环境质量Receive_data[2] = USART_RX_STA[5];Receive_data[2] <<= 8;Receive_data[2] |= USART_RX_STA[6];*(Data+2) = Receive_data[2]; //环境光强 break;} break;}else{Delay_ms(1);y++;if(y==10) { Num = 0;break; }}}
///读取距离、环境质量、环境光强数值///
}
讲解
内部实现逻辑如下:
-
定义了一个缓存区
Receive_data[3],用来存储读取到的数据。 -
Num = 0;将变量 Num 初始化为 0,用于计数接收到的数据字节数。 -
发送命令起始信号
0x57到激光测距模块,表示开始读取数据。 -
发送激光测距模块的 ID 号码。
-
延时 2 毫秒。
-
进入一个循环,判断接收到的数据是否满足要求。
-
判断帧头是否为
0x75,如果不是,则重新接收。 -
如果接收到的数据字节数为 8,则表示接收完成。
-
判断帧尾是否为
0x07,如果是,则将接收到的数据赋值给相应的变量。 -
跳出循环。
-
返回读取到的距离、环境质量和环境光强的值。
设置功能参数
/********************************************************************** 函数名称:Set_LaserDis* 函数功能:设置功能参数* 形 参:ID: 模块编号,Fun: 功能项,Par: 参数,* 输 出:无* 备 注:无********************************************************************/
void Set_LaserDis(unsigned char ID, unsigned char Fun,unsigned char Par)
{ ///设置功能参数/// while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, 0x4C); //命令起始信号while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, ID); //ID模块编号while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, Fun); //功能项while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET); while(USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);USART_SendData(USART3, Par); //参数while(USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);///设置功能参数///
}
MSP432P401R版
不懂432串口的请参考:MSP432P401R第三讲:串口通信_三马分享家的博客-CSDN博客
串口初始化:
void uart_A1_init(uint32_t baudRate)
{
#ifdef EUSCI_A_UART_7_BIT_LEN//固件库v3_40_01_02//默认SMCLK 48MHz 比特率 115200const eUSCI_UART_ConfigV1 uartConfig ={EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source26, // BRDIV = 260, // UCxBRF = 0111, // UCxBRS = 111EUSCI_A_UART_NO_PARITY, // No ParityEUSCI_A_UART_LSB_FIRST, // MSB FirstEUSCI_A_UART_ONE_STOP_BIT, // One stop bitEUSCI_A_UART_MODE, // UART modeEUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // OversamplingEUSCI_A_UART_8_BIT_LEN // 8 bit data length};eusci_calcBaudDividers((eUSCI_UART_ConfigV1 *)&uartConfig, baudRate); //配置波特率
#else//固件库v3_21_00_05//默认SMCLK 48MHz 比特率 115200const eUSCI_UART_Config uartConfig ={EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source26, // BRDIV = 260, // UCxBRF = 0111, // UCxBRS = 111EUSCI_A_UART_NO_PARITY, // No ParityEUSCI_A_UART_LSB_FIRST, // MSB FirstEUSCI_A_UART_ONE_STOP_BIT, // One stop bitEUSCI_A_UART_MODE, // UART modeEUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling};eusci_calcBaudDividers((eUSCI_UART_Config *)&uartConfig, baudRate); //配置波特率
#endifMAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);//GPIO复用MAP_UART_initModule(EUSCI_A1_BASE, &uartConfig);//初始化串口函数MAP_UART_enableModule(EUSCI_A1_BASE);//使能串口模块UART_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);//开启串口相关中断Interrupt_enableInterrupt(INT_EUSCIA1);//开启串口端口中断
}
读取数据:
uint8_t USART_A1_RX_STA[8] = { 0 }; //接收状态标记
uint8_t Num = 0; //接收数据的当前位置/********************************************************************** 函数名称:Read_LaserDis* 函数功能:读取数据* 形 参:ID: 模块编号,*Data: 读取到的数据* 输 出:无* 备 注:无********************************************************************/
void Read_LaserDis(unsigned char ID, unsigned int *Data)
{ unsigned char y=0;unsigned int Receive_data [3] = { 0 }; //数据缓存区Num = 0;
///读取距离、环境质量、环境光强数值/////while (EUSCI_A1->IFG & EUSCI_A_IFG_TXIFG);UART_transmitData(EUSCI_A1_BASE,0x57); //命令起始信号//while (EUSCI_A1->IFG & EUSCI_A_IFG_TXIFG); //while (EUSCI_A1->IFG & EUSCI_A_IFG_TXIFG);UART_transmitData(EUSCI_A1_BASE,ID);//ID模块编号//while (EUSCI_A1->IFG & EUSCI_A_IFG_TXIFG);delay_ms(2);while(1){if(USART_A1_RX_STA[0] != 0x75) { Num = 0; } //判断帧头0x75,否者重新接收if(Num == 8){Num = 0;if(USART_A1_RX_STA[7] == 0x07) //判断帧尾0x07,否者不赋值{Receive_data[0] = USART_A1_RX_STA[1];Receive_data[0] <<= 8;Receive_data[0] |= USART_A1_RX_STA[2]; *Data = Receive_data[0]; //距离Receive_data[1] = USART_A1_RX_STA[3];Receive_data[1] <<= 8;Receive_data[1] |= USART_A1_RX_STA[4];*(Data+1) = Receive_data[1]; //环境质量Receive_data[2] = USART_A1_RX_STA[5];Receive_data[2] <<= 8;Receive_data[2] |= USART_A1_RX_STA[6];*(Data+2) = Receive_data[2]; //环境光强 break;} break;}else{delay_ms(1);y++;if(y==10) { Num = 0;break; }}}
///读取距离、环境质量、环境光强数值///
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
