STM32 HAL库硬I2C的TOF050C模块

这篇具有很好参考价值的文章主要介绍了STM32 HAL库硬I2C的TOF050C模块。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

最近在倒腾毕业设计,需要用到TOF050C,但是现有的案例都是软IIC,并且还是基于STM32F103的,笔者用的STM32F767,没有GPIO->CRH寄存器。问题来了,如果我每次都要去看寄存器手册属实费时间,这不干脆直接用硬IIC?

于是乎,打开了TOF050C手册,硬啃!

STM32  HAL库硬I2C的TOF050C模块,嵌入式开发,TOF050C,硬IIC,STM32,硬I2C,HAL,Powered by 金山文档

这手册好在它有工作流程图,能提高开发人员的理解速度。

STM32  HAL库硬I2C的TOF050C模块,嵌入式开发,TOF050C,硬IIC,STM32,硬I2C,HAL,Powered by 金山文档

硬IIC开发代码

由于是使用IIC,用定时器实现微秒级延时,这就不多说了。

直接上库代码

vl6180x.c:

#include    "vl6180x.h"

#define addr_write                                                         0x52
#define addr_read                                                          0x53

#define IDENTIFICATION__MODEL_ID                0x000
#define IDENTIFICATION__MODEL_REV_MAJOR       0x001
#define IDENTIFICATION__MODEL_REV_MINOR       0x002
#define IDENTIFICATION__MODULE_REV_MAJOR      0x003
#define IDENTIFICATION__MODULE_REV_MINOR      0x004
#define IDENTIFICATION__DATE_HI               0x006
#define IDENTIFICATION__DATE_LO               0x007
#define IDENTIFICATION__TIME                  0x008
#define SYSTEM__MODE_GPIO0                    0x010
#define SYSTEM__MODE_GPIO1                    0x011
#define SYSTEM__HISTORY_CTRL                  0x012
#define SYSTEM__INTERRUPT_CONFIG_GPIO         0x014
#define SYSTEM__INTERRUPT_CLEAR               0x015
#define SYSTEM__FRESH_OUT_OF_RESET            0x016
#define SYSTEM__GROUPED_PARAMETER_HOLD        0x017
#define SYSRANGE__START                       0x018
#define SYSRANGE__THRESH_HIGH                 0x019
#define SYSRANGE__THRESH_LOW                  0x01A
#define SYSRANGE__INTERMEASUREMENT_PERIOD     0x01B
#define SYSRANGE__MAX_CONVERGENCE_TIME        0x01C
#define SYSRANGE__CROSSTALK_COMPENSATION_RATE 0x01E
#define SYSRANGE__CROSSTALK_VALID_HEIGHT      0x021
#define SYSRANGE__EARLY_CONVERGENCE_ESTIMATE  0x022
#define SYSRANGE__PART_TO_PART_RANGE_OFFSET   0x024
#define SYSRANGE__RANGE_IGNORE_VALID_HEIGHT   0x025
#define SYSRANGE__RANGE_IGNORE_THRESHOLD      0x026
#define SYSRANGE__MAX_AMBIENT_LEVEL_MULT      0x02C
#define SYSRANGE__RANGE_CHECK_ENABLES         0x02D
#define SYSRANGE__VHV_RECALIBRATE             0x02E
#define SYSRANGE__VHV_REPEAT_RATE             0x031
#define SYSALS__START                         0x038
#define SYSALS__THRESH_HIGH                   0x03A
#define SYSALS__THRESH_LOW                    0x03C
#define SYSALS__INTERMEASUREMENT_PERIOD       0x03E
#define SYSALS__ANALOGUE_GAIN                 0x03F
#define SYSALS__INTEGRATION_PERIOD            0x040
#define RESULT__RANGE_STATUS                  0x04D
#define RESULT__ALS_STATUS                    0x04E
#define RESULT__INTERRUPT_STATUS_GPIO         0x04F
#define RESULT__ALS_VAL                       0x050
#define RESULT__HISTORY_BUFFER_0              0x052
#define RESULT__HISTORY_BUFFER_1              0x054
#define RESULT__HISTORY_BUFFER_2              0x056
#define RESULT__HISTORY_BUFFER_3              0x058
#define RESULT__HISTORY_BUFFER_4              0x05A
#define RESULT__HISTORY_BUFFER_5              0x05C
#define RESULT__HISTORY_BUFFER_6              0x05E
#define RESULT__HISTORY_BUFFER_7              0x060
#define RESULT__RANGE_VAL                     0x062
#define RESULT__RANGE_RAW                     0x064
#define RESULT__RANGE_RETURN_RATE             0x066
#define RESULT__RANGE_REFERENCE_RATE          0x068
#define RESULT__RANGE_RETURN_SIGNAL_COUNT     0x06C
#define RESULT__RANGE_REFERENCE_SIGNAL_COUNT  0x070
#define RESULT__RANGE_RETURN_AMB_COUNT        0x074
#define RESULT__RANGE_REFERENCE_AMB_COUNT     0x078
#define RESULT__RANGE_RETURN_CONV_TIME        0x07C
#define RESULT__RANGE_REFERENCE_CONV_TIME     0x080
#define RANGE_SCALER                          0x096
#define READOUT__AVERAGING_SAMPLE_PERIOD      0x10A
#define FIRMWARE__BOOTUP                      0x119
#define FIRMWARE__RESULT_SCALER               0x120
#define I2C_SLAVE__DEVICE_ADDRESS             0x212
#define INTERLEAVED_MODE__ENABLE              0x2A3

