VL53L1X移植到STM32实战记录,使用软件IIC(附源代码)

2023-05-16

序言

VL53L1X是一个很小又很优秀的测距传感器,它相比于上一代VL53L0X有着不小的提升,这次毕业设计打算将这个传感器用起来,就来移植了一下,遇到的坑怎么说还是有一些,故在此分享给大家。

开发环境

IDE:Keil V5 STM32CubeMX ,使用HAL库

具体操作

获取官方库并进行移植

这一步是移植的基础,首先从官方把API库下下来,并添加到IDE中:
在这里插入图片描述

适配硬件

这里由于不同的硬件平台,他们对io的操作也是各异的,因此具体平台的c文件也是需要自己去修改的。由于VL53L1支持IIC通信,而硬件IIC通信速度也就那样,我更趋向于使用软件的模拟IIC,使用软件模拟IIC可以在进行硬件设计的时候可以使用任意的IO口,而不限制于具体的硬件IIC接口,而且移植起来也很简单(毕竟模拟IIC的硬件需求只有最普通的GPIO)。因此再导入模拟IIC的库文件,可以将两个io口模拟为IIC_SCL和IIC_SDA,同时模拟IIC提供了以下读写操作
在这里插入图片描述
IIC的接口也准备好了,那么我们就可以看vl53l1_platform.c这个平台适配文件了。
这个文件如果是从官方库拿下来的话,它的正文基本上全部都是一些空名函数,所有的函数列表如下:在这里插入图片描述
这些就是VL53的硬件操作函数了,如VL53L1_RdByte()这个函数就是VL53读取一个字节的函数。VL53的API库中的所有功能最终操作具体硬件的时候用的都是这个文件下的函数,因此我们必须把这些操作函数给移植到我们的硬件平台上,这样API函数才能调用我们实际的IIC硬件,最终完成操作硬件的目的。
以VL53L1_RdByte函数的移植为例

VL53L1_Error VL53L1_RdByte(VL53L1_DEV Dev, uint16_t index, uint8_t *data) {
    if(IIC_ReadOneByte(Dev->I2cDevAddr,index,data))
    {
        return VL53L1_ERROR_NONE;
    }else return VL53L1_ERROR_CONTROL_INTERFACE;
}

其中 Dev代表的API手册中的VL53结构体,它的其他元素我们并不关心,但传感器的器件地址就保存在Dev->I2cDevAddr里,器件地址是IIC操作的必须参数,另外两个必须参数则是读取的器件内的存储地址index和读取的长度了。因为在这里是只读一个字节,因此长度为1,使用了IIC_ReadOneByte这个函数。可以看到,移植API的硬件操作函数,其实就是在这个函数里面套用实际硬件的操作函数,套个壳而已罢了。但是在这种简单的套壳下,还有很多需要注意的坑,如读取一个半字的函数的实现如下:

VL53L1_Error VL53L1_RdWord(VL53L1_DEV Dev, uint16_t index, uint16_t *data) {
    uint8_t ret[2];
    IICreadBytes(Dev->I2cDevAddr,index,2,(uint8_t*)ret);
    *data=(ret[0]<<8) | ret[1];
    return VL53L1_ERROR_NONE;
}

可以看到,读取半字的操作函数竟然不是直接读2个字节返回,而是读取之后进行了高低位的字节的调换,这是因为STM32的存储方式是小端模式,而进行IIC通信的时候数据的传输方式是大端传输,因此为了保证数据的一致性就得进行调换。前面的例子不需要调换是因为它只涉及了一个字节的传输,就不存在大小端的问题。如果对大小端不了解的话可以去搜索引擎了解一下,它在数据交互的时候是一个非常需要注意的点。

在将这个文件的函数一个对应一个套娃完成后,这个API的硬件操作接口就算被我们实现了,那么我们现在就可以使用API的操作函数进行初始化设备了!

软件初始化

关于VL53的初始化,可以多多参考VL53的API手册,来进行如距离,测量速度等参数的确定。
我的初始化代码如下:

