分享一个TFMINI激光测距传感器的程序

2019-07-20 23:07发布

       前段时间在做一个项目时,用到了一块TFMINI激光测距的传感器,在编写程序时,自己也遇到了一些问题,跟大家分享一下。
       首先,简要介绍一下这个传感器的基本情况。
       TFmini 是一款小型激光雷达模组。主要实现实时、无接触式的距离测量功能,具有测量准确、稳定、高速的特点。TFmini 产品经过光路与算法优化,已最大程度减小外界环境对测距性能的影响。但限于工作原理,测距范围仍会受到环境光照强度和被测目标反射率不同程度的影响。

       ①:TFmini 的测距盲区,为 0-30cm,该范围内的数据不可信。
       ②:TFmini 在极限环境下的测距范围,一般为 0.3-3m,极限条件是指室外强光(夏天正午室外的光照强度约 100klux 左右)下对黑 {MOD}目标物(10%反射率)探测。
       ③:代表 TFmini 在一般日照条件下(70klux 左右)测量白 {MOD}目标物的测距范围,包含②的范围,为 0.3-7m。
       ④:代表 TFmini 在室内或环境光很弱的情况下,测距范围为 0.3-12m。

简而言之,这个传感器能够实现元距离较为精确的距离测量。
       TFmini 采用串口数据通信协议。通信接口 UART默认波特率 115200,数据位 8,停止位 1,奇偶校验 None。TFmini 有两种数据输出格式,标准数据输出格式(默认)和 pixhawk 数据格式。
       标准数据输出格式(默认):数据结构:每个数据包为 9Byte。包含距离信息(Dist)、信号强度信息(Strength)、测距档位(Mode)、数据校验字节(CheckSum)等。数据格式为 16 进制(HEX)。具体数据编码详见表 。
1.PNG
       在我的项目中,我用的就是这个默认数据格式。我将这传感器与串口2相连。用串口2接收传感器发送的数据包,并将数据帧解析出来。在这个地方我停滞了很久,原因就是我在串口接收数据时,处理的不到位,导致解析的数据异常。同时,我也查了相当多的资料、论坛,CSDN啥的逛了好久,也借鉴了其他人的方法,包括利用空闲中断啥的,依旧没有解决。没办法,自己就用仿真器仿真调试,一步一步运行,终于解决了这个问题。说来丢人,还是怪自己C语言掌握不牢,在编写解析程序时犯了几个错误。
       下面是我调试成功的程序。主要的就是在串口接收中断里的处理。
       首先,还是常规的串口2配置:   [mw_shl_code=c,true]#include "tfmini.h"#include "delay.h"
#define USART2_REC_LEN   200
#define EN_USART2               1
#define Data_Head            0X59   
#define        Data_Length            9   
u16 USART2_RX_BUF[USART2_REC_LEN];     
u16 TFMINI_Distance;   
void USART2_Init(u32 bound)   
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
   USART_InitTypeDef USART_InitStructure;
   NVIC_InitTypeDef NVIC_InitStructure;
                 
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;            
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;            
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;             
    GPIO_Init(GPIOA, &GPIO_InitStructure);  

   //USART2相关初始化
        USART_InitStructure.USART_BaudRate = bound;        
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        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);            
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);        
        USART_Cmd(USART2, ENABLE);                          

        //Usart2 NVIC配置
          NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
          NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;               
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                       
          NVIC_Init(&NVIC_InitStructure);                            
}            

[/mw_shl_code]
        接下来就是串口接收数据帧的处理了:        [mw_shl_code=c,true]void USART2_IRQHandler(void)
{
      static u8 seri_count=0;
      u16 check_sum=0;                          //D£Ñéoí
      u8 i;
      static u8 flag;
      if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
     {       
                                                 
       if(USART_ReceiveData(USART2) == Data_Head)
      {
         flag = 1;
      }
                       
      if(flag)
     {       
          USART2_RX_BUF[seri_count++] =USART_ReceiveData(USART2);
                               
         if(seri_count == Data_Length)       
         {
             if(USART2_RX_BUF[0]==Data_Head && USART2_RX_BUF[1]== Data_Head)
             {
                for( i = 0; i < Data_Length-1; i++)
               {
                  check_sum += USART2_RX_BUF;             //&#188;&#198;&#203;&#227;D£&#209;éoí
               }
               if((check_sum & 0x00ff)== USART2_RX_BUF[8])  TFMINI_Distance = USART2_RX_BUF[2] + USART2_RX_BUF[3]* 256;
              //        printf("dis=  %d ",data);
                seri_count = 0;
                flag=0;
            }                                               
        }       
    }
   }  
}[/mw_shl_code]       在此,给大家提供一个解决思路。如果有更好的方法,欢迎大家跟我讨论。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。