MSP432P401R+TOFLuna激光雷达测距+OLED显示

目录

前言 

一、TOFLuna激光雷达

 1、工作原理

测距原理

数据传输解析

二、 CCS工程代码部分代码

main.c

tof.c

tof.h

usart.c

三、输出结果显示

四、源码链接


前言 

前段时间弄到了一个TOF的Luna迷你激光雷达,一直想弄来着,正好昨天看到了于是花一天写了一个驱动协议,电赛需要的小伙伴可以参考一下。


一、TOFLuna激光雷达

这个是官方的说明书资料:链接:https://pan.baidu.com/s/13CejQEn5fjeshuhveFg9ig 提取码:cg2x

可以看到这个雷达还是很小巧的,就是有点小贵。。。。。。

TF-Luna有两种工作模式,一个是串口通信模式,一个是I2C通信模式,我这里写的协议是串口通信的,I2C通信协议之后有时间补上吧。(挖坑+1)

 1、工作原理

测距原理

TF-Luna基于TOF (Time ofFlight)即飞行时间原理。具体为产品周期性的向外发出近红外光调制波,调制波遇物体后反射。产品通过测量调制波往返相位差,得到飞行时间,再计算出产品与被测目标之间的相对距离,如图所示,测量距离为0.2m~8m还是挺远的。


 

 

数据传输解析

从图中可以看出9字节cm数据格式下,第一位和第二位是0x59,也就是信号起始位,第三位和第四位是距离数据的低8位和高8位,第五位和第六位是信号强度数据的低8位和高8位,第七位和第八位是温度数据的低8位和高8位,计算公式是Temp / 8-256,知道数据格式之后我们就可以开始编写协议了,当然主要还是根据说明手册来编写。


二、 CCS工程代码部分代码

main.c

/****************************************************/
// MSP432P401R
// 激光测距
// Bilibili:巴啦啦1能量
// CSDN:静·无羡
// E-mail:3075221401@qq.com
// 创建日期:2021/10/31
/****************************************************/
#include "sys.h"
/*  全局变量申明区  */
/* extern variables ----------------------------------------------------------*/

/* 函数调用申明区 */


int main(void)
{
    System_init();
    while(1)
    {
        Get_Distance();
    }
}


tof.c

/****************************************************/
// MSP432P401R
// 激光测距
// Bilibili:巴啦啦1能量
// CSDN:静·无羡
// E-mail:3075221401@qq.com
// 创建日期:2021/10/31
/****************************************************/

#include "tof.h"
#include "usart.h"
#include "oled.h"
#include "delay.h"
/**************************************         全局变量          *******************************************/
uint8_t Freq;//输出频率
uint8_t I2C_slave_addr;//I2C从机地址
uint8_t Dist_min_High,Dist_min_Low,Dist_max_High,Dist_max_Low;//距离限制变量
uint32_t timeout;
uint16_t Distance,Sign,Temp;
Format_Type TOF_Format = Format_CM;//9字节CM输出模式
Output_Type TOF_Output = Output_On;//使能输出
Checksum_Type TOF_Checksum = Frame_Checksum_Off;//关闭校验和
Filter_Type TOF_Filter = Filter_bit;//开启卡尔曼滤波和中值滤波
Power_Type TOF_Power = Low_Power_Mode_OFF;//退出超低功耗模式
DEALIAS_Type TOF_Freq = Dobule_Freq_Mode;//双频模式
CONFIG_Type TOF_Config;//雷达配置
/**************************************         指令集合          *******************************************/
uint8_t LOW_POWER_MODE[5] = {0x5a,0x05,0x58,0x00,0x00};//关闭开启超功耗模式
uint8_t SAVE_SETTINGS[4] = {0x5a,0x04,0x11,0x00};//保存当前设置返回数据为[0x5a,0x05,0x11,data,0x6f],data为0则成功,非0则失败。
uint8_t SOFT_RESET[4] = {0x5a,0x04,0x02,0x00};//系统软件复位
uint8_t SAMPLE_FREQ[6] = {0x5a,0x06,0x03,0x32,0x00,0x00};//设置输出频率
uint8_t SAMPLE_TRIG[4] = {0x5a,0x04,0x04,0x00};//单次触发指令
uint8_t OUTPUT_FORMAT[5] = {0x5a,0x05,0x05,0x01,0x00};//设置输出格式
uint8_t BAUD_RATE[8] = {0x5a,0x08,0x06,0x00,0xc2,0x01,0x00,0x00};//设置串口波特率115200
uint8_t OUTPUT_EN[5] = {0x5a,0x05,0x07,0x01,0x00};//输出开关
uint8_t FRAME_CHECKSUM[5] = {0x5a,0x05,0x08,0x00,0x00};//校验和开关
uint8_t I2C_SLAVE_ADDR[5] = {0x5a,0x05,0x0B,0x20,0x00};//修改I2C从机地址 范围[0x08,0x77]
uint8_t RESTORE_DEFAULT[4] = {0x5a,0x04,0x10,0x00};//恢复出厂设置,返回数据为[0x5a,0x05,0x10,data,0x6f],data为0则成功,非0则失败。
uint8_t READ_MANU_BIN[4] = {0x5a,0x04,0x12,0x00};//读取生产条码
uint8_t LOW_CONSUMPTION[6] = {0x5a,0x06,0x35,0x32,0x00,0x00};//低功耗模式
uint8_t FILTER_BIT_MAP[5] = {0x5a,0x05,0x39,0x03,0x00};//滤波器设置开启卡尔曼滤波和中值滤波
uint8_t DIST_LIMIT[9] = {0x5a,0x09,0x3a,0x14,0x00,0xF4,0x01,0x00,0x00};//设置距离限制
uint8_t GET_CONFIG_PARA[5] = {0x5a,0x05,0x08,0x03,0x00};//读取指定的雷达配置