VL53L1_Error VL53L1Init(VL53L1_Dev_t* pDev)
{
    VL53L1_Error Status = VL53L1_ERROR_NONE;
    pDev->I2cDevAddr=0x52;//默认地址
    pDev->comms_type=1;//默认通信模式
    pDev->comms_speed_khz = 400;//通信速率(可到400hz)
    Status = VL53L1_WaitDeviceBooted(pDev);
    if(Status!=VL53L1_ERROR_NONE)
	{
		printf("Wait device Boot failed!\r\n");
		return Status;
	}
    osDelay(2);

	Status = VL53L1_DataInit(pDev);//device init
	if(Status!=VL53L1_ERROR_NONE) 
	{
		printf("datainit failed!\r\n");
		return Status;
	}

	osDelay(2);
	Status = VL53L1_StaticInit(pDev);
	if(Status!=VL53L1_ERROR_NONE) 
	{
		printf("static init failed!\r\n");
		return Status;
	}
	osDelay(2);
	Status = VL53L1_SetDistanceMode(pDev, VL53L1_DISTANCEMODE_LONG);	//short,medium,long
	if(Status!=VL53L1_ERROR_NONE) 
	{
		printf("set discance mode failed!\r\n");
		return Status;
	}
	osDelay(2);
	return Status;
}

其中前面三句都是标准的初始化流程 是调用任何其他API前的初始化函数,而最后一个则决定了测量模式。在这些都设置好了之后就可以使用VL53L1_StartMeasurement(pDev);来开启这个测距传感器的测量了!

传感器的校准

大家可以看到我初始化的时候和其他例程有一定的出入,在刚刚的代码中我并没有进行传感器的校准,因为阅读API手册后可以发现,校准函数在进行校准时是有校准条件的,一般都要求有一定的距离,校准面的颜色,和环境光的要求。如果每次都进行一次完全的校准的话,很有可能因为传感器校准的时候环境不够严格导致最终得到的数据不准确。因此我将校准函数和初始化函数进行了分离,只在模块完全部署好之后进行一次严格的校准然后保存这次结果,到时候每次启动的时候就录入这个结果就可以了。我的校准代码如下,仅包括默认校准和偏移校准,不包括串扰校准:

VL53L1_Error VL53Cali(VL53L1_Dev_t* pDev,void * save)
{
    VL53L1_Error Status = VL53L1_ERROR_NONE;
    Status = VL53L1_StopMeasurement(pDev);
	if(Status!=VL53L1_ERROR_NONE) 
		return Status;
    Status = VL53L1_PerformRefSpadManagement(pDev);//perform ref SPAD management
	if(Status!=VL53L1_ERROR_NONE) 
		return Status;
    
    Status = VL53L1_PerformOffsetSimpleCalibration(pDev,140);//14cm的出厂校验值
	if(Status!=VL53L1_ERROR_NONE) 
		return Status;
    
    Status = VL53L1_GetCalibrationData(pDev,save);
	if(Status!=VL53L1_ERROR_NONE) 
		return Status;
    //全部完成 重新打开测量
    Status = VL53L1_StartMeasurement(pDev);
    return Status;
}

该函数执行时要求离一个14cm的白色墙面,尽量在无光环境下执行,校准完成后得到的数据会存储到save变量中。以后启动的时候可以使用VL53L1_SetCalibrationData(save)函数来读取校准数据。

读取数据的函数

传感器开启测量后,我们就可以通过一系列的操作函数来完成测距的功能了,测距的具体流程如下

	VL53L1_RangingMeasurementData_t result_data;
	int32_t distance;
    status = VL53L1_WaitMeasurementDataReady(pDev);//等待测量就绪
    if(status!=VL53L1_ERROR_NONE) 
	{
		printf("Wait too long!\r\n");
		return status;
	}
    status = VL53L1_GetRangingMeasurementData(pDev, &result_data);//得到测量数据集
    distance = result_data.RangeMilliMeter;//从测量数据集中提取距离
    status = VL53L1_ClearInterruptAndStartMeasurement(pDev);//清除标志 等待下一次测量
    return status;

最终distance便是我们得到的测量距离(单位:mm)。同时result_data中有更全面的各种测量数据,如测量范围差,测量强度,可信度,错误号码等。如果发现测量得到的数据和真实数据出入较大,建议看看result_data中的错误码再进行代码的排查。

