GY56 红外激光测距传感器 (内附STM32、MSP432代码)


一、GY56简介

1. 概述

在这里插入图片描述

GY-56 是一款低成本数字红外测距传感器模块。 工作电压 3-5v,功耗小,体积小,安装方便。 其工作原理是,红外 LED 发光,照射到被测物体后,返回光经过 MCU 接收,MCU 计算出时间差,得到距离。直接输出距离值。此模块,有两种方式读取数据,即串口 UART(TTL 电平)+IIC(2 线)模式,串口的波特率有 9600bps 与 115200bps,可配置,有连续,询问输出两种方式,可掉电保存设置。GY-56 可以设置上下限距离报警值,开关量输出,在设定的区间内有被测物体挡住,直接输出高电平。IIC 模式下,如果需要,可以设置内部 IIC 地址不同,以便多个传感器直接接在同一个总线。

2. 特点

  • 高性价比
  • 内置 MCU 计算距离
  • IIC、串口通信协议
  • 配有相应的上位机软件

3. 参数

在这里插入图片描述

4. 引脚说明

在这里插入图片描述

5. 应用

  • 智能机器人
  • 教学实验室仪器
  • 生产线产品检测
  • 红外测距

二、通信协议

1. 串口

Tips: 模块默认为串口

(1)串口通信参数(默认波特率值 9600bps,可通过软件设定)
波特率:9600 bps 校验位:N 数据位:8 停止位:1
波特率:115200 bps 校验位:N 数据位:8 停止位:1

(2)、模块输出格式,每帧包含 8-13 个字节(十六进制):
①.Byte0: 0x5A 帧头标志
②.Byte1: 0x5A 帧头标志
③.Byte2: 0x15 本帧数据类型
④.Byte3: 0x03 数据量
⑤.Byte4: 0x00~0xFF 数据前高 8 位
⑥.Byte5: 0x00~0xFF 数据前低 8 位
⑦.Byte6: 0x00~0xFF 模块测量模式
⑧.Byte7: 0x00~0xFF 模块温度
⑨.Byte8: 0x00~0xFF 校验和(前面数据累加和,仅留低 8 位)

在这里插入图片描述

数据计算方法(距离长度计算方法):

Distance= (Byte4<<8) | Byte5 单位 cm
Mode= Byte6
Temp= Byte7(MCU 温度)

例:一帧数据
< 5A-5A-15-04-00-0A-02-1A-F3>
Distance =(0x00<<8)|0x0A =10cm
Mode=2 (高精度模式)
Temp=0x1A=26℃

(3)命令字节,由外部控制器发送至 GY-56 模块(十六进制)
串口命令指令:
命令格式:0xA5+功能指令+指令值+sum
在这里插入图片描述
例 1:设置串口连续输出数据,(如需掉电保存,请发送掉电保存指令)
连续输出指令=0xA5+0x65+0x01+0x0B

例 2:设置在 10cm-50cm 的区间范围内 OUT 引脚输出高电平
(如需掉电保存,请发送掉电保存指令)
设置上限阀值 50CM=0xA5+0x98+0x32+0x6F
设置下限阀值 10CM=0xA5+0xA9+0x0A+0x58

例 3: 掉电保存指令 = 0xA5+0x87+0x01+0x2D

2. IIC协议

当 GY-56 模块硬件 ps 焊点焊上时候使用,CT 为 SCL,DR 为 SDA
在这里插入图片描述

IIC 时钟:250K 以下,模块默认 8bit IIC 地址为 0XE0;
1bit write:0;
1bit read: 1;
在这里插入图片描述

三、模块使用方法

该模块为串口和 IIC 输出模块,模块默认为串口模式。模块接入电源后,检测距离不在上限阀值内,LED 会闪亮 1 秒,检测距离在上限阀值内,LED 指示灯会长亮,如果指示
灯一直闪烁,说明模块初始化失败,模块不能使用。

串口模式(默认):PS 端口拉高(默认,PS 焊点开放),模块上电,默认配置为波特率9600、高精度测量、连续输出模式;使用该模块配套的上位机可方便的对模块进行相应的设置;上位机使用前请先选择好端口和波特率,然后再点击“打开串口”按钮,此时,上位机将显示对应的数据。

串口输出模式分两种,一种连续输出,一种查询输出。连续输出的频率根据测量模式
的不同而不同,具体参见 Byte6 代表的含义说明;查询输出的形式为模块接收到查询指令后,模块开启一次测量,测量完毕后再返回一帧测量数据。不同的输出模式和不同测量模式,导致模块的消耗电流也不同,模块在不测量距离时,电流约为 15mA,查询输出模式在测量结束后电流约为 15mA,连续输出模式电流具体参见 Byte6 代表的含义说明。

  • 1. SET、OUT 引脚使用说明:

