打印
[范例教程]

VL53L0X激光测距模块的单片机驱动程序

[复制链接]
470|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
saservice|  楼主 | 2023-8-26 23:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
 
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int

#define VL53L0X_REG_IDENTIFICATION_MODEL_ID         0xc0
#define VL53L0X_REG_IDENTIFICATION_REVISION_ID      0xc2
#define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD   0x50
#define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
#define VL53L0X_REG_SYSRANGE_START                  0x00
#define VL53L0X_REG_RESULT_INTERRUPT_STATUS         0x13
#define VL53L0X_REG_RESULT_RANGE_STATUS             0x14
#define address 0x52

sbit I2C_SCL = P1^3;
sbit I2C_SDA = P1^2;


void I2C_Delay10us();
void I2C_Start();
void I2C_Stop();
uchar I2C_SendByte(uchar dat);
uchar I2C_ReadByte();
//void I2C_SendACK(bit ack);
void vl53l0x_send(uchar reg,uchar dat);
uchar vl53l0x_read(uchar reg);
short makeuint16(int lsb, int msb);

uchar gbuf[16];
uint acnt ;
uint scnt;
uint dist ;
uchar DeviceRangeStatusInternal;

/*******************************************************************************
* 函 数 名         : Delay1ms()                //@11.0592MHz
* 函数功能                     : 延时
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Delay1ms()                //@11.0592MHz
{
    unsigned char i, j;

    _nop_();
    i = 11;
    j = 190;
    do
    {
        while (--j);
    } while (--i);
}
/*******************************************************************************
* 函 数 名         : delay_ms(unsigned int time)
* 函数功能                     : 延时
* 输    入         : time
* 输    出         : 无
*******************************************************************************/
void delay_ms(unsigned int time)
{
    unsigned char
    i;
    for(i=1; i<=time; i++)
        Delay1ms();
}
/*******************************************************************************
* 函 数 名         : Delay1us()
* 函数功能                   : 延时
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void I2C_Delay10us()
{
    unsigned char i;

    _nop_();
    _nop_();
    _nop_();
    i = 24;
    while (--i);
}
/*******************************************************************************
* 函 数 名         : I2C_Start()
* 函数功能                   : 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
* 输    入         : 无
* 输    出         : 无
* 备    注         : 起始之后I2C_SDA和I2C_SCL都为0
*******************************************************************************/
void I2C_Start()
{
    I2C_SDA = 1;
    I2C_Delay10us();
    I2C_SCL = 1;
    I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
    I2C_SDA = 0;
    I2C_Delay10us();//保持时间是>4us
    I2C_SCL = 0;
    I2C_Delay10us();
}
/*******************************************************************************
* 函 数 名           : I2C_Stop()
* 函数功能                 : 终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
* 输    入           : 无
* 输    出                  : 无
* 备    注           : 结束之后保持I2C_SDA和I2C_SCL都为1;表示总线空闲
*******************************************************************************/
void I2C_Stop()
{
    I2C_SDA = 0;
    I2C_Delay10us();
    I2C_SCL = 1;
    I2C_Delay10us();//建立时间大于4.7us
    I2C_SDA = 1;
    I2C_Delay10us();
}
/*******************************************************************************
* 函 数 名           : I2cSendByte(uchar num)
* 函数功能                  : 通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,
*                    * 保持发送信号I2C_SDA保持稳定
* 输    入           : num ,ack
* 输    出                  : 0或1。发送成功返回1,发送失败返回0
* 备    注           : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0
*******************************************************************************/
uchar I2C_SendByte(uchar dat)
{
    uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。

    for(a=0; a<8; a++)//要发送8位,从最高位开始
    {
        dat <<= 1;
        I2C_SDA=CY;
        I2C_Delay10us();
        I2C_SCL = 1;
        I2C_Delay10us();//建立时间>4.7us
        I2C_SCL = 0;
        I2C_Delay10us();//时间大于4us
    }

    //I2C_SDA = 1;
    //I2C_Delay10us();
    I2C_SCL = 1;
    I2C_Delay10us();
    CY=I2C_SDA;
    I2C_SCL = 0;
    I2C_Delay10us();
    return CY;
}
/*******************************************************************************
* 函 数 名           : I2cReadByte()
* 函数功能                     : 使用I2c读取一个字节
* 输    入           : 无
* 输    出                  : dat
* 备    注           : 接收完一个字节I2C_SCL=0
*******************************************************************************/
uchar I2C_ReadByte()
{
    uchar a = 0,dat = 0;
    I2C_SDA = 1;                        //起始和发送一个字节之后I2C_SCL都是0
    I2C_Delay10us();
    for(a=0; a<8; a++)//接收8个字节
    {
        I2C_SCL = 1;
        I2C_Delay10us();
        dat <<= 1;
        dat |= I2C_SDA;
        I2C_Delay10us();
        I2C_SCL = 0;
        I2C_Delay10us();
    }
    return dat;
}
/*******************************************************************************
* 函 数 名           : vl53l0x_send(uchar reg,uchar dat)
* 函数功能                     : 使用I2c向vl530xl发送命令
* 输    入           : reg,dat
* 输    出                  : 无
*******************************************************************************/
void vl53l0x_send(uchar reg,uchar dat)
{
    I2C_Start();
    I2C_SendByte(address);
    I2C_SendByte(reg);
    I2C_SendByte(dat);
    I2C_Stop();
}
/*******************************************************************************
* 函 数 名           : vl53l0x_read(uchar reg)
* 函数功能                     : 使用I2c向vl530x0l读取一个字节
* 输    入           : reg
* 输    出                  : num
*******************************************************************************/
uchar vl53l0x_read(uchar reg)
{
    unsigned char num;
    I2C_Start();
    I2C_SendByte(address); //发送写器件地址
    I2C_SendByte(reg); //发送要读取的地址
                I2C_Stop();
    I2C_Start();
    I2C_SendByte(address+1); //发送读器件地址
    num=I2C_ReadByte(); //读取数据
    I2C_Stop();
    return num;
}
/*******************************************************************************
* 函 数 名           :  makeuint16(int lsb, int msb)
* 函数功能                       :  将读出数据转换到数组当中
* 输    入           : lsb,msb
* 输    出                  : dat
*******************************************************************************/
short makeuint16(int lsb, int msb)
{
    return ((msb & 0xFF) << 8) | (lsb & 0xFF);
}
/*******************************************************************************
* 函 数 名           :  date()
* 函数功能                       :  进行数据的读取与转换,将数据处理
* 输    入           : 无
* 输    出                  : dist
*******************************************************************************/
unsigned char date()
{
        uchar val = 0;        
//        uchar vall;
        int cnt = 0;
                        vl53l0x_send(VL53L0X_REG_SYSRANGE_START, 0x01);
                while (cnt < 100)                                      ///检测数据是否传输正常
                {
      delay_ms(10);
      val = vl53l0x_read(VL53L0X_REG_RESULT_RANGE_STATUS);
      if (val & 0x01) break;
      cnt++;
    }
                 gbuf[0]=vl53l0x_read(0x14);
                 gbuf[7]=vl53l0x_read(0x14+7);
                 gbuf[6]=vl53l0x_read(0x14+6);
                 gbuf[9]=vl53l0x_read(0x14+9);
                 gbuf[8]=vl53l0x_read(0x14+8);
                 gbuf[11]=vl53l0x_read(0x14+11);
                 gbuf[10]=vl53l0x_read(0x14+10);
     acnt = makeuint16(gbuf[7], gbuf[6]);
     scnt = makeuint16(gbuf[9], gbuf[8]);                 
     dist = makeuint16(gbuf[11], gbuf[10]);                 
//                 DeviceRangeStatusInternal = ((gbuf[0] & 0x78) >> 3);
//                         if(DeviceRangeStatusInternal==11&&dist>20&&dist<1200)
//                        {
//                                vall=dist/10000;
//                    OLED_dan(8*0,0,vall+16);
//                    vall=dist%10000/1000;
//                    OLED_dan(8*1,0,vall+16);
//                    vall=dist%1000/100;
//                    OLED_dan(8*2,0,vall+16);
//                    vall=dist%100/10;
//                    OLED_dan(8*3,0,vall+16);
//                    vall=dist%10/1;
//                    OLED_dan(8*4,0,vall+16);
//                        }
                        return  dist;             //该数组为五位
}
void main()
{

        while(1)
        {
    date();
        }
}


