标题: VL53L0X激光测距模块的单片机驱动程序 [打印本页]

作者: xoxojojo    时间: 2019-8-1 14:22
标题: VL53L0X激光测距模块的单片机驱动程序
自己做的激光测距VL53L0X程序,拿出来和大家分享。这程序里面没有加显示设备,因为不知道大家要使用什么来显示,所以请根据个人情况来进行修改添加,但是附件里面的程序是我加上OLED后的程序
各位请按需使用。

单片机源程序如下:
  1. #include <REGX51.H>
  2. #include "intrins.h"
  3. #define uchar unsigned char
  4. #define uint unsigned int

  5. #define VL53L0X_REG_IDENTIFICATION_MODEL_ID         0xc0
  6. #define VL53L0X_REG_IDENTIFICATION_REVISION_ID      0xc2
  7. #define VL53L0X_REG_PRE_RANGE_CONFIG_VCSEL_PERIOD   0x50
  8. #define VL53L0X_REG_FINAL_RANGE_CONFIG_VCSEL_PERIOD 0x70
  9. #define VL53L0X_REG_SYSRANGE_START                  0x00
  10. #define VL53L0X_REG_RESULT_INTERRUPT_STATUS         0x13
  11. #define VL53L0X_REG_RESULT_RANGE_STATUS             0x14
  12. #define address 0x52

  13. sbit I2C_SCL = P1^3;
  14. sbit I2C_SDA = P1^2;


  15. void I2C_Delay10us();
  16. void I2C_Start();
  17. void I2C_Stop();
  18. uchar I2C_SendByte(uchar dat);
  19. uchar I2C_ReadByte();
  20. //void I2C_SendACK(bit ack);
  21. void vl53l0x_send(uchar reg,uchar dat);
  22. uchar vl53l0x_read(uchar reg);
  23. short makeuint16(int lsb, int msb);

  24. uchar gbuf[16];
  25. uint acnt ;
  26. uint scnt;
  27. uint dist ;
  28. uchar DeviceRangeStatusInternal;

  29. /*******************************************************************************
  30. * 函 数 名         : Delay1ms()                //@11.0592MHz
  31. * 函数功能                     : 延时
  32. * 输    入         : 无
  33. * 输    出         : 无
  34. *******************************************************************************/
  35. void Delay1ms()                //@11.0592MHz
  36. {
  37.     unsigned char i, j;

  38.     _nop_();
  39.     i = 11;
  40.     j = 190;
  41.     do
  42.     {
  43.         while (--j);
  44.     } while (--i);
  45. }
  46. /*******************************************************************************
  47. * 函 数 名         : delay_ms(unsigned int time)
  48. * 函数功能                     : 延时
  49. * 输    入         : time
  50. * 输    出         : 无
  51. *******************************************************************************/
  52. void delay_ms(unsigned int time)
  53. {
  54.     unsigned char
  55.     i;
  56.     for(i=1; i<=time; i++)
  57.         Delay1ms();
  58. }
  59. /*******************************************************************************
  60. * 函 数 名         : Delay1us()
  61. * 函数功能                   : 延时
  62. * 输    入         : 无
  63. * 输    出         : 无
  64. *******************************************************************************/
  65. void I2C_Delay10us()
  66. {
  67.     unsigned char i;

  68.     _nop_();
  69.     _nop_();
  70.     _nop_();
  71.     i = 24;
  72.     while (--i);
  73. }
  74. /*******************************************************************************
  75. * 函 数 名         : I2C_Start()
  76. * 函数功能                   : 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
  77. * 输    入         : 无
  78. * 输    出         : 无
  79. * 备    注         : 起始之后I2C_SDA和I2C_SCL都为0
  80. *******************************************************************************/
  81. void I2C_Start()
  82. {
  83.     I2C_SDA = 1;
  84.     I2C_Delay10us();
  85.     I2C_SCL = 1;
  86.     I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
  87.     I2C_SDA = 0;
  88.     I2C_Delay10us();//保持时间是>4us
  89.     I2C_SCL = 0;
  90.     I2C_Delay10us();
  91. }
  92. /*******************************************************************************
  93. * 函 数 名           : I2C_Stop()
  94. * 函数功能                 : 终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
  95. * 输    入           : 无
  96. * 输    出                  : 无
  97. * 备    注           : 结束之后保持I2C_SDA和I2C_SCL都为1;表示总线空闲
  98. *******************************************************************************/
  99. void I2C_Stop()
  100. {
  101.     I2C_SDA = 0;
  102.     I2C_Delay10us();
  103.     I2C_SCL = 1;
  104.     I2C_Delay10us();//建立时间大于4.7us
  105.     I2C_SDA = 1;
  106.     I2C_Delay10us();
  107. }
  108. /*******************************************************************************
  109. * 函 数 名           : I2cSendByte(uchar num)
  110. * 函数功能                  : 通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,
  111. *                    * 保持发送信号I2C_SDA保持稳定
  112. * 输    入           : num ,ack
  113. * 输    出                  : 0或1。发送成功返回1,发送失败返回0
  114. * 备    注           : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0
  115. *******************************************************************************/
  116. uchar I2C_SendByte(uchar dat)
  117. {
  118.     uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。

  119.     for(a=0; a<8; a++)//要发送8位,从最高位开始
  120.     {
  121.         dat <<= 1;
  122.         I2C_SDA=CY;
  123.         I2C_Delay10us();
  124.         I2C_SCL = 1;
  125.         I2C_Delay10us();//建立时间>4.7us
  126.         I2C_SCL = 0;
  127.         I2C_Delay10us();//时间大于4us
  128.     }

  129.     //I2C_SDA = 1;
  130.     //I2C_Delay10us();
  131.     I2C_SCL = 1;
  132.     I2C_Delay10us();
  133.     CY=I2C_SDA;
  134.     I2C_SCL = 0;
  135.     I2C_Delay10us();
  136.     return CY;
  137. }
  138. /*******************************************************************************
  139. * 函 数 名           : I2cReadByte()
  140. * 函数功能                     : 使用I2c读取一个字节
  141. * 输    入           : 无
  142. * 输    出                  : dat
  143. * 备    注           : 接收完一个字节I2C_SCL=0
  144. *******************************************************************************/
  145. uchar I2C_ReadByte()
  146. {
  147.     uchar a = 0,dat = 0;
  148.     I2C_SDA = 1;                        //起始和发送一个字节之后I2C_SCL都是0
  149.     I2C_Delay10us();
  150.     for(a=0; a<8; a++)//接收8个字节
  151.     {
  152.         I2C_SCL = 1;
  153.         I2C_Delay10us();
  154.         dat <<= 1;
  155.         dat |= I2C_SDA;
  156.         I2C_Delay10us();
  157.         I2C_SCL = 0;
  158.         I2C_Delay10us();
  159.     }
  160.     return dat;
  161. }
  162. /*******************************************************************************
  163. * 函 数 名           : vl53l0x_send(uchar reg,uchar dat)
  164. * 函数功能                     : 使用I2c向vl530xl发送命令
  165. * 输    入           : reg,dat
  166. * 输    出                  : 无
  167. *******************************************************************************/
  168. void vl53l0x_send(uchar reg,uchar dat)
  169. {
  170.     I2C_Start();
  171.     I2C_SendByte(address);
  172.     I2C_SendByte(reg);
  173.     I2C_SendByte(dat);
  174.     I2C_Stop();
  175. }
  176. /*******************************************************************************
  177. * 函 数 名           : vl53l0x_read(uchar reg)
  178. * 函数功能                     : 使用I2c向vl530x0l读取一个字节
  179. * 输    入           : reg
  180. * 输    出                  : num
  181. *******************************************************************************/
  182. uchar vl53l0x_read(uchar reg)
  183. {
  184.     unsigned char num;
  185.     I2C_Start();
  186.     I2C_SendByte(address); //发送写器件地址
  187.     I2C_SendByte(reg); //发送要读取的地址
  188.                 I2C_Stop();
  189.     I2C_Start();
  190.     I2C_SendByte(address+1); //发送读器件地址
  191.     num=I2C_ReadByte(); //读取数据
  192.     I2C_Stop();
  193.     return num;
  194. }
  195. /*******************************************************************************
  196. * 函 数 名           :  makeuint16(int lsb, int msb)
  197. * 函数功能                       :  将读出数据转换到数组当中
  198. * 输    入           : lsb,msb
  199. * 输    出                  : dat
  200. *******************************************************************************/
  201. short makeuint16(int lsb, int msb)
  202. {
  203.     return ((msb & 0xFF) << 8) | (lsb & 0xFF);
  204. }
  205. /*******************************************************************************
  206. * 函 数 名           :  date()
  207. * 函数功能                       :  进行数据的读取与转换,将数据处理
  208. * 输    入           : 无
  209. * 输    出                  : dist
  210. *******************************************************************************/
  211. unsigned char date()
  212. {
  213.         uchar val = 0;        
  214. //        uchar vall;
  215.         int cnt = 0;
  216.                         vl53l0x_send(VL53L0X_REG_SYSRANGE_START, 0x01);
  217.                 while (cnt < 100)                                      ///检测数据是否传输正常
  218.                 {
  219.       delay_ms(10);
  220.       val = vl53l0x_read(VL53L0X_REG_RESULT_RANGE_STATUS);
  221.       if (val & 0x01) break;
  222.       cnt++;
  223.     }
  224.                  gbuf[0]=vl53l0x_read(0x14);
  225.                  gbuf[7]=vl53l0x_read(0x14+7);
  226.                  gbuf[6]=vl53l0x_read(0x14+6);
  227.                  gbuf[9]=vl53l0x_read(0x14+9);
  228.                  gbuf[8]=vl53l0x_read(0x14+8);
  229.                  gbuf[11]=vl53l0x_read(0x14+11);
  230.                  gbuf[10]=vl53l0x_read(0x14+10);
  231.      acnt = makeuint16(gbuf[7], gbuf[6]);
  232.      scnt = makeuint16(gbuf[9], gbuf[8]);                 
  233.      dist = makeuint16(gbuf[11], gbuf[10]);                 
  234. //                 DeviceRangeStatusInternal = ((gbuf[0] & 0x78) >> 3);
  235. //                         if(DeviceRangeStatusInternal==11&&dist>20&&dist<1200)
  236. //                        {
  237. //                                vall=dist/10000;
  238. //                    OLED_dan(8*0,0,vall+16);
  239. //                    vall=dist%10000/1000;
  240. //                    OLED_dan(8*1,0,vall+16);
  241. //                    vall=dist%1000/100;
  242. //                    OLED_dan(8*2,0,vall+16);
  243. //                    vall=dist%100/10;
  244. //                    OLED_dan(8*3,0,vall+16);
  245. //                    vall=dist%10/1;
  246. //                    OLED_dan(8*4,0,vall+16);
  247. //                        }
  248.                         return  dist;             //该数组为五位
  249. }
  250. void main()
  251. {

  252.         while(1)
  253.         {
  254.     date();
  255.         }
  256. }
