找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 658|回复: 0
打印 上一主题 下一主题
收起左侧

基于arduino的VL53L0X驱动做的C51适配VL53L0X驱动

[复制链接]
跳转到指定楼层
楼主
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
人机交互的相关代码替换成自己的就行了
  1. #include"inc/VL53L0X.h"
复制代码

VL53L0X的驱动 VL53L0X.c

代码太多了只显示一部分,详情看附件,大家用的时候记得添加时基就行了。

  1. // Most of the functionality of this library is based on the VL53L0X API
  2. // provided by ST (STSW-IMG005), and some of the explanatory comments are quoted
  3. // or paraphrased from the API source code, API user manual (UM2039), and the
  4. // VL53L0X datasheet.

  5. #include "inc/VL53L0X.h"
  6. #include "inc/VL53L0X_IIC.h"
  7. #include "NodeHandler.h"
  8. #include <string.h>


  9. unsigned char stop_variable;
  10. unsigned long measurement_timing_budget_us;
  11. unsigned int io_timeout = 0, timeout_start_ms, t2;
  12. bit did_timeout;


  13. //===================================
  14. //你自己的定时器时基定时1ms
  15. void Time2() interrupt 12
  16. {
  17.         t2++;
  18. }
  19. //==================================================


  20. // Defines /////////////////////////////////////////////////////////////////////

  21. // The Arduino two-wire interface uses a 7-bit number for the address,
  22. // and sets the last bit correctly based on reads and writes
  23. #define ADDRESS_DEFAULT 0x52

  24. // Record the current time to check an upcoming timeout against
  25. #define startTimeout() (timeout_start_ms = t2)

  26. // Check if timeout is enabled (set to nonzero value) and has expired
  27. #define checkTimeoutExpired() (io_timeout > 0 && ((unsigned  int)t2 - timeout_start_ms) > io_timeout)

  28. // Decode VCSEL (vertical cavity surface emitting laser) pulse period in PCLKs
  29. // from register value
  30. // based on VL53L0X_decode_vcsel_period()
  31. #define decodeVcselPeriod(reg_val)      (((reg_val) + 1) << 1)

  32. // Encode VCSEL pulse period register value from period in PCLKs
  33. // based on VL53L0X_encode_vcsel_period()
  34. #define encodeVcselPeriod(period_pclks) (((period_pclks) >> 1) - 1)
复制代码