/**************************************         串口波特率          *******************************************/
/*
 * 9600     [5A 08 06 80 25 00 00 00]
 * 19200    [5A 08 06 00 4B 00 00 00]
 * 38400    [5A 08 06 00 96 00 00 00]
 * 57600    [5A O8 06 00 E1 00 00 00]
 * 115200   [5A 08 06 00 C2 01 00 00]
 * 230400   [5A 08 06 00 84 03 00 00]
 * 460800   [5A 08 06 00 08 07 00 00]
 * 921600   [5A 08 06 00 10 OE 00 00]
 * */


void TOF_init(void)
{
    Freq = 0x00;//设置频率为0
    Send_Data(SAMPLE_FREQ);//设置频率
    Send_Data(SAMPLE_TRIG);//单次触发指令
    waitflag=1;
    rxcnt=0;
}

void Get_Distance(void)
{
    Send_Data(SAMPLE_TRIG);//单次触发指令
    timeout=10000;
    while((rxflag==0)&&(timeout--));
    //如果是主动发送只需要查询rxflag标志位
    if(rxflag)//接收到一组有效数据
    {
        Distance = rxbuf[Dist_H] * 256 + rxbuf[Dist_L];
        Sign = rxbuf[Amp_H] * 256 + rxbuf[Amp_L];
        Temp = rxbuf[Temp_H] * 256 + rxbuf[Temp_L];
        Temp = Temp / 8 -256;
        rxflag = 0;
        rxcnt = 0;
        sprintf((char*)str,"Distance=%dCM     ",Distance);
        OLED_ShowString(1,0,str,12);
        sprintf((char*)str,"Sign=%d           ",Sign);
        OLED_ShowString(2,12,str,12);
        sprintf((char*)str,"Tempt=%d          ",Temp);
        OLED_ShowString(2,24,str,12);
        OLED_Refresh();
    }
}

void Send_Data(uint8_t *COM_DATA)
{
    int i;
    for(i = 0;i < *(COM_DATA + 1);i++)
    {

       USART0PutChar(*(COM_DATA + i));
    }
}

/****************************************************/
//(1)进入超低功耗模式
/*通过指令"超低功耗模式ID_ ULTRA_LOW_POWER_MODE=Ox58"使能超低功耗模式,该指令下发后TF-Luna停止串口输出,但并未立即进入超低功耗模式,
还需要继续依次发送“保存当前设置ID_SAVE_SETTINGS=0x11”和“系统软件复位ID_SOFT_RESET=Ox02"指令之后,TF-Luna才进入超低功耗模式。
由于配置已经保存,再次上电后将直接进入该模式。
*/
 /****************************************************/
void TOF_LOW_POWER_MODE_ON(Power_Type Power_Mode)
{
    TOF_Power = Power_Mode;
    LOW_POWER_MODE[3] = TOF_Power;
    Send_Data(LOW_POWER_MODE);
    delay_us(1);
    Send_Data(SAVE_SETTINGS);
    delay_us(1);
    Send_Data(SOFT_RESET);
}

/****************************************************/
/*(2)唤醒测距
用户通过串口向TF-Luna发送任意一个字节数据,将唤醒TF-Luna进行一次测距,测距完成后通过串口发送出指定格式的测距结果,然后再次进入超低功耗模式。
以115200波特率,9字节输出格式为例,唤醒时长约8.5ms。
*/
 /****************************************************/
void Wake_Up_Get_Distense(void)
{
    uint8_t Wake = 1;
    USART0PutChar(Wake);
}

/****************************************************/
/*(3)退出超低功耗模式
由于处于超低功耗模式下时TF-Luna的串口通信模块未使能,因此不能直接退出该模式,TF-Luna只能在被唤醒的短暂时序内可以响应串口指令。
因此用户需要连续发送“超低功耗模式 ID_ULTRA_LOW_POWER_MODE=Ox58"的"不使能”指令,直到接收到TF-Luna的回应。
然后用户再发送"保存当前设置ID_SAVE_SETTINGS=0x11"指令,确保将该状态保存。
*/
 /****************************************************/
void TOF_LOW_POWER_MODE_OFF(Power_Type Power_Mode)
{
    int i;
    TOF_Power = Power_Mode;
    LOW_POWER_MODE[3] = TOF_Power;
    for(i = 0;i < 3;i++)
    {
        Send_Data(LOW_POWER_MODE);
        delay_us(1);
    }
    Send_Data(SAVE_SETTINGS);
}