复制代码
全部资料51hei下载地址:
VL530X0L激光测距.zip (108.48 KB, 下载次数: 621)

作者: zhpic    时间: 2019-8-5 17:51
不错,正好要用到这个测距。
作者: 腾飞的龙    时间: 2019-8-30 13:47
好资料,感谢分享!!!!!!!
作者: beyondpzy    时间: 2019-12-4 16:02
很好,正在学习中。谢谢分享!
作者: 1091647965    时间: 2019-12-17 22:47
感谢分享
作者: hc201909    时间: 2019-12-22 15:32
里面的   CY   是什么意思呢,也没见在那个地方定义了
作者: hc201909    时间: 2019-12-23 11:23
zhpic 发表于 2019-8-5 17:51
不错,正好要用到这个测距。

我直接编译怎么一直出错呢
作者: lazybonesyang    时间: 2021-3-2 10:29
也想用类似51的程序,但里面的寄存器定义哪份文件看得到?
作者: xiexugang    时间: 2021-3-8 02:05
这个很好,激光测距很实用
作者: baishifanzon    时间: 2021-3-24 01:17
好好学习一下,感谢楼主无私的分享
作者: 201909zc    时间: 2021-7-27 11:14
你好,里面的YC是什么意思呢
作者: 11112223354    时间: 2021-8-2 16:27
测出来的数据是哪一个
作者: 冯666    时间: 2021-8-15 19:28
这个程序里面用的显示模块是12864吗

