热门标签 | HotTags
当前位置:  开发笔记 > 程序员 > 正文

STM32F4+VL530L0x激光测距cubemx实现

STM32F4VL53L0激光测距cubemx实现前言一、STM32cubemx配置a.配置RCCb.配置SYSc.配置VL530使能口d.时钟线配置二、STM32F4keil配置


STM32F4+VL53L0激光测距cubemx实现

  • 前言
  • 一、STM32cubemx配置
    • a.配置RCC
    • b.配置SYS
    • c.配置VL530使能口
    • d.时钟线配置
  • 二、STM32F4 keil配置
    • 1.引入库
      • a.引入IIC口配置
      • b.引入VL530底层配置
    • 2.读取数据
      • a.初始化配置
      • b.获取数据
      • c.结果展示
    • 3.总结
  • 三.程序下载链接


前言

提示:本程序测试主控使用STM32F427VGT6系列单片机,使用cubemx作为开发工具,串口波特率为115200,使用VL530L0模块,使用IIC通信,可移植到相关STM32F4型号单片机上




一、STM32cubemx配置


a.配置RCC

RCC设置,选择HSE(外部高速时钟)为Crystal/Ceramic Resonator(晶振/陶瓷谐振器)

在这里插入图片描述


b.配置SYS


##c, 配置USART
这里使用串口1,波特率设为115200,开启中断,用于接收VL530的数据
在这里插入图片描述
在这里插入图片描述


c.配置VL530使能口

这里使用PB8,PB9作为SDA,SCL配置口,这里设为输出模式,电平拉高

在这里插入图片描述


d.时钟线配置

配置系统目录为180M最高速度,只用调节SYSCLK其它即可自动配置,时钟配置不同型号单片机可能不同,这里我设置为180MHZ
在这里插入图片描述


二、STM32F4 keil配置


1.引入库


a.引入IIC口配置

myiic.c配置

