GY56红外激光测距传感器工作原理及STM32、MSP432代码详解

文章目录

  • 一、GY56简介
  • 1. 概述
  • 2. 特点
  • 3. 参数
  • 4. 引脚说明
  • 5. 应用
  • 二、通信协议
  • 1. 串口
  • 2. IIC协议
  • 三、模块使用方法
  • 四、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;//处理数据完毕标志
    }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » GY56红外激光测距传感器工作原理及STM32、MSP432代码详解

    发表评论