作者: 冯666    时间: 2021-8-15 19:29
11112223354 发表于 2021-8-2 16:27
测出来的数据是哪一个

您好,请问显示模块您用的是哪一个
作者: 冯666    时间: 2021-8-15 19:37
hc201909 发表于 2019-12-23 11:23
我直接编译怎么一直出错呢

您好,请问,这个显示模块用的是哪个?
作者: at366    时间: 2021-10-7 14:16
谢谢分享。要改一下CY
作者: 1212101    时间: 2022-2-15 16:00
666.我也正好需要参考一下
作者: 1212101    时间: 2022-3-24 22:25
CY是什么意思呀
作者: ccnnzz315    时间: 2023-8-2 08:01
201909zc 发表于 2021-7-27 11:14
你好,里面的YC是什么意思呢

它是PSW状态寄存器里面的高位进位标志位。你写的这个应该是IIC总线协议里面的。SDA是数据标志位,CY每次溢出的数据都付给它,一共写8次。
作者: wkman    时间: 2023-8-2 15:36
VL53L0X  这激光测距,在范围内,重复精度大概多少?
作者: goalpeak    时间: 2023-8-19 11:14
某一个宝买了个模组回来,写了代码测试了下,大概在3-4MM误差,反应速度还可以,有兴趣大家可以一起交流下。
另外代码里有几个小问题:
1.CY很多朋友不知道,是单片机状态寄存器的进位标志位,各位对应换成自己单片机对应的进位标志位即可。
2.有的单片机的I/O输入输出需要自己切换,实例代码里面的读取函数,没有该方面的说明,自己用的时候需要自己手动切换SDA为输入,再读取数据。
作者: william_wangxb    时间: 2023-10-11 20:30
goalpeak 发表于 2023-8-19 11:14
某一个宝买了个模组回来,写了代码测试了下,大概在3-4MM误差,反应速度还可以,有兴趣大家可以一起交流下 ...