#include "myiic.h"
#include "delay.h"
//初始化IIC
void IIC_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;IIC_SCL=1;IIC_SDA=1;
}
//产生IIC起始信号
void IIC_Start(void)
{SDA_OUT(); //sda线输出IIC_SDA=1; IIC_SCL=1;delay_us(4);IIC_SDA=0;//START:when CLK is high,DATA change form high to low delay_us(4);IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void IIC_Stop(void)
{SDA_OUT();//sda线输出IIC_SCL=0;IIC_SDA=0;//STOP:when CLK is high DATA change form low to highdelay_us(4);IIC_SCL=1; IIC_SDA=1;//发送I2C总线结束信号delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{u8 ucErrTime=0;SDA_IN(); //SDA设置为输入 IIC_SDA=1;delay_us(1); IIC_SCL=1;delay_us(1); while(READ_SDA){ucErrTime++;if(ucErrTime>250){IIC_Stop();return 1;}}IIC_SCL=0;//时钟输出0 return 0;
}
//产生ACK应答
void IIC_Ack(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=0;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//不产生ACK应答
void IIC_NAck(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=1;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{ u8 t; SDA_OUT(); IIC_SCL=0;//拉低时钟开始数据传输for(t=0;t<8;t++){ IIC_SDA=(txd&0x80)>>7;txd<<=1; delay_us(2); //对TEA5767这三个延时都是必须的IIC_SCL=1;delay_us(2); IIC_SCL=0; delay_us(2);}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA_IN();//SDA设置为输入for(i=0;i<8;i++ ){IIC_SCL=0; delay_us(2);IIC_SCL=1;receive<<=1;if(READ_SDA)receive++; delay_us(1); } if (!ack)IIC_NAck();//发送nACKelseIIC_Ack(); //发送ACK return receive;
}

myiic.h配置

#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"
#include "stdio.h"
#include "main.h"
#include "string.h"
#include "sys.h"
//IO方向设置
#define SDA_IN() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=0<<9*2;} //PB9输入模式
#define SDA_OUT() {GPIOB->MODER&=~(3<<(9*2));GPIOB->MODER|=1<<9*2;} //PB9输出模式
//IO操作函数
#define IIC_SCL PBout(8) //SCL
#define IIC_SDA PBout(9) //SDA
#define READ_SDA PBin(9) //输入SDA //IIC所有操作函数
void IIC_Init(void); //初始化IIC的IO口
void IIC_Start(void); //发送IIC开始信号
void IIC_Stop(void); //发送IIC停止信号
void IIC_Send_Byte(u8 txd); //IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); //IIC等待ACK信号
void IIC_Ack(void); //IIC发送ACK信号
void IIC_NAck(void); //IIC不发送ACK信号void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);
#endif

b.引入VL530底层配置

VL530L0.c配置:

#include "VL53L0.h"
#include "myiic.h"
uint16_t bswap(u8 b[])
{uint16_t val = ((b[0]<< 8) & b[1]);return val;
}uint16_t VL53L0X_decode_vcsel_period(short vcsel_period_reg)
{uint16_t vcsel_period_pclks = (vcsel_period_reg + 1) <<1;return vcsel_period_pclks;
}uint16_t makeuint16(int lsb, int msb)
{return ((msb & 0xFF) << 8) | (lsb & 0xFF);
}//IIC连续写
//addr:器件地址
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
// 其他,错误代码
u8 VL53L0X_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{u8 i; IIC_Start(); IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 if(IIC_Wait_Ack()) //等待应答{IIC_Stop(); return 1; }IIC_Send_Byte(reg); //写寄存器地址IIC_Wait_Ack(); //等待应答for(i=0;i<len;i++){IIC_Send_Byte(buf[i]); //发送数据if(IIC_Wait_Ack()) //等待ACK{IIC_Stop(); return 1; } } IIC_Stop(); return 0;
}
//IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
// 其他,错误代码
u8 VL53L0X_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{ IIC_Start(); IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 if(IIC_Wait_Ack()) //等待应答{IIC_Stop(); return 1; }IIC_Send_Byte(reg); //写寄存器地址IIC_Wait_Ack(); //等待应答IIC_Start();IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令 IIC_Wait_Ack(); //等待应答 while(len){if(len==1)*buf=IIC_Read_Byte(0);//读数据,发送nACK else *buf=IIC_Read_Byte(1); //读数据,发送ACK len--;buf++; } IIC_Stop(); //产生一个停止条件 return 0;
}
//IIC写一个字节
//reg:寄存器地址
//data:数据
//返回值:0,正常
// 其他,错误代码
u8 VL53L0X_Write_Byte(u8 reg,u8 data)
{ IIC_Start(); IIC_Send_Byte((VL53L0X_Add<<1)|0);//发送器件地址+写命令 if(IIC_Wait_Ack()) //等待应答{IIC_Stop(); return 1; }IIC_Send_Byte(reg); //写寄存器地址IIC_Wait_Ack(); //等待应答 IIC_Send_Byte(data);//发送数据if(IIC_Wait_Ack()) //等待ACK{IIC_Stop(); return 1; } IIC_Stop(); return 0;
}
//IIC读一个字节
//reg:寄存器地址
//返回值:读到的数据
u8 VL53L0X_Read_Byte(u8 reg)
{u8 res;IIC_Start(); //IIC_Send_Byte((VL53L0X_Add<<1)|0);//发送器件地址+写命令 IIC_Send_Byte(0x52);//发送器件地址+写命令 IIC_Wait_Ack(); //等待应答 IIC_Send_Byte(reg); //写寄存器地址IIC_Wait_Ack(); //等待应答IIC_Start();IIC_Send_Byte(0x53 );//发送器件地址+读命令 IIC_Wait_Ack(); //等待应答 res=IIC_Read_Byte(0);//读取数据,发送nACK IIC_Stop(); //产生一个停止条件 return res;
}

VL53L0.h:

#ifndef _VL53L0_H
#define _VL53L0_H#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 VL53L0X_Add 0x29#include "sys.h"u8 VL53L0X_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf);//连续写
u8 VL53L0X_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf);//连续读
u8 VL53L0X_Write_Byte(u8 reg,u8 data);//写一个字节
u8 VL53L0X_Read_Byte(u8 reg);//读一个字节
uint16_t bswap(u8 b[]);
uint16_t VL53L0X_decode_vcsel_period(short vcsel_period_reg);
uint16_t makeuint16(int lsb, int msb);
#endif

2.读取数据


a.初始化配置

主函数初始化配置

#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "fmc.h"#include "myiic.h" //测距初始化
#include "VL53L0.h" //测距初始化

定义相关变量

float data[2],i;
uint8_t pcStr[20];
uint8_t aTxStartMessage;//储存接收的数据
uint8_t USART_RX_STA;
int z1,js,bzpd=0,bzpd1=0;
int temp0,temp1,temp2;
static int x,y,z,xz,yz=0; //串口接收到的横纵坐标
extern uint16_t msHcCount;
float length=0;
extern int jd1,asd;
u8 val = 0; //测距函数定义
u8 gbuf[16];
u8 DeviceRangeStatusInternal;

在mian函数中添加声明初始化

SystemClock_Config();IIC_Init(); //使能定义,已经移植到cubeMX_USART1_UART_Init(); uint32_t cnt = 0;uint16_t count[3];MX_GPIO_Init();MX_FMC_Init();

b.获取数据

在while(1)中添加如下代码

while(cnt < 100){HAL_Delay(10); val = VL53L0X_Read_Byte(VL53L0X_REG_RESULT_RANGE_STATUS);if( val & 0x01) break;cnt++;}VL53L0X_Read_Len(VL53L0X_Add, 0x14 , 12, gbuf); count[0] = makeuint16(gbuf[7], gbuf[6]);count[1] = makeuint16(gbuf[9], gbuf[8]);count[2] = makeuint16(gbuf[11], gbuf[10]);DeviceRangeStatusInternal = ((gbuf[0] & 0x78) >> 3);printf("\r\n ambient count = %4d signal count = %4d distance = %4d status = %d ",count[0],count[1],count[2],DeviceRangeStatusInternal);// data_analy(count[2]);HAL_Delay(200);

c.结果展示

连接串口线到电脑,设置波特率为115200,即可看到相关数据

在这里插入图片描述
在这里插入图片描述




3.总结

数据中第一个是环境统计,第二个是信号数统计,如果前方物体越平滑,值越小趋近1,如果前方物体有多个凹凸面,或者检查到多个物体玛者信号数越大,第三个就是相对距离,单位是mm,我用的是一个简单的测距模块,测试精度为20mm—3m,如果高低于这个范围,则会显示20或者8190,一般在1m中效果最佳,准确度比HC05.06要高很多,适合近距离测距,本文章只粘贴了一部分主要程序,如果有需要完整工程可以在下面链接下载,比赛准备用,有缺陷之处,还望请各位大佬指教


三.程序下载链接

https://download.csdn.net/download/weixin_44984773/20357255?spm=1001.2014.3001.5501


推荐阅读
author-avatar
Opera2502898747
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有