作者:Opera2502898747 | 来源:互联网 | 2023-06-04 17:34
STM32F4VL53L0激光测距cubemx实现前言一、STM32cubemx配置a.配置RCCb.配置SYSc.配置VL530使能口d.时钟线配置二、STM32F4keil配置
STM32F4+VL53L0激光测距cubemx实现 前言 一、STM32cubemx配置 a.配置RCC b.配置SYS c.配置VL530使能口 d.时钟线配置 二、STM32F4 keil配置 三.程序下载链接
前言 提示:本程序测试主控使用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" void IIC_Init ( void ) { GPIO_InitTypeDef GPIO_InitStructure; IIC_SCL= 1 ; IIC_SDA= 1 ; } void IIC_Start ( void ) { SDA_OUT ( ) ; IIC_SDA= 1 ; IIC_SCL= 1 ; delay_us ( 4 ) ; IIC_SDA= 0 ; delay_us ( 4 ) ; IIC_SCL= 0 ; } void IIC_Stop ( void ) { SDA_OUT ( ) ; IIC_SCL= 0 ; IIC_SDA= 0 ; delay_us ( 4 ) ; IIC_SCL= 1 ; IIC_SDA= 1 ; delay_us ( 4 ) ; } u8 IIC_Wait_Ack ( void ) { u8 ucErrTime= 0 ; SDA_IN ( ) ; 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 ; return 0 ; } void IIC_Ack ( void ) { IIC_SCL= 0 ; SDA_OUT ( ) ; IIC_SDA= 0 ; delay_us ( 2 ) ; IIC_SCL= 1 ; delay_us ( 2 ) ; IIC_SCL= 0 ; } void IIC_NAck ( void ) { IIC_SCL= 0 ; SDA_OUT ( ) ; IIC_SDA= 1 ; delay_us ( 2 ) ; IIC_SCL= 1 ; delay_us ( 2 ) ; IIC_SCL= 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 ) ; IIC_SCL= 1 ; delay_us ( 2 ) ; IIC_SCL= 0 ; delay_us ( 2 ) ; } } u8 IIC_Read_Byte ( unsigned char ack) { unsigned char i, receive= 0 ; SDA_IN ( ) ; 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 ( ) ; else IIC_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" # define SDA_IN ( ) { GPIOB-> MODER&= ~ ( 3 << ( 9 * 2 ) ) ; GPIOB-> MODER|= 0 << 9 * 2 ; } # define SDA_OUT ( ) { GPIOB-> MODER&= ~ ( 3 << ( 9 * 2 ) ) ; GPIOB-> MODER|= 1 << 9 * 2 ; } # define IIC_SCL PBout ( 8 ) # define IIC_SDA PBout ( 9 ) # define READ_SDA PBin ( 9 ) void IIC_Init ( void ) ; void IIC_Start ( void ) ; void IIC_Stop ( void ) ; void IIC_Send_Byte ( u8 txd) ; u8 IIC_Read_Byte ( unsigned char ack) ; u8 IIC_Wait_Ack ( void ) ; void IIC_Ack ( void ) ; void IIC_NAck ( void ) ; 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 ) ; } 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 ( ) ) { IIC_Stop ( ) ; return 1 ; } } IIC_Stop ( ) ; return 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 ) ; else * buf= IIC_Read_Byte ( 1 ) ; len-- ; buf++ ; } IIC_Stop ( ) ; return 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 ( ) ) { IIC_Stop ( ) ; return 1 ; } IIC_Stop ( ) ; return 0 ; } u8 VL53L0X_Read_Byte ( u8 reg) { u8 res; IIC_Start ( ) ; 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 ) ; 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 ( ) ; MX_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) ; 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