思岚激光雷达

文章目录


数据格式为:角度(°):距离(mm)。

STM32C8t6驱动激光雷达

前言

前面我们了解了激光雷达的原理,下面用C8T6驱动激光雷达

一、接线说明

激光雷达一共有 6 个引脚,其中 2 个 GND,2 个 5V,一对 RX 和 TX 引脚, 按照下表 1-1 的接线要求接在 STM32 单片机上。其中 2 个 5V 因为电流要求, 可以接在 TTL 转串口的 5V 引脚或者 ST Link 的 5V 引脚上。激光雷达的立贴座 端子不能直接与 STM32 连接,需将引脚用排线接出。

二、效果实现

1.串口通信实现

想要实现激光雷达数据的接收和发送,就需要将雷达接在串口上,因为串口 1 需要用来与电脑通信,所以这里选用串口 2,通过查找芯片手册可以找到串口 2 的 TX 引脚为 A2,RX 引脚为 A3。
注意:这里的串口 2 并不需要使用接收中断,因为雷达数据传输速度非常快, 如果使用中断的话很容易卡死在中断里。

在串口 1 的接收中断里,我们把接收到的数据通过串口 2 发送出去。

void USART1_IRQHandler(void) //串口 1 中断服务程序
 { 
 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是 0x0d 0x0a 结尾) 
 { 
 Res =USART_ReceiveData(USART1); //读取接收到的数据 
 USART_SendData(USART2,Res); //发送到串口 2 
 while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET); //等待发送完成 
 } 
 }

2.激光雷达数据处理

因为不用在串口 2 接收中断里接收数据,所以我们只需要判断 USART_SR 状态寄存器的 RXNE(读数据寄存器非空)位就可以了。接收到数据后,我们先 判断有效性,判断激光雷达发送数据第一位的质量是否满足要求(直接过滤掉质 量低的点),即判断质量是否为 0x3E,如果满足要求再将之后的 4 位数据接收进行处理。

if(USART_GetFlagStatus(USART2,USART_FLAG_RXNE))  // 串口寄存器接收到数据
					{
						Res =USART_ReceiveData(USART2);	//读取接收到的数据
						if(flag)
						{
							i++;
							if(i>4)
							{
								flag=0;
								i=0;
							}
							if(i==2)printf("%d:",Res<<1);  //打印角度数据(°)
							if(i==3)distan=Res>>2;
							if(i==4)
							{
								result=Res;
								result=result<<6|distan;  //整合距离数据
								printf("%d\r\n",result);  // 打印距离数据(mm)
							}
							
						}

如果只是单纯想要接收数据的话可以将数据处理部分改为将接收到的数据 发送到串口 1。 处理数据的方式主要是通过移位操作来完成对数据的整合和解算,再将数据 通过 printf 的方式打印到串口 1 进行输出。因为激光雷达数据的校验位很少,通 过判断质量的方式来解算数据非常简单有效。

数据格式为:角度(°):距离(mm)。

3.PWM 控制激光雷达启停

和控制电机一样

TIM_SetCompare1(TIM2,1000); //电机开始转动,Compare1 最大值
TIM_SetCompare1(TIM2, 0); //设置 pwm,电机停止转动

三、完整代码

用正点原子的串口例程就行,主函数的代码改成下面的

#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "key.h"
#include "TIMER.h"

u8 scan[]={0xA5,0x20}; //开始扫描采样(SCAN)命令请求
u8 stop[]={0xA5,0x25}; //停止扫描命令
u8 Res,distan;
u16 result;
int main(void)
{
	u8 i,j,flag;
	u8 t=0; 
	delay_init();	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	uart1_init(115200);   //串口初始化
	uart2_init(115200); 
	KEY_Init();	 			//按键初始化
	TIM2_PWM_Init(1000,71);  //pwm初始化
	TIM_SetCompare1(TIM2, 0);//pwm设置输出低电平
	j=1;
	printf("开始\r\n");  // 打印距离数据(mm)
	while(1)
	{
		if(j)
		{	
			
				TIM_SetCompare1(TIM2,1000);  //电机开始转动,Compare1最大值
				for (i=0;i<2;i++)  //发送开始扫描指令
				{	
					USART_SendData(USART2,scan[i]);
					while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);
				}
				i=0;
				flag=0;//数据有效性标志
				while(1)
				{
					if(USART_GetFlagStatus(USART2,USART_FLAG_RXNE))  // 串口寄存器接收到数据
					{
						Res =USART_ReceiveData(USART2);	//读取接收到的数据
//						USART_SendData(USART1,Res);  //发送原始数据
//						while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
						if(flag)
						{
							i++;
							if(i>4)
							{
								flag=0;
								i=0;
							}
//							if(i==1)if(!(Res&0x01))flag=0,i=0;  //第二位C的奇偶校验
							if(i==2)printf("%d:",Res<<1);  //打印角度数据(°)
							if(i==3)distan=Res>>2;
							if(i==4)
							{
								result=Res;
								result=result<<6|distan;  //整合距离数据
								printf("%d\r\n",result);  // 打印距离数据(mm)
							}
							
						}
						if(Res==0x3E)flag=1;  //有效性数据判断
					}
					t=KEY_Scan();  //单击结束
					if(t==KEY_PRE)
					{	
						delay_ms(100);
						j=j^0x01;
						break;
					}
				}
			  }
					
	}
}