效果展示

下面是专门新建的一个简单例程,任意选择两个io口作为传感器接口,如图所示
在这里插入图片描述
使用自动生成的工程,只需要添加方框所示的代码即可得到距离值。
在这里插入图片描述
本例程也上传到了我的github

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VL53L1X移植到STM32实战记录,使用软件IIC(附源代码) 的相关文章

  • ubuntu配置USB权限

    usbcan设备在ubutu下使用 xff0c 每次必须动用root权限才能使用 xff0c 比较繁琐 参考如下文章进行配置 xff1a https blog csdn net bigdog 1027 article details 790
  • SocketCAN学习笔记

    1 对SocketCAN的理解 69条消息 对Socket CAN的理解 xff08 1 xff09 CAN总线原理 yuzeze的博客 CSDN博客 can socket 对Socket CAN的理解 xff08 2 xff09 Sock
  • Golang写Post请求并获取返回值

    直接上代码 xff0c 其中可以在下面代码中添加 package main import fmt net http io ioutil net url func main 需要post的数据 以key value形式提交 data 61 m
  • postMan 汉化

    1 下载postman解压安装 xff0c 下载地址Postman 2 下载汉化包 Release 9 2 0 hlmd Postman cn GitHub 选择postMan对应的版本 3 找到postman根目录我的在c盘 xff0c
  • 2022 小学组试题

    1 史密斯数 若一个合数的质因数分解式逐为位相加之和等于其本身逐位相加之和 则称这个数为smith数 如4937775 3 5 5 65837 而3 5 5 6 5 8 3 7 42 4 9 3 7 7 7 5 42 所以4937775是s
  • usaco 1 回文素数快速筛选

    求指定区间的回文素数 include lt bits stdc 43 43 h gt define N 10000010 using namespace std bool st N int cnt 61 0 primes N n m voi
  • C++ STL 学习笔记

    MAP的用法 xff1a 389找不同 给定两个字符串 s 和 t xff0c 它们只包含小写字母 字符串 t 由字符串 s 随机重排 xff0c 然后在随机位置添加一个字母 请找出在 t 中被添加的字母 示例 输入 xff1a s 61
  • 大模型平台

    大模型训练平台的算力急速增长 xff1a 据报道 xff0c GPT3 5 的训练使用了微软专门建设的 AI 计算系统 xff0c 由 1 万个 V100 GPU 组成的高性能网络集群 xff0c 总算力消耗约 3640 PF days 即
  • Float IP 浮动IP地址

    xfeff xfeff 就是多个主机工作在 同一个集群中 xff0c 即两台主机以上 每台机器除了自己的实IP外 xff0c 会设置一个浮动IP xff0c 浮动IP与主机的服务 xff08 HTTP服务 邮箱服务 xff09 绑在一起的
  • linux 下安装 c++编译器的方法

    xfeff xfeff 假设你的电脑能够访问internet xff0c 这个命令会自动从网络下载并把软件安装到本地 超级用户权限 xff1a yum y install gcc c 43 43 另外一定不要天真的认为linux 下面 编译
  • linux 内核编译错误的原因

    xfeff xfeff 直接编译centos 7 内核目录下的代码出现如下错误 xff1a root 64 localhost 3 10 0 123 el7 x86 64 make make 1 No rule to make target
  • ifconfig 看到Rx error overrun 如何解决

    xfeff xfeff 一台机器经常收到丢包的报警 xff0c 先看看最底层的有没有问题 ethtool em2 egrep 39 Speed Duplex 39 Speed 1000Mb s Duplex Full ethtool S e
  • AES-GCM算法

    AES GCM算法简介 AES GCM算法是带认证和加密的算法 xff0c 同时可以对给定的原文 xff0c 生成加密数据和认证码 参数如下 xff1a 1 xff09 带加密的原文 2 xff09 存储加密后密文 3 xff09 IV向量
  • cmake 编译c++项目

    分两步 xff1a CMakeLists txt文件编写结束以后就可以对工程进行编译了 xff0c 进入build目录 并执行cmake和make指令 xff0c 如下 xff1a 第一步 cmake span class token pu
  • sshd 无法启用的问题 Could not load host key: /etc/ssh/ssh_host_rsa_key Could not load host key: /etc/ssh/ss

    原文链接 xff1a http blog csdn net lynn kong article details 9112009 1 问题现象 版本 xff1a Grizzly master分支代码2013 06 17 部署 xff1a 三个
  • iptables nat

    NAT一般情况下分为SNAT xff0c DNAT和PNAT 此篇主要讲述的是使用iptables配置NAT xff0c 所以这3种NAT的区别和应用场景就简单的说明一下 SNAT xff1a 源地址转换 目标地址不变 xff0c 重新改写
  • Qt 的Cmake方式如何创建资源文件和添加类

    今天看到有人问Qt 的Cmake方式如何创建资源文件 xff0c 这个问题和添加类都是一样的 xff0c 也有朋友问如何添加类 xff0c 百度的回答是把cmake改成Qmake 这样等于没有回答 xff0c 根据自己的经验我在这里回答一下
  • ajax 请求头Authorization 添加账号密码访问

    在header中添加 34 Authorization 34 字段 xff0c 值为 34 api key api secret 34 进行base64加密后 在前面加入 34 Basic 34 Basic后有空格 字符串 最后形式为 34
  • Authorization—权限控制流程

    本篇是对Shiro体系架构的介绍 xff0c 本栏目大部分内容来自于Shiro官网 翻译过程中已经尽量保证用词的准确性和易懂性 xff0c 如有不准确或者不确切的地方 xff0c 请联系作者加以修改 本篇内容翻译自Authorization
  • C语言在头文件中用extern架起变量沟通的桥梁

    span class hljs comment a c span span class hljs keyword int span foo span class hljs keyword int span bar span class hl

