基于STM32激光雷达的使用

本文介绍了YDLIDARSDM15单点激光雷达的工作原理、接线方式、模式设置及系统通信机制。在编程实验部分,详细阐述了如何在STM32F407ZGT6上使用HAL库进行串口通信,包括对USART配置、中断处理和数据传输的修改,以适应激光雷达的通信需求。实验结果显示了成功接收和解码激光雷达数据的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、激光雷达简介

笔者使用的激光雷达为亚博智能YDLIDAR SDM15。
YDLIDAR SDM15 激光雷达是一款高性能单点激光雷达(以下简称:SDM15)。本产品基于飞行时间测距原理,并配以相关光学、电学、算法设计,实现高精度激光距离测量,并输出高帧率的点云据。可用于无人机定高、机器人避障、导航等。测量距离为 50mm-15m。

二、接线部分

在这里插入图片描述
从左到右依次为:
黄线:RX : 通信串口的输入口
黑线:GND: 供电接口(负极) 0v
绿线:TX : 通信串口的输出口
红线:VCC: 供电接口(正极) 5V * (低于5v测量的数据不准确,高于5V可能会烧坏激光雷达) *

三、模式

YDLIDAR SDM15 单点激光雷达(以下简称 SDM15)的系统设置了 3 种工作模式:空闲模
式、测距模式、停机模式。
➢ 空闲模式:SDM15 上电时,默认为空闲模式;空闲模式时,SDM15 的测距单元不工作,激
光器不亮。
➢ 测距模式:当 SDM15 进入测距模式时,点亮激光器,实时输出测距数据。
➢ 停机模式:当 SDM15 运行有错时,如测距异常,自检不过等状况,SDM15 会自动关闭测距
单元,并反馈错误代码。

四、系统通信

(一)通信机制

SDM15 是通过串口来和外部设备进行命令和数据的交互。当外部设备发送一个系统命令
至 SDM15,SDM15 解析系统命令,会返回相应的应答报文,并根据命令内容,来切换相应的工
作状态,外部系统根据报文内容,解析报文,便可获取应答数据。

(二)系统命令

外部系统通过发送相关的系统命令,便可设置 SDM15 相应的工作状态,获取相应的数据。SDM15 对外发布的系统命令如下:

命令描述模式切换应答模式
0x60开启测距测距模式持续应答
0x61停止测距停机模式单次应答
0x62获取版本信息不切换单次应答
0x63雷达自检不切换单次应答
0x64设置输出频率不切换单次应答
0x65设置滤波不切换单次应答
0x66设置串口波特率不切换单次应答
0x67设置输出数据格式不切换单次应答
0x68恢复出厂设置不切换单次应答

(三)系统报文

系统报文是系统根据接收的系统命令反馈的应答报文,不同的系统命令,系统报文的应答模式和应答内容也不一样,其中应答模式有三种:无应答、单次应答和持续应答。无应答表示系统不反馈任何报文;单次应答表示系统的报文长度是有限的,应答一次即结束;持续应答表示系统的报文长度是无限长的,需要持续发送数据,如进入测距模式时。单次应答和持续应答的报文采用同一个数据协议,其协议内容为:包头、包类型、数据长度、数据段和校验码,通过串口 16 进制输出。
YDLIDAR SDM15 系统报文数据协议

包头包类型数据长度数据段校验码
2 Bytes1 Byte1 ByteN Bytes1 Byte

➢ 包头:SDM15 的报文包头标志为 0x55AA;
➢ 包类型:系统命令的类型
➢ 数据长度:表示的是应答数据的长度;
➢ 数据段:不同系统命令下的应答内容,反馈不同的数据内容,其数据格式也不同;
➢ 校验码:校验码(CheckSum),除去校验码以外的其他所有数据的和校验。

SDM15 的数据通信采用的是小端模式,低位在前。

五、编程实验

cube

USART1(与上位机进行通信)
在这里插入图片描述
USART2(与激光雷达进行通信)
在这里插入图片描述
这里波特率设置为460800是因为默认波特率就是460800我没有管他
时钟树
在这里插入图片描述

记得开启外部高速晶振和USART2的全局中断

keil

由于官方给的demo是STM32F103C8T6而且是用标准库写的代码。而我用的是STM32F407ZGT6而且是用HAL库写的,所以没办法直接cv。不过我会保留一部分官方的源码[doge]。
SMD15.c
首先把官方给的SMD15.c和SMD15.h文件整个弄过去,需要修改的部分如下:

delay_ms(200);->HAL_Delay(200);

USART2
官方的USART2的单独封装成.c.h文件,我的usart1和usart2是和到一起的
在usart2初始化函数里要手动开启中断

  HAL_UART_Receive_IT(&huart2, (uint8_t*)&RX_buffer, 1);  //手动开启中断

void USART2_Send_U8(uint8_t Data)
{
	while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)
		;
	USART_SendData(USART2, Data);
}

修改为下面的代码