能不能分享一下资料,最近准备搞个测试角度案子,打算用到激光模块测距,苦于没有相关资料
作者: ZIXUYOU    时间: 2023-12-20 19:38
baishifanzon 发表于 2021-3-24 01:17
好好学习一下,感谢楼主无私的分享

请问你有没有基于51的这个测距模块的代码文件呢??
作者: ZIXUYOU    时间: 2023-12-20 19:39
goalpeak 发表于 2023-8-19 11:14
某一个宝买了个模组回来,写了代码测试了下,大概在3-4MM误差,反应速度还可以,有兴趣大家可以一起交流下 ...

大佬,可以分享一下资料吗?
作者: huangshaoliang    时间: 2024-3-15 09:03
goalpeak 发表于 2023-8-19 11:14
某一个宝买了个模组回来,写了代码测试了下,大概在3-4MM误差,反应速度还可以,有兴趣大家可以一起交流下 ...

代码能不能分享下
作者: wkman    时间: 2024-3-15 14:27
goalpeak 发表于 2023-8-19 11:14
某一个宝买了个模组回来,写了代码测试了下,大概在3-4MM误差,反应速度还可以,有兴趣大家可以一起交流下 ...

误差是针对金属、木板类硬质类材料的吧,,,针对液体类,精度会变化多大???
作者: cr8526    时间: 2024-3-16 23:07
做出的产品如何使用??
作者: wkman    时间: 2024-10-9 16:22
tb上有好多卖的,,,还没下手测一下
作者: LIULIU0000    时间: 2024-10-14 19:56
请问,这个调长距离,高精度,高速的这三个模式的寄存器是什么呀?
作者: william_wangxb    时间: 2025-2-19 14:21
william_wangxb 发表于 2023-10-11 20:30
能不能分享一下资料,最近准备搞个测试角度案子,打算用到激光模块测距,苦于没有相关资料

我也是准备做个测试角度的小玩意,兄弟,有资料和例程的话分享下,谢谢
作者: wkman    时间: 2025-2-24 07:52
  重复精度,和材质有关吧?
作者: 源流    时间: 2025-4-21 18:08
我有点不懂,测量到40以下就不会测量到数据,要怎么弄才能测到0-1000,而不是40-1000
作者: qixi6793    时间: 2025-6-18 17:04
使用RTX51操作系统时 与delay不会有冲突吧
作者: qixi6793    时间: 2025-6-20 17:41
[17:23:55.269]接收←val = 0x00005f00
                    [状态码:2817] 距离:8960mm | 信号强度:52993 | 原始值:0x2323
                    
[17:23:56.373]接收←val = 0x00005f01
                    [状态码:2816] 距离:27392mm | 信号强度:2304 | 原始值:0x6B23
                    
[17:23:57.465]接收←val = 0x00005f00
                    [状态码:2816] 距离:53760mm | 信号强度:40704 | 原始值:0xD223
                    
[17:23:58.576]接收←val = 0x00004f00
                    [状态码:2335] 距离:65025mm | 信号强度:5151 | 原始值:0xFE23
我这测量的数据太离谱了




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1