S 表示模块与被测物体之间的距离;
S1 表示设定的最大警界阀值(上限阀值);
S2 表示设定的最小警界阀值(下限阀值);
S3 表示解除最大警界状态值;S3 和 S1 的关系,S3+3≤S1。例如 S1=100,则 S3≤97;
S4 表示解除最小警界状态值;S4 和 S2 的关系,S4-3≥S2。例如 S2=50,则 S3≥53;
OUT 引脚的状态为高电平和低电平两种。高电平表示 S2<S<S1;低电平表示 S>S1 或 S<S2。

(1)OUT 由高电平变低电平。当模块 S>S1 或 S<S2 时,OUT 引脚变成低电平,模块 LED灯将由亮变灭。
(2)OUT 由低电平变高电平。当 S>S1,让 S≤S3 时(即当实际距离低于最大警界阀值 3cm时),OUT 引脚由低电平变高电平,模块 LED 灯将由灭变亮。当 S<S2,让 S≥S4 时(即当实际距离大于最小警界阀值 3cm 时),OUT 引脚由低电平变高电平,模块 LED 灯将由灭变亮。

  • 2. 设置最大警界阀值:可通过发送指令外,也可通过 SET 引脚手动来设置。

(1)模块连续输出模式下,例如设置最大警界阀值 S1 为 100cm,则将模块放置在据被测物体 97cm 的位置进行 SET 引脚设置,或者发送指令:(A5 98 64 A1)0x64 是十进制的 100。
(2)手动 SET 引脚接入 3.3V 高电平,大约 3 秒,待模块 LED 指示灯闪速 2 下,此时断开 SET 引脚 3.3V 连接,断开后大约 5 秒,待 LED 闪烁 3 下,则设置成功。如果 LED 闪烁 4下,表示设置失败。失败原因有两种,一种是,接入高电平时间不够,另一种是设置的距离值小于最小警界阀值。

  • 3. 设置最小警界阀值:可通过发送指令外,也可通过 SET 引脚来设置。

(1)模块连续输出模式下,例如设置最小警界阀值 S2 为 50cm,则将模块放置在据被测物体 53cm 的位置,进行 SET 引脚设置, 或者发送指令:(A5 A9 32 B2)0x32 是十进制的 50。
(2)手动 SET 引脚接入 GND,大约 3 秒,待模块 LED 指示灯闪速 2 下,此时断开 SET 引脚 GND 连接,断开后大约 5 秒,待 LED 闪烁 3 下,则设置成功。如果 LED 闪烁 4 下,表示设置失败。失败原因有两种,一种是,接入低电平时间不够,另一种是设置的距离值大于最大警界阀值。

  • 4. 串口下 GY56 模块校准说明:

该模块由测距传感器和一个 MCU 组成。
(1)SPADs 修正: 当测距传感器上方被透明材质物体覆盖,模块需进行一次该修正,
并上电后加载 SPADs 修正参数。默认情况下,模块在每次上电后会进行一次 SPADs 修正操作,如用户手动执行一次 SPADs 修正后,设置了上电加载 SPADs 修正参数则模块不进行上电后 SPADs 修正操作,这样可以缩短模块初始化时间;通过上位机发送十六进制 A5 0A 01 B0 给模块,模块 LED 亮起,待熄灭校准完成。
(2)温度修正: 当模块工作环境温度变化超过 8 摄氏度,测距传感器灵敏度会发生改变,需进行一次温度修正;默认情况下,模块在每次上电后会进行一次温度修正操作,如模块工作环境温度恒定,可进手动进行一次温度修正后,设置模块上电后加载温度修正参数,这样可以缩短模块初始化时间;如用户开启了自动温度修正,则模块根据 MCU 温度超过 8度后,自行进行一次温度修正;通过上位机发送十六进制 A5 10 01 B6 给模块,模块 LED亮起,待熄灭校准完成。
(3)偏差校准: 当模块测距值与实际值之间存在一个固有的偏差时,可执行此操作。
偏差校准的指令=0xA5+0x21+指令值+sum,指令值为实际距离值。例如:模块测距值为
13CM,而实际值为 10CM,则指令中的指令值为十进制的 10;如需重新上电后加载该补偿值,需设置上电后加载偏差校准参数。通过上位机发送十六进制指令给模块,模块 LED 亮起,待熄灭校准完成。
(4)窗口校准: 当测距传感器上方被透明材质物体覆盖,模块在全量程测距的值不是线性的情况下,执行该操作。如下图所示:
在这里插入图片描述
X 轴为实际值,Y 轴为测量值。绿色虚线说明该材质对测距无影响或是传感器表面
无任务材质覆盖,蓝色线表明为轻度影响,红线为中度影响,绿色实线为重度影响。
窗口校准的指令=0xA5+0x32+指令值+sum;