const uint16_t ScalerValues[] = {0, 253, 127, 84};
uint8_t ptp_offset;
uint8_t scaling;
uint16_t io_timeout;


void VL6180X_WR_CMD(uint16_t cmd, uint8_t data)
{
    uint8_t data_write[3];
    data_write[0]=(cmd>>8)&0xff;
    data_write[1]=cmd&0xff;
    data_write[2]=data&0xff;
    HAL_I2C_Master_Transmit(&hi2c1, addr_write, data_write, 3, 0x100);
}

void VL6180X_WR_CMD2(uint16_t cmd, uint16_t data)
{
    uint8_t data_write[4];
    data_write[0]=(cmd>>8)&0xff;
    data_write[1]=cmd&0xff;
     data_write[2]=(data>>8)&0xff;
    data_write[3]=data&0xff;
    HAL_I2C_Master_Transmit(&hi2c1, addr_write, data_write, 4, 0x100);
}

uint8_t VL6180X_ReadByte(uint16_t reg)
{
    uint8_t data_write[2];
    uint8_t receive_data=0;
    data_write[0]=(reg>>8)&0xff;
    data_write[1]=reg&0xff;
    HAL_I2C_Master_Transmit(&hi2c1, addr_write, data_write, 2, 0x100);
    HAL_I2C_Master_Receive(&hi2c1, addr_read, &receive_data, 1, 0x100);
    return receive_data;
}

uint8_t VL6180X_Init()
{
    ptp_offset = 0;
    scaling = 0;
    io_timeout = 2;
    
    ptp_offset = VL6180X_ReadByte(SYSRANGE__PART_TO_PART_RANGE_OFFSET);
    uint8_t reset=VL6180X_ReadByte(0x016);//check wether reset over
    if(reset==1)
    {
        VL6180X_WR_CMD(0X0207,0X01);
        VL6180X_WR_CMD(0X0208,0X01);
        VL6180X_WR_CMD(0X0096,0X00);
        VL6180X_WR_CMD(0X0097,0XFD);
        VL6180X_WR_CMD(0X00E3,0X00);
        VL6180X_WR_CMD(0X00E4,0X04);
        VL6180X_WR_CMD(0X00E5,0X02);
        VL6180X_WR_CMD(0X00E6,0X01);
        VL6180X_WR_CMD(0X00E7,0X03);
        VL6180X_WR_CMD(0X00F5,0X02);
        VL6180X_WR_CMD(0X00D9,0X05);
        VL6180X_WR_CMD(0X00DB,0XCE);
        VL6180X_WR_CMD(0X02DC,0X03);
        VL6180X_WR_CMD(0X00DD,0XF8);
        VL6180X_WR_CMD(0X009F,0X00);
        VL6180X_WR_CMD(0X00A3,0X3C);
        VL6180X_WR_CMD(0X00B7,0X00);
        VL6180X_WR_CMD(0X00BB,0X3C);
        VL6180X_WR_CMD(0X00B2,0X09);
        VL6180X_WR_CMD(0X00CA,0X09);
        VL6180X_WR_CMD(0X0198,0X01);
        VL6180X_WR_CMD(0X01B0,0X17);
        VL6180X_WR_CMD(0X01AD,0X00);
        VL6180X_WR_CMD(0X00FF,0X05);
        VL6180X_WR_CMD(0X0100,0X05);
        VL6180X_WR_CMD(0X0199,0X05);
        VL6180X_WR_CMD(0X01A6,0X1B);
        VL6180X_WR_CMD(0X01AC,0X3E);
        VL6180X_WR_CMD(0X01A7,0X1F);
        VL6180X_WR_CMD(0X0030,0X00);
         
        VL6180X_WR_CMD(0X0011,0X10);
        VL6180X_WR_CMD(0X010A,0X30);
        VL6180X_WR_CMD(0X003F,0X46);
        VL6180X_WR_CMD(0X0031,0XFF);
        VL6180X_WR_CMD(0X0040,0X63);
        VL6180X_WR_CMD(0X002E,0X01);
        VL6180X_WR_CMD(0X001B,0X09);
        VL6180X_WR_CMD(0X003E,0X31);
        VL6180X_WR_CMD(0X0014,0X24);
         
        VL6180X_WR_CMD(0x016,0x00);
        return 1;
    }
    return 0;
}