tof.h

/****************************************************/
// MSP432P401R
// 激光测距
// Bilibili:巴啦啦1能量
// CSDN:静·无羡
// E-mail:3075221401@qq.com
// 创建日期:2021/10/31
/****************************************************/

#ifndef __TOF_H
#define __TOF_H
#include <driverlib.h>

#define Dist_L          2
#define Dist_H          3
#define Amp_L           4
#define Amp_H           5
#define Temp_L          6
#define Temp_H          7
#define Check_sum       8
typedef enum
{
    Output_On = 0x01,//使能输出
    Output_Off = 0x00,//关闭输出
}Output_Type;//输出开关

typedef enum
{
    Frame_Checksum_On = 0x01,//开启校验和
    Frame_Checksum_Off = 0x00,//关闭校验和
}Checksum_Type;//校验和开关

typedef enum
{
    Format_CM = 0x01,//9字节CM输出
    Format_PIK = 0x02, //PIK输出
    Format_MM = 0x06, //9字节MM输出
    Format_BIT = 0x07, //带32bit时间戳
    Format_ID0 = 0x06, //IDO输出
    Format_CM0 = 0x09, //8字节CM输出
    Format_ID = 0x0A, //带设备ID输出
}Format_Type;//输出格式


typedef enum
{
    Filter_bit0 = 0x01,//开启卡尔曼滤波
    Filter_bit1 = 0x02,//开启中值滤波
    Filter_bit = 0x03,//开启卡尔曼滤波和中值滤波
}Filter_Type;

typedef enum
{
    Low_Power_Mode_ON = 0x01,//进入超低功耗模式
    Low_Power_Mode_OFF = 0x00,//退出超低功耗模式
}Power_Type;

typedef enum
{
    Dobule_Freq_Mode = 0x01,//双频模式
    Single_Freq_Mode = 0x00,//单频模式
}DEALIAS_Type;

typedef enum
{
    ID_Output_Format = 0x05,//输出格式设置
    ID_Output_EN = 0x07,//输出开关设置
    ID_Frame_Checksum_EN = 0x08,//校验和开关设置
    ID_DEALIAS_EN = 0x29,//单双频模式设置
    ID_DIST_LIMIT = 0x3A,//距离限制设置
    ID_ON_OFF_MODE = 0x3B,//开关量输出模式设置
}CONFIG_Type;

extern uint16_t Distance, Sign, Temp;
extern uint8_t Freq;//输出频率
extern uint8_t I2C_slave_addr;//I2C从机地址
extern uint8_t Dist_min_High,Dist_min_Low,Dist_max_High,Dist_max_Low;//距离限制变量
extern uint32_t timeout;
void TOF_init(void);
void Get_Distance(void);
void Send_Data(uint8_t *COM_DATA);
void TOF_LOW_POWER_MODE_ON(Power_Type Power_Mode);
void Wake_Up_Get_Distense(void);
void TOF_LOW_POWER_MODE_OFF(Power_Type Power_Mode);

#endif

usart.c

void uart_init(uint32_t baudRate)
{
#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, baudRate); //配置波特率
#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, baudRate); //配置波特率
#endif

  MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

  //初始化串口
  MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);

  //开启串口
  MAP_UART_enableModule(EUSCI_A0_BASE);
                                  /*开启串口相关中断*/
  UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT);

  /*开启串口端口中断*/
  Interrupt_enableInterrupt(INT_EUSCIA0);
}

void EUSCIA0_IRQHandler(void)
{
//    uint8_t  rev0;
    uint32_t status = UART_getEnabledInterruptStatus(EUSCI_A0_BASE);//中断接收标志

    if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)  //说明接收到数据
    {
//        rev0 = UART_receiveData(EUSCI_A0_BASE);//(UART0->DR); 读取接收到的数据
        if(rxflag == 0)
        {
            rxbuf[rxcnt++] = UART_receiveData(EUSCI_A0_BASE);//(UART0->DR); 读取接收到的数据
            if(rxcnt >= 2)
            {
                if(waitflag == 1)
                {
                    if((rxbuf[0] == TOF_RES_FLAG) && (rxbuf[1] == TOF_RES_FLAG))//串口接收距离TOF数据两次都为0x59
                    {
                        waitflag = 2;
                    }
                }
                else
                {
                    if(rxcnt == Check_sum)//串口接收TOF数据的最后一位
                    {
                        rxflag = 1;
                        waitflag = 1;
                    }
                }
            }
            else if(rxcnt >= 9)
            {
                rxcnt = 0;
            }
        }
        else
        {
            rxempty = UART_receiveData(EUSCI_A0_BASE);//(UART0->DR); 读取接收到的数据
        }
    }
}

三、输出结果显示

 

 第一行显示了距离数据,单位是CM,也可以设置为M和MM,第二行显示了信号强度,信号强度低于100则数据不可信,大于65536则是曝光严重,最后第三行显示了雷达的温度,单位是摄氏度。


四、源码链接

MSP432_Project.zip

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静·无羡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值