使用特权

评论回复
沙发
uiint| | 2023-9-12 15:57 | 只看该作者
VL53L0X激光测距模块的工作温度为-40℃到+85℃。在使用前,需要确保模块的工作温度在范围内,以免影响其工作稳定性。

使用特权

评论回复
板凳
loutin| | 2023-9-12 20:35 | 只看该作者
注意模块的最小和最大测量距离以及测量误差。

使用特权

评论回复
地板
deliahouse887| | 2023-9-12 21:48 | 只看该作者
必要时可以采取软件滤波方法提高测量精度。

使用特权

评论回复
5
bestwell| | 2023-9-12 22:05 | 只看该作者
VL53L0X模块上的激光传感器和光学元件非常敏感

使用特权

评论回复
6
jonas222| | 2023-9-13 10:29 | 只看该作者
通常,VL53L0X模块使用I2C接口进行通信

使用特权

评论回复
7
rosemoore| | 2023-9-13 11:54 | 只看该作者
检查模块的规格和数据手册,并根据要求提供稳定的电源。

使用特权

评论回复
8
phoenixwhite| | 2023-9-13 12:44 | 只看该作者
VL53L0X通常可以在3.3V到5V的电压范围内工作。不要超过这个范围,以免损坏模块。

使用特权

评论回复
9
houjiakai| | 2023-9-13 12:53 | 只看该作者
解VL53L0X的数据输出格式以及如何进行数据处理非常重要。