随机推荐

  • 【C语言】5. 指针free后为什么要刻意指向NULL、野指针(原因、解决)、悬垂指针

    目录 1 指针free后为什么还要刻意指向NULL xff1f 2 野指针2 1 什么是野指针 xff1f 2 2 野指针形成的原因2 3 如何避免野指针 3 悬垂指针3 1 什么是悬垂指针 xff1f 3 2 示例代码3 3 解决方法 1
  • 【QT】UDP通信QUdpSocket(单播、广播、组播)

    目录 1 UDP通信概述2 UDP消息传送的三种模式3 QUdpSocket类的接口函数4 UDP单播和广播代码示例4 1 测试说明4 2 MainWindow h4 3 MainWindow cpp4 4 界面展示 5 UDP组播代码示例
  • Fiddler 调试HTTP工具,帮助Debug HTTP连接的免费工具

    Fiddler是一个C 实现的浏览器抓包和调试工具 xff0c fiddler启用后作为一个proxy存在于浏览器和服务器之间 xff0c 从中监测浏览器与服务器之间的http https级别的网络交互 目前可以支持各种主要浏览器如IE C
  • 对话框使用VIEW (转)

    现在的程序功能越来越复杂 xff0c 很多功能要求能在对话框中实现复杂的功能 xff0c 而在对话框中使用视图不像使用一些诸如静态控件 xff0c 编辑控件等那么方便 xff0c 下面文章用实例说明如何在对话框中使用视图 正文 http w
  • ubuntu系统下安装putty

    1 打开终端 xff0c 使用下面的命令来安装putty xff1a 1 1 sudo apt get update 1 2 sudo apt get install putty 上面两步成功则说明putty安装成功 2 接下来配置putt
  • 改变linux shell的输出效果

    文本终端的颜色可以使用 ANSI非常规字符序列 来生成 举例 xff1a echo e 34 033 44 37 5m ME 033 0m COOL 34 以上命令设置背景成为蓝色 xff0c 前景白色 xff0c 闪烁光标 xff0c 输
  • GNU ARM 汇编指令

    原文地址 http blog sina com cn s blog 59b189220100au1k html 第一部分 Linux下ARM汇编语法尽管在Linux下使用C或C 43 43 编写程序很方便 xff0c 但汇编源程序用于系统最
  • 什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决?

    什么是序列化 序列化 xff1a 把对象转换为字节序列的过程称为对象的序列化 反序列化 xff1a 把字节序列恢复为对象的过程称为对象的反序列化 怎么序列化 实现Serializable接口 xff0c 指定serialVersionUID
  • 寻迹小车笔记——红外对管(TCRT5000)原理

    一 概述 深色 xff08 黑色 xff09 的是发射端 xff0c 白色 xff08 透明 xff09 的是接收端 中间蓝色的是可以调节灵敏度的旋钮 TCRT5000光电传感器模块是基于TCRT5000红外光电传感器设计的一款红外反射式光
  • C语言判断一个数是否是水仙花数

    水仙花数是指一个N位正整数 xff08 N 3 xff09 xff0c 它的每个位上的数字的N次幂之和等于它本身 例如 xff1a 153 61 1 3 43 5 3 43 3 3 include lt stdio h gt int nar
  • C语言分类统计字符个数

    题目来源 xff1a 分类统计字符个数 PTA 本题要求实现一个函数 xff0c 统计给定字符串中英文字母 空格或回车 数字字符和其他字符的个数 函数接口定义 xff1a void StringCount char s 其中 char s
  • MIPS单周期CPU的设计——I型指令的设计

    一 一些概念 1 单周期CPU 指令周期 xff1a CPU从内存取出一条指令并执行这条指令的时间总和 CPU周期 xff1a 又称机器周期 xff0c CPU访问一次内存所花的时间较长 xff0c 因此用从内存读取一条指令字的最短时间来定
  • MIPS单周期CPU设计——lw和sw指令的设计

    1 lw xff0c sw指令格式及功能 指令 31 26 25 21 20 16 15 0 意义lw100011rsrtoffset从数存 xff08 数据存储器 xff09 中取数据写进寄存器sw101011rsrtoffset将寄存器
  • 计算机网络传输层概念及其协议

    一 概念 链路层保证的是点到点的可靠传输 xff0c 传输层保证端到端的可靠性 传输层是进程之间的通信 传输实体 xff1a 在收 发两端的传输层实现对等实体通信的硬件或软件 实现TCP协议的用户进程或者硬件称为TCP的传输实体 二 TCP
  • C++big three(构造函数、拷贝构造函数,拷贝赋值函数)

    一个类中只要带有指针类型的成员 xff0c 就必须自己写出big three xff08 构造函数 拷贝构造函数 xff0c 拷贝赋值函数 xff09 xff0c 如果没有指针类型的成员 xff0c 大部分情况下可以用默认的 字符串类是一个
  • 电网中DTU FTU RTU TTU的区别

    FTU xff08 Feeder Terminal Unit xff09 xff1a 馈线开关监控终端是装设在10KV断路器 负荷开关的开关监控装置 主要作用是采集各开关所在线路的电气参数 xff0c 并将这些信息向上级系统传输 xff1b
  • 他山之石可以攻玉

    计算之外的喜欢这一栏创建很久了 xff0c 但是一直没有内容 xff0c 目前勉强能够记录的大概就是我这一年里 xff08 2021 2022 xff09 读的书吧 人的一生很短暂 xff0c 也很宝贵 xff0c 能够在太平时节经历喜怒哀
  • 关于天干地支及其计算

    以天干地支计算日期是我国悠良的传统文化 xff0c 最近在看如何计算人的生辰八字 xff0c 写了个程序 xff0c 但是只能算年的干支 xff0c 月 日的干支计算方法太复杂了 xff0c 望之只能却步 xff0c 还是乖乖去查万年历比较
  • petalinux配置的系统启动出现cannot set terminal process group (-1): Inappropriate ioctl for device的问题解决小记

    配置好的系统在启动的时候出现cannot set terminal process group 1 Inappropriate ioctl for device 随后无法正常启动系统 经过判断后觉得是vivado生成的文件导入到petali
  • VL53L1X移植到STM32实战记录,使用软件IIC(附源代码)

    序言 VL53L1X是一个很小又很优秀的测距传感器 xff0c 它相比于上一代VL53L0X有着不小的提升 xff0c 这次毕业设计打算将这个传感器用起来 xff0c 就来移植了一下 xff0c 遇到的坑怎么说还是有一些 xff0c 故在此