1.简介
在研究了各位大神的代码后,结合购买模块时商家提供的arduino的VL53L0X驱动,我修改ardiuno的驱动写出了兼容C51的VL53L0X驱动。我的测试的单片机是STC8H3K64S4,IIC通信使用的时STC硬件的IIC。大家只需要把我的IIC驱动和显示代码修改成自己的,最后添加一个定时1ms的定时器作为VL53L0X的时基,就可以直接拿来用了。
这是本人第一次发帖,做的工作也比较简单,如果有什么做的不好的还请谅解。
参考的网站:
http://www.51hei.com/bbs/dpj-167298-1.html
使用上面网站的代码写出来的程序,这个代码只有最基本的测距功能,测距误差大概在±5%。对我刚刚接触VL53L0X时启发很大。
在使用商家提供的arduino的VL53L0X驱动后,由于设置了VL53L0X的相关寄存器,精度可以达到±1%。当然超过模块的1.2m的测距范围精度还是会差很多。
2.上代码
主函数 main.c
人机交互的相关代码替换成自己的就行了
VL53L0X的驱动 VL53L0X.c
代码太多了只显示一部分,详情看附件,大家用的时候记得添加时基就行了。
- // Most of the functionality of this library is based on the VL53L0X API
- // provided by ST (STSW-IMG005), and some of the explanatory comments are quoted
- // or paraphrased from the API source code, API user manual (UM2039), and the
- // VL53L0X datasheet.
- #include "inc/VL53L0X.h"
- #include "inc/VL53L0X_IIC.h"
- #include "NodeHandler.h"
- #include <string.h>
- unsigned char stop_variable;
- unsigned long measurement_timing_budget_us;
- unsigned int io_timeout = 0, timeout_start_ms, t2;
- bit did_timeout;
- //===================================
- //你自己的定时器时基定时1ms
- void Time2() interrupt 12
- {
- t2++;
- }
- //==================================================
- // Defines /////////////////////////////////////////////////////////////////////
- // The Arduino two-wire interface uses a 7-bit number for the address,
- // and sets the last bit correctly based on reads and writes
- #define ADDRESS_DEFAULT 0x52
- // Record the current time to check an upcoming timeout against
- #define startTimeout() (timeout_start_ms = t2)
- // Check if timeout is enabled (set to nonzero value) and has expired
- #define checkTimeoutExpired() (io_timeout > 0 && ((unsigned int)t2 - timeout_start_ms) > io_timeout)
- // Decode VCSEL (vertical cavity surface emitting laser) pulse period in PCLKs
- // from register value
- // based on VL53L0X_decode_vcsel_period()
- #define decodeVcselPeriod(reg_val) (((reg_val) + 1) << 1)
- // Encode VCSEL pulse period register value from period in PCLKs
- // based on VL53L0X_encode_vcsel_period()
- #define encodeVcselPeriod(period_pclks) (((period_pclks) >> 1) - 1)
复制代码
IIC驱动
有人喜欢模拟IIC,有人喜欢硬件IIC,他们各有各的优点,大家按照自己的喜好替换调我的IIC驱动就行了
- #define VL53L0X_address 0x52
- //IIC写8位数据
- void VL53L0X_Write(unsigned char address, unsigned char value)
- {
- P_SW2 = 0xB0;
- Start();
- SendData(VL53L0X_address);
- RecvACK();
- SendData(address);
- RecvACK();
- SendData(value);
- RecvACK();
- Stop();
- Delay();
- P_SW2 = 0x00;
- }
- //IIC写16位数据
- void VL53L0X_Write16Bit(unsigned char address, unsigned int value)
- {
- P_SW2 = 0xB0;
- VL53L0X_Write(address++, (value >> 8) & 0xFF);
- VL53L0X_Write(address++, value & 0xFF);
- P_SW2 = 0x00;
- }
- //IIC写32位数据
- //void VL53L0X_Write32Bit(unsigned char address, unsigned long value)
- //{
- // Start();
- // SendData(VL53L0X_address);
- // RecvACK();
- // SendData(address);
- // RecvACK();
- // SendData((value >> 24) & 0xFF);
- // RecvACK();
- // SendData((value >> 16) & 0xFF);
- // RecvACK();
- // SendData((value >> 8) & 0xFF);
- // RecvACK();
- // SendData(value & 0xFF);
- // RecvACK();
- // Stop();
- // Delay();
- //}
- //写多位数据
- void VL53L0X_WriteMulti(unsigned char address, unsigned char const * src, unsigned char count)
- {
- P_SW2 = 0xB0;
- while(count--)
- {
- VL53L0X_Write(address++, *(src++));
- }
- P_SW2 = 0x00;
- }
- //IIC读8位数据
- unsigned char VL53L0X_Read(unsigned char address)
- {
- unsigned char receive;
- P_SW2 = 0xB0;
- Start();
- SendData(VL53L0X_address);
- RecvACK();
- SendData(address);
- RecvACK();
-
- Start();
- SendData(VL53L0X_address + 1);
- RecvACK();
- receive = RecvData();
- SendNAK();
- Stop();
- Delay();
- P_SW2 = 0x00;
-
- return receive;
- }
- //IIC读16位数据
- unsigned int VL53L0X_Read16Bit(unsigned char address)
- {
- unsigned int receive;
- P_SW2 = 0xB0;
- receive = VL53L0X_Read(address++) << 8;
- receive |= VL53L0X_Read(address);
- P_SW2 = 0x00;
-
- return receive;
- }
- //IIC读多位数据
- void VL53L0X_ReadMulti(unsigned char address, unsigned char * dst, unsigned char count)
- {
- while(count--)
- {
- *(dst++) = VL53L0X_Read(address++);
- }
- P_SW2 = 0x00;
- }
复制代码
3.其他
说一个我的IIC编程遇到的问题,我在IIC连续读SDA的数据的时候会存在有时读到的数据不稳定的情况
连续读的时候,如下读两个字节
- //IIC读16位数据
- unsigned int VL53L0X_Read16Bit(unsigned char address)
- {
- unsigned int receive;
- IICStart();
- IICSendData(VL53L0X_address);
- IICWaitACK();
- IICSendData(address);
- IICWaitACK();
- IICStop();
-
- IICStart();
- IICSendData(VL53L0X_address + 1);
- IICWaitACK();
复制代码 VL53L0X的内部寄存器索引会在读完一个寄存器后自加1,索引加1后读下一个寄存器的数据。
那么如果这个自加1的索引自加的速度跟不上你IIC读取的速度呢。
这样IIC读取的数据就会不可靠。
连续读两个字节,我修改成连续两次读一个字节后,数据的读取就稳定许多了
- //IIC读16位数据
- unsigned int VL53L0X_Read16Bit(unsigned char address)
- {
- unsigned int receive;
- P_SW2 = 0xB0;
- receive = VL53L0X_Read(address++) << 8; //两个字节分两次读取
- receive |= VL53L0X_Read(address);
- P_SW2 = 0x00;
-
- return receive;
- }
复制代码 或者大家有更好的见解也可以告诉我,毕竟我也是刚刚开始研究IIC,对IIC的认识也可能有错误(说不定我的程序就是建立在BUG上的 )
4.结果
5.工程源码及附件
MRC048A-GY-VL53L0XV2 资料.rar
(696.82 KB, 下载次数: 5)
|