使用特权

评论回复
10
lihuami| | 2023-9-13 15:03 | 只看该作者
尽管VL53L0X可以测量不同目标的距离,但目标的反射率会影响测量精度。不同材质和颜色的目标可能会产生不同的测量结果。在特定应用中,需要注意这一点。

使用特权

评论回复
11
maqianqu| | 2023-9-13 17:36 | 只看该作者
VL53L0X模块提供测距数据,需要适当的数据处理和解释。根据模块的输出格式和单位,将测量数据转换为实际距离或其他相关信息。

使用特权

评论回复
12
phoenixwhite| | 2023-9-13 19:40 | 只看该作者
VL53L0X激光测距模块的工作电压为3.3V到5V。

使用特权

评论回复
13
bestwell| | 2023-9-13 19:57 | 只看该作者
VL53L0X激光测距模块提供了四种不同的精度模式,针对不同的精度模式,测量时间也是有所区别的,测量精度越高,需要的测量时间越长。

使用特权

评论回复
14
febgxu| | 2023-9-13 22:07 | 只看该作者
在明亮的阳光下或强光源附近使用时,可能需要采取额外的措施来减小环境光的干扰。

使用特权

评论回复
15
lzmm| | 2023-9-17 08:17 | 只看该作者
VL53L0X模块通常通过I2C接口与主控单元通信。确保正确连接和配置I2C接口,并根据模块的规格和文档使用正确的通信协议。

使用特权

评论回复
16
wilhelmina2| | 2023-9-17 10:11 | 只看该作者
在布局和安装模块时,避免遮挡激光发射和接收器的视野。

使用特权

评论回复
17
wangdezhi| | 2023-9-17 10:53 | 只看该作者
在使用VL53L0X激光测距模块时,需要注意周围环境的光干扰。

使用特权

评论回复
18
biechedan| | 2023-9-17 12:17 | 只看该作者
VL53L0X激光测距模块有单次模式、连续模式、连续间隔模式三种工作模式,不同模式下测距操作时间和方式有所不同。

使用特权

评论回复
19
wengh2016| | 2023-9-17 13:21 | 只看该作者
VL53L0X激光测距模块的测量范围为10cm到1000m

使用特权

评论回复
20
uytyu| | 2023-9-17 15:17 | 只看该作者
工作光功率为100mW到300mW

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

1082

帖子

2

粉丝