IIC驱动
有人喜欢模拟IIC,有人喜欢硬件IIC,他们各有各的优点,大家按照自己的喜好替换调我的IIC驱动就行了
  1. #define VL53L0X_address                         0x52

  2. //IIC写8位数据
  3. void VL53L0X_Write(unsigned char address, unsigned char value)
  4. {
  5.         P_SW2 = 0xB0;
  6.         Start();
  7.         SendData(VL53L0X_address);
  8.         RecvACK();
  9.         SendData(address);
  10.         RecvACK();
  11.         SendData(value);
  12.         RecvACK();
  13.         Stop();
  14.         Delay();
  15.         P_SW2 = 0x00;
  16. }

  17. //IIC写16位数据
  18. void VL53L0X_Write16Bit(unsigned char address, unsigned int value)
  19. {
  20.         P_SW2 = 0xB0;
  21.         VL53L0X_Write(address++, (value >> 8) & 0xFF);
  22.         VL53L0X_Write(address++, value & 0xFF);
  23.         P_SW2 = 0x00;
  24. }

  25. //IIC写32位数据
  26. //void VL53L0X_Write32Bit(unsigned char address, unsigned long value)
  27. //{
  28. //        Start();
  29. //        SendData(VL53L0X_address);
  30. //        RecvACK();
  31. //        SendData(address);
  32. //        RecvACK();
  33. //        SendData((value >> 24) & 0xFF);
  34. //        RecvACK();
  35. //        SendData((value >> 16) & 0xFF);
  36. //        RecvACK();
  37. //        SendData((value >> 8) & 0xFF);
  38. //        RecvACK();
  39. //        SendData(value & 0xFF);
  40. //        RecvACK();
  41. //        Stop();
  42. //         Delay();
  43. //}

  44. //写多位数据
  45. void VL53L0X_WriteMulti(unsigned char address, unsigned char const * src, unsigned char count)
  46. {
  47.         P_SW2 = 0xB0;        
  48.         while(count--)
  49.         {
  50.                 VL53L0X_Write(address++, *(src++));
  51.         }
  52.         P_SW2 = 0x00;
  53. }

  54. //IIC读8位数据
  55. unsigned char VL53L0X_Read(unsigned char address)
  56. {
  57.         unsigned char receive;
  58.         P_SW2 = 0xB0;
  59.         Start();
  60.         SendData(VL53L0X_address);
  61.         RecvACK();
  62.         SendData(address);
  63.         RecvACK();
  64.         
  65.         Start();
  66.         SendData(VL53L0X_address + 1);
  67.         RecvACK();
  68.         receive = RecvData();
  69.         SendNAK();
  70.         Stop();
  71.         Delay();
  72.         P_SW2 = 0x00;
  73.         
  74.         return receive;
  75. }

  76. //IIC读16位数据
  77. unsigned int VL53L0X_Read16Bit(unsigned char address)
  78. {
  79.         unsigned int receive;
  80.         P_SW2 = 0xB0;
  81.         receive = VL53L0X_Read(address++) << 8;
  82.         receive |= VL53L0X_Read(address);
  83.         P_SW2 = 0x00;
  84.         
  85.         return receive;
  86. }

  87. //IIC读多位数据
  88. void VL53L0X_ReadMulti(unsigned char address, unsigned char * dst, unsigned char count)
  89. {
  90.         while(count--)
  91.         {
  92.                 *(dst++) = VL53L0X_Read(address++);
  93.         }
  94.         P_SW2 = 0x00;
  95. }
复制代码

3.其他
说一个我的IIC编程遇到的问题,我在IIC连续读SDA的数据的时候会存在有时读到的数据不稳定的情况
连续读的时候,如下读两个字节
  1. //IIC读16位数据
  2. unsigned int VL53L0X_Read16Bit(unsigned char address)
  3. {
  4.         unsigned int receive;
  5.         IICStart();
  6.         IICSendData(VL53L0X_address);
  7.         IICWaitACK();
  8.         IICSendData(address);
  9.         IICWaitACK();
  10.         IICStop();
  11.         
  12.         IICStart();
  13.         IICSendData(VL53L0X_address + 1);
  14.         IICWaitACK();
复制代码
VL53L0X的内部寄存器索引会在读完一个寄存器后自加1,索引加1后读下一个寄存器的数据。
那么如果这个自加1的索引自加的速度跟不上你IIC读取的速度呢。
这样IIC读取的数据就会不可靠。
连续读两个字节,我修改成连续两次读一个字节后,数据的读取就稳定许多了

  1. //IIC读16位数据
  2. unsigned int VL53L0X_Read16Bit(unsigned char address)
  3. {
  4.         unsigned int receive;
  5.         P_SW2 = 0xB0;
  6.         receive = VL53L0X_Read(address++) << 8;     //两个字节分两次读取
  7.         receive |= VL53L0X_Read(address);
  8.         P_SW2 = 0x00;
  9.         
  10.         return receive;
  11. }
复制代码
或者大家有更好的见解也可以告诉我,毕竟我也是刚刚开始研究IIC,对IIC的认识也可能有错误(说不定我的程序就是建立在BUG上的

4.结果





5.工程源码及附件
MRC048A-GY-VL53L0XV2 资料.rar (696.82 KB, 下载次数: 5)

VL53L0X -硬件IIC(发帖).rar (210.5 KB, 下载次数: 4)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表