void VL6180X_SetScaling(uint8_t new_scaling)
{
  uint8_t const DefaultCrosstalkValidHeight = 20; // default value of SYSRANGE__CROSSTALK_VALID_HEIGHT

  // do nothing if scaling value is invalid
  if (new_scaling < 1 || new_scaling > 3) { return; }
    
    scaling = new_scaling;
  VL6180X_WR_CMD2(RANGE_SCALER, ScalerValues[scaling]);

  // apply scaling on part-to-part offset
  VL6180X_WR_CMD(SYSRANGE__PART_TO_PART_RANGE_OFFSET, ptp_offset / scaling);

  // apply scaling on CrossTalkValidHeight
  VL6180X_WR_CMD(SYSRANGE__CROSSTALK_VALID_HEIGHT, DefaultCrosstalkValidHeight / scaling);

  // This function does not apply scaling to RANGE_IGNORE_VALID_HEIGHT.

  // enable early convergence estimate only at 1x scaling
  uint8_t rce = VL6180X_ReadByte(SYSRANGE__RANGE_CHECK_ENABLES);
  VL6180X_WR_CMD(SYSRANGE__RANGE_CHECK_ENABLES, (rce & 0xFE) | (scaling == 1));
}


void VL6180X_ConfigureDefault()
{
  VL6180X_WR_CMD(READOUT__AVERAGING_SAMPLE_PERIOD,0x30);
  VL6180X_WR_CMD(SYSALS__ANALOGUE_GAIN, 0x46);
  VL6180X_WR_CMD(SYSRANGE__VHV_REPEAT_RATE, 0xFF);
  VL6180X_WR_CMD2(SYSALS__INTEGRATION_PERIOD, 0x0063);
  VL6180X_WR_CMD(SYSRANGE__VHV_RECALIBRATE, 0x01);
  VL6180X_WR_CMD(SYSRANGE__INTERMEASUREMENT_PERIOD, 0x09);
  VL6180X_WR_CMD(SYSALS__INTERMEASUREMENT_PERIOD, 0x31);
  VL6180X_WR_CMD(SYSTEM__INTERRUPT_CONFIG_GPIO, 0x24);
  VL6180X_WR_CMD(SYSRANGE__MAX_CONVERGENCE_TIME, 0x31);
  VL6180X_WR_CMD(INTERLEAVED_MODE__ENABLE, 0);
  VL6180X_SetScaling(1);
}

void VL6180X_SetTimeout(uint16_t timeout)
{ 
  io_timeout = timeout; 
}

uint8_t VL6180X_Start_Range()
{
  VL6180X_WR_CMD(0x018,0x01);
  return 0;
}
  
uint16_t timeoutcnt=0;

/*poll for new sample ready */
uint8_t VL6180X_Poll_Range()
{
    uint8_t status;
    uint8_t range_status;
    status=VL6180X_ReadByte(0x04f);
    range_status=status&0x07;
    while(range_status!=0x04)
    {
        timeoutcnt++;
        if(timeoutcnt > io_timeout)
        {
            break;
        }
        status=VL6180X_ReadByte(0x04f);
        range_status=status&0x07;
        delay_ms(1);
    }          
    return 0;
}
   
  
/*read range result (mm)*/
uint8_t VL6180_Read_Range()
{
    int range;
    range=VL6180X_ReadByte(0x062);
    return range;
}
  