void USART2_Send_U8(uint8_t Data)
{
	HAL_UART_Transmit(&huart2, (uint8_t *)&Data, 1, 1000);	
//	HAL_UART_Transmit(&huart1, (uint8_t *)&Data, 1, 1000);	
	if(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TC) )
	{
		//printf("I have Transmit Data\r\n");
	}
}

HAL库查看usart串口状态的函数是__HAL_UART_GET_FLAG()
串口中断回调函数

void USART2_IRQHandler(void)
{
	if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
	{
		uint8_t Rx2_Temp = USART_ReceiveData(USART2);
		SDM15_Decode(Rx2_Temp);
//		USART2_Send_U8(Rx2_Temp);
	}
}

修改为下面的代码

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance == USART2)
    {
		//printf("%d\r\n",RX_buffer);		
		SDM15_Decode(RX_buffer);
    }		
    HAL_UART_Receive_IT(&huart2, (uint8_t*)&RX_buffer, 1);
}

六、实验结果

在这里插入图片描述

补充

(一)memset

memset 是一个C语言标准库函数,其功能是将一块内存中的每个字节都设置为一个特定的值。该函数通常被用于初始化数据结构中的内存块,例如字符数组、整型数组、结构体等等。
memset 函数的原型如下:
void *memset(void *ptr, int value, size_t num);

  • ptr 是指向要设置的内存块的指针,该内存块的大小至少为 num。
  • value 是要将内存块的每个字节设置为的值,它的取值范围是 0 到 255,通常用十六进制表示,例如 0x00 表示零、0xFF 表示 255 等等。
  • num 是要设置的字节数,即要将 ptr 指向的内存块中的前 num 个字节都设置为 value。
    memset 函数的返回值是指向 ptr 的指针,即返回指向被设置内存块的指针。如果函数调用成功,则返回值与 ptr 相等。
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
int main()
{
  int array[ARRAY_SIZE];
  memset(array, 0, sizeof(int) * ARRAY_SIZE);
  printf("The array contents:\n");
  for (int i = 0; i < ARRAY_SIZE; i++) 
{
    printf("%d ", array[i]);
  }
  printf("\n");
  return 0;
}

在上面的例子中,首先定义了一个整型数组 array,其大小为 ARRAY_SIZE。然后,调用 memset 函数将 array 中的所有元素都设置为零。最后,使用一个循环打印出 array 中的所有元素。
需要注意的是,使用 memset 函数时需要确保 ptr 所指向的内存块大小至少为 num,否则可能会发生内存访问越界等错误。此外,当使用 memset 函数时,value 参数是一个整数类型,而不是字符类型。

(二)前缀 _Bool

前缀 _Bool 是 C99 标准中定义的布尔类型,其取值只能是 0 或 1,分别表示 false 和 true。在 C99 之前,C语言没有内置的布尔类型,通常使用整型变量来模拟布尔类型。但是这种方式并不够安全和直观,因为整数类型的取值范围比布尔类型要大,不易于阅读和维护代码。C99 引入了 _Bool 类型,使得布尔类型的操作更加方便和直观。

(三)strstr()

strstr()是一个C语言函数,用于在一个字符串中查找另一个字符串的第一次出现。它的函数原型为:
char* strstr(const char* str1, const char* str2);
其中,str1表示要查找的字符串,str2表示要在str1中查找的字符串。如果找到了str2在str1中的第一次出现,返回指向该位置的指针;如果没有找到,返回NULL指针。

(四)implicit declaration of function

这个问题其实是很低级的问题,但是经常还是容易发生,翻译下就是西数的隐式说明
有两种情况会产生这种情况
1没有把函数所在的c文件生成.0目 文件
2在西数所在的c文件中定义了,但是没有在与之相关联的.h文件中声明

(五)Over Sampling

在STM32F407微控制器上,USART是一种用于串行通信的外设。在使用CubeMX配置USART时,有一个名为"Over Sampling"的选项。
Over Sampling(过采样)是指在USART的接收端,将输入的数据信号进行多次采样以获得更准确的信号值。在USART中,过采样可以设置为8或16,这表示接收端将对输入信号进行8或16次采样以获得一个符号。
如果过采样设置为8,则USART将对每个输入数据位进行8次采样,以获得每个数据位的最精确的值。过采样值为16时,将对每个数据位进行16次采样。
较高的过采样值可以提供更高的采样精度,但也会增加处理器的负载。在选择过采样值时,应该考虑到所需的精度和处理器的性能。在STM32F407微控制器上,USART是一种用于串行通信的外设。在使用CubeMX配置USART时,有一个名为"Over Sampling"的选项。
Over Sampling(过采样)是指在USART的接收端,将输入的数据信号进行多次采样以获得更准确的信号值。在USART中,过采样可以设置为8或16,这表示接收端将对输入信号进行8或16次采样以获得一个符号。
如果过采样设置为8,则USART将对每个输入数据位进行8次采样,以获得每个数据位的最精确的值。过采样值为16时,将对每个数据位进行16次采样。
较高的过采样值可以提供更高的采样精度,但也会增加处理器的负载。在选择过采样值时,应该考虑到所需的精度和处理器的性能。

在这里插入图片描述

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值