指令值的选取:使用 17%灰色的反射率目标,则设模块与被测目标的距离为 S。对于
轻度影响的情况下,参见下图左侧蓝线,只要 S 在 AB 之间即可。指令值为实际距离值。中度影响的选取右测红线 AB 之间区域。如需重新上电后加载该补偿值,需设置上电后加载窗口校准参数。通过上位机发送十六进制指令给模块,模块 LED 亮起,待熄灭校准完成。
在这里插入图片描述

IIC 模式:该模式为每发送一次启动测量命令,模块才会进行一次测距操作,等待测距完成才能读取距离值,测距时间根据模块所处何种测量模式,如下表,例如是高精度模式,则需在大约 200ms 后读取测距值。模块的测量模式配置需通过串口方式进行设置。

在这里插入图片描述

四、GY56 上位机

在这里插入图片描述

五、STM32驱动代码

1. 串口初始化

	//GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);	//使能USART2,GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
	//USART2_TX   GPIOA
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2

	//USART2_RX	  GPIOA
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3 

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

	//USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART2, &USART_InitStructure); //初始化串口2
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART2, ENABLE);                    //使能串口2

2. 发送指令

void USART_Send(uint8_t *Buffer, uint8_t Length)
{
    
    
	uint8_t i=0;
	while(i<Length)
	{
    
    
		if(i<(Length-1))
		Buffer[Length-1]+=Buffer[i];//累加Length-1前的数据
		while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕   
		USART_SendData(USART2,Buffer[i++]); 
	}
}

void send_com(u8 function,u8 value )
{
    
    
	u8 bytes[4]={
    
    0};
	bytes[0]=0xa5;
	bytes[1]=function;//功能指令
	bytes[2]=value;//指令值
	USART_Send(bytes,4);//发送帧头、功能字节、校验和
}

3. 接收中断

void USART2_IRQHandler(void)                	//串口2中断服务程序
{
    
    
	static uint8_t i=0,rebuf[20]={
    
    0};
	if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//判断接收标志
	{
    
    
		rebuf[i++]=USART_ReceiveData(USART2);//读取串口数据,同时清接收标志
		if (rebuf[0]!=0x5a)//帧头不对
			i=0;	
		if ((i==2)&&(rebuf[1]!=0x5a))//帧头不对
			i=0;
	
		if(i>3)//i等于4时,已经接收到数据量字节rebuf[3]
		{
    
    
			if(i!=(rebuf[3]+5))//判断是否接收一帧数据完毕
				return;	
			switch(rebuf[2])//接收完毕后处理
			{
    
    
				case 0x15:
					if(!Receive_ok)//当数据处理完成后才接收新的数据
					{
    
    
						memcpy(re_Buf_Data,rebuf,9);//拷贝接收到的数据
						Receive_ok=1;//接收完成标志
					}
					break;
			
			}
			i=0;//缓存清0
		}
	}
} 

4. 数据解析

if(Receive_ok)//串口接收完毕
{
    
    
	for(sum=0,i=0;i<(re_Buf_Data[3]+4);i++)
	sum+=re_Buf_Data[i];
	if(sum==re_Buf_Data[i])//校验和判断
	{
    
    
		GY56.distance=re_Buf_Data[4]<<8|re_Buf_Data[5];
		GY56.mode=re_Buf_Data[6];
		GY56.temp=re_Buf_Data[7];		
		printf("%d\r\n",GY56.distance);
	}
	Receive_ok=0;//处理数据完毕标志
}

六、MSP432驱动代码

1. 串口初始化