/*clear interrupt*/
void VL6180X_Clear_Interrupt()
{
  VL6180X_WR_CMD(0x015,0x07); 
}

uint16_t VL6180X_ReadRangeSingleMillimeters() 
{
    /*Start Single measure mode*/
    VL6180X_Start_Range();
    /* Wait for measurement ready. */
    VL6180X_Poll_Range();
    delay_ms(100);
    return (uint16_t)scaling * VL6180_Read_Range();
}

vl6180x.h:

#ifndef __VL6180X_H
#define __VL6180X_H

#include "main.h"
#include "i2c.h"
#include "tim.h"


uint8_t VL6180X_Start_Range(void);
uint8_t VL6180X_Poll_Range(void);
uint8_t VL6180_Read_Range(void);
uint16_t VL6180X_ReadRangeSingleMillimeters(void);
void VL6180X_Clear_Interrupt(void);

uint8_t VL6180X_Init(void);
void VL6180X_ConfigureDefault(void);
void VL6180X_SetScaling(uint8_t new_scaling);
void VL6180X_SetTimeout(uint16_t timeout);



#endif

这里笔者用的是I2C1,读者要是用其他I2C,只需要对

void VL6180X_WR_CMD(uint16_t cmd, uint8_t data)
void VL6180X_WR_CMD2(uint16_t cmd, uint8_t data)
uint8_t VL6180X_ReadByte(uint16_t reg)

中的HAL_I2C_Master_XXXXX进行修改就好了。


测试

笔者用的STM32F767进行开发的,然后用串口进行输出

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_USART1_UART_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
    
  while(!VL6180X_Init());
  VL6180X_ConfigureDefault();
  VL6180X_SetTimeout(2);
  VL6180X_SetScaling(1);
    
  printf("test!\r\n");
    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    uint16_t distance = VL6180X_ReadRangeSingleMillimeters();
    printf("%04d\r\n", distance);
    delay_ms(900);
        
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

整个项目模板是有STM32CUBEMX生成的,所以这里我直接上main()函数了,注意需要串口重定向哦~

usart.c:

#pragma import(__use_no_semihosting)                          
struct __FILE 
{ 
    int handle; 
}; 

FILE __stdout;

void _sys_exit(int x) 
{ 
    x = x; 
} 

int fputc(int ch, FILE *f)
{     
    while((USART1->ISR&0X40)==0);//Ñ­»··¢ËÍ,Ö±µ½·¢ËÍÍê±Ï   
    USART1->TDR=(uint8_t)ch;      
    return ch;
}

串口输出情况:

STM32  HAL库硬I2C的TOF050C模块,嵌入式开发,TOF050C,硬IIC,STM32,硬I2C,HAL,Powered by 金山文档

缩放因子

上述实验是使用缩放因子为1的 VL6180X_SetScaling(1);

其测量距离 2-18cm

根据手册,其实在不同缩放因子下,测量距离范围是不一样的,并且误差大小也不一样。

STM32  HAL库硬I2C的TOF050C模块,嵌入式开发,TOF050C,硬IIC,STM32,硬I2C,HAL,Powered by 金山文档

这里第二个"Scaling factor = 1"应该是写错了,改成"Scaling factor = 2"

也就是最大测量范围的值,实际上到不了这个距离,大概80~90%。

事实上,不仅有上限范围,下线范围也有变化,这个是我多次测量后发现数据不对劲所总结出来的。大概:

  • Scaling factor = 2测量范围是20~40cm,需要做数据拟合矫正数据

  • Scaling factor = 3测量范围是40~60cm,需要做数据拟合矫正数据

似乎不是线性关系,应该要二次函数拟合


简评

可能TOF050F版本会少这些破事,能通过上位机直接矫正,TOF050C只有通过自己多次测量,去调整寄存器的矫正参数,确实不是那么的好用哈。还是建议大家使用TOF050F版本。文章来源地址https://www.toymoban.com/news/detail-623292.html