void UARTA2_Init(void)
{
    
    
    //1.配置GPIO复用
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

    //2.配置UART结构体
#ifdef EUSCI_A_UART_7_BIT_LEN
    //固件库v3_40_01_02
    //默认SMCLK 48MHz 比特率 115200
    const eUSCI_UART_ConfigV1 uartConfig =
        {
    
    
            EUSCI_A_UART_CLOCKSOURCE_SMCLK,                // SMCLK Clock Source
            26,                                            // BRDIV = 26
            0,                                             // UCxBRF = 0
            111,                                           // UCxBRS = 111
            EUSCI_A_UART_NO_PARITY,                        // No Parity
            EUSCI_A_UART_LSB_FIRST,                        // MSB First
            EUSCI_A_UART_ONE_STOP_BIT,                     // One stop bit
            EUSCI_A_UART_MODE,                             // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
            EUSCI_A_UART_8_BIT_LEN                         // 8 bit data length
        };
    eusci_calcBaudDividers((eUSCI_UART_ConfigV1 *)&uartConfig, 115200); //配置波特率
#else
    //固件库v3_21_00_05
    //默认SMCLK 48MHz 比特率 115200
    const eUSCI_UART_Config uartConfig =
        {
    
    
            EUSCI_A_UART_CLOCKSOURCE_SMCLK,                // SMCLK Clock Source
            26,                                            // BRDIV = 26
            0,                                             // UCxBRF = 0
            111,                                           // UCxBRS = 111
            EUSCI_A_UART_NO_PARITY,                        // No Parity
            EUSCI_A_UART_LSB_FIRST,                        // MSB First
            EUSCI_A_UART_ONE_STOP_BIT,                     // One stop bit
            EUSCI_A_UART_MODE,                             // UART mode
            EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
        };
    eusci_calcBaudDividers((eUSCI_UART_Config *)&uartConfig, 115200); //配置波特率
#endif
    //3.初始化串口
    UART_initModule(EUSCI_A2_BASE, &uartConfig);

    //4.开启串口模块
    UART_enableModule(EUSCI_A2_BASE);
	
    //5.开启串口相关中断
    UART_enableInterrupt(EUSCI_A2_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);

    //6.开启串口端口中断
    Interrupt_enableInterrupt(INT_EUSCIA2);

    //7.开启总中断
    Interrupt_enableMaster();
}

2. 发送指令

void USART2_Send(uint8_t *Buffer, uint8_t Length)
{
    
    
	uint8_t i=0;
	while(i<Length)
	{
    
    
		if(i<(Length-1))
		Buffer[Length-1]+=Buffer[i];//累加Length-1前的数据
		//while (!(UART_getInterruptStatus(EUSCI_A2_BASE, EUSCI_A_UART_TRANSMIT_COMPLETE))); //循环发送,直到发送完毕   
		UART_transmitData(EUSCI_A2_BASE, Buffer[i++]);
	}
}

void send_com(u8 function,u8 value )
{
    
    
	u8 bytes[4]={
    
    0};
	bytes[0]=0xa5;
	bytes[1]=function;//功能指令
	bytes[2]=value;//指令值
	USART2_Send(bytes,4);//发送帧头、功能字节、校验和
}

3. 接收中断

void EUSCIA2_IRQHandler(void)
{
    
    
    uint32_t status = UART_getEnabledInterruptStatus(EUSCI_A2_BASE);
	static uint8_t i=0,rebuf[20]={
    
    0};
	
    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) //接收中断
    {
    
    
		rebuf[i++]=MAP_UART_receiveData(EUSCI_A2_BASE);;//读取串口数据,同时清接收标志
		if (rebuf[0]!=0x5a)//帧头不对
			i=0;	
		if ((i==2)&&(rebuf[1]!=0x5a))//帧头不对
			i=0;
	
		if(i>3)//i等于4时,已经接收到数据量字节rebuf[3]
		{
    
    
			if(i!=(rebuf[3]+5))//判断是否接收一帧数据完毕
				return;	
			switch(rebuf[2])//接收完毕后处理
			{
    
    
				case 0x15:
					if(!Receive_ok)//当数据处理完成后才接收新的数据
					{
    
    
						memcpy(re_Buf_Data,rebuf,9);//拷贝接收到的数据
						Receive_ok=1;//接收完成标志
					}
					break;
			
			}
			i=0;//缓存清0
		}
    }

}

4. 数据解析

if(Receive_ok)//串口接收完毕
{
    
    
	for(sum=0,i=0;i<(re_Buf_Data[3]+4);i++)
	sum+=re_Buf_Data[i];
	if(sum==re_Buf_Data[i])//校验和判断
	{
    
    
		GY56.distance=re_Buf_Data[4]<<8|re_Buf_Data[5];
		GY56.mode=re_Buf_Data[6];
		GY56.temp=re_Buf_Data[7];		
		printf("%d\r\n",GY56.distance);
	}
	Receive_ok=0;//处理数据完毕标志
}

猜你喜欢

转载自blog.csdn.net/Dustinthewine/article/details/131492162