到了这里,关于STM32 HAL库硬I2C的TOF050C模块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32之I2C总线知识和HAL库函数

    一、 I2C总线知识 I2C总线物理拓扑结构 I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来 产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接

    2024年02月21日
    浏览(44)
  • STM32设置为I2C从机模式(HAL库版本)

    我之前出过一篇关于STM32设置为I2C从机的博客,现在应粉丝要求,出一篇HAL库版本的I2C从机编程。 基于官方库版本的可以看下我之前发的文章:STM32设置为I2C从机模式 测试芯片:STM32F103RCT6 测试方法:用一个USB转I2C的工具接到STM32的I2C引脚上,通过上位机工具进行读写操作。如

    2024年02月12日
    浏览(62)
  • 【STM32CubeMX+HAL库】I2C详解+读写EEPROM

    在之前的标准库中,STM32的硬件IIC非常复杂,更重要的是它并不稳定,所以都不推荐使用。但是在我们的HAL库中,对硬件IIC做了全新的优化,使得之前软件IIC几百行代码,在HAL库中,只需要寥寥几行就可以完成 那么这篇文章将带你去感受下它的优异之处。 通过本篇博客您将

    2024年02月03日
    浏览(52)
  • Clion开发STM32之HAL库I2C封装(基础库)

    引用参考: Clion开发STM32之HAL库GPIO宏定义封装(最新版)

    2024年02月13日
    浏览(46)
  • 01_STM32软件+硬件I2C读取MPU6050(HAL库)

    目录 1、I2C简介 2、I2C时序单元 2.1 起始条件 2.2 终止条件 2.3 发送一个字节 2.4 接收一个字节 2.5 发送应答 2.6 接收应答 3、I2C完整时序 3.1 指定地址写一个字节 3.2 当前地址读一个字节 3.2 指定地址读一个字节 4、简单软件I2C代码(HAL) 4.1 软件I2C 4.2 软件I2C读MPU6050寄存器 5、ST

    2024年04月17日
    浏览(47)
  • 【STM32】I2C练习,HAL库读取MPU6050角度陀螺仪

    MPU-6000(6050)为全球首例整合性6轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时间轴之差的问题,减少了大量的封装空间。当连接到三轴磁强计时,MPU-60X0提供完整的9轴运动融合输出到其主I2C或SPI端口(SPI仅在MPU-6000上可用)。 寄存器地址 寄存器内容 0X3B

    2024年02月16日
    浏览(50)
  • 【STM32】AT24C256硬件I2C读写,基于HAL库

    目录 一、简单介绍 二、配置工程 打开CubeMX,配置时钟,调试接口,工程名,目录等 配置iic 配置串口用于显示信息 三、硬件连接 四、代码编写 一、随机写入一个字节 测试代码 波形如下 代码编写 二、连续写入 代码如下 三、随机读取 测试代码 波形如下 代码编写 四、连续

    2024年02月03日
    浏览(48)
  • 关于STM32硬件I2C HAL_I2C_Mem_Read,在I2C_WaitOnTXISFlagUntilTimeout返回HAL_ERROR

    在使用NUCLEO-L452RE开发版的IIC总线作为主机和其他设备从机通信时主机IIC在以下代码处返回HAL_ERROR. /* Wait until TXIS flag is set */   if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)   {     return HAL_ERROR;   } 在调试中发现如果使用模拟IIC,可以与从机正常通信,但是使用硬件

    2024年04月28日
    浏览(44)
  • STM32模拟I2C协议获取HMC5883L电子罗盘磁角度数据 (HAL)

    HMC5883L 传感器采用霍尼韦尔各向异性磁阻(AMR)技术,应用于罗盘和三轴磁场角度检测领域,常用于水平物体转动的角度识别。HMC5883L 采用I2C总线接口,2.16~3.6V供电范围,带有校准测试功能。 HMC5883L的硬件连接有5个管脚,除了VCC和GND,以及I2C的SCK和SDA,还有一根INT中断线,用于

    2024年02月13日
    浏览(43)
  • HAL STM32 HW I2C DMA + SSD1306/SH1106驱动示例

    📍硬件I2C DMA驱动参考: https://blog.csdn.net/weixin_45065888/article/details/118225993 🔖本工程基于 STM32F103VCT6 ,驱动程序独立,可以移植到任意STM32型号上使用。 📑字体大小说明 🌿该驱动程序ASCII字符集类型大小包含:6X8、8X16,12X6 三种。其中6X8和8X16共用一个API函数调用,形参不同

    2024年02月22日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包