1.STM32F4系列IIC接口初始化

(1)通过STM32Cube创建工程

本项目采用的是STM32F427,IO 接口采用的是PC9和PA8;如下图:

 if(i2cHandle->Instance==I2C3)
  {
  /* USER CODE BEGIN I2C3_MspInit 0 */

  /* USER CODE END I2C3_MspInit 0 */

    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**I2C3 GPIO Configuration
    PC9     ------> I2C3_SDA   用于板载的温湿度传感器通讯
    PA8     ------> I2C3_SCL
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_8;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* I2C3 clock enable */
    __HAL_RCC_I2C3_CLK_ENABLE();
  /* USER CODE BEGIN I2C3_MspInit 1 */

  /* USER CODE END I2C3_MspInit 1 */
  }

STM32Cube的IIC配置直接用默认信息就行。中断也无须使能,IO端口设置为高速。

(2)IIC接口初始化

void MX_I2C3_Init(void)//用于板载的温湿度传感器通讯
{

  /* USER CODE BEGIN I2C3_Init 0 */

  /* USER CODE END I2C3_Init 0 */

  /* USER CODE BEGIN I2C3_Init 1 */

  /* USER CODE END I2C3_Init 1 */
  hi2c3.Instance = I2C3;
  hi2c3.Init.ClockSpeed = 100000;
  hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c3.Init.OwnAddress1 = 0;
  hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c3.Init.OwnAddress2 = 0;
  hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c3) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C3_Init 2 */

  /* USER CODE END I2C3_Init 2 */

}

2.HDC1080数据采集部分

(1)头文件里宏定义寄存器地址和函数声明


#define ADDR_HDC1080  0x80             //1000 000RW 
#define HDC1080_TempAddress         0x00  //读取温度的地址
#define HDC1080_HumiAddress         0x01  //读取湿度的地址
#define HDC1080_Configuration       0x02  //写配置信息的寄存器地址

#define HDC1080_ManufactID          0xFE

void HDC1080Setresolition(void);
void Get_HDC1080Value(float *rt,float *rh);

(2)重点寄存器与手册对照关系

(3)测试STM32硬件IIC与HDC芯片的接口是否通讯正常

void HDC1080Setresolition(void)
{
    uint8_t Manu_Id[2];
    HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)HDC1080_ManufactID, I2C_MEMADD_SIZE_8BIT, (uint8_t *)Manu_Id, 2,1000); //0x5449 是正确的
    Usart8_SendData(Manu_Id,2); 
    
    
    uint8_t buf[4];
    buf[0]=0x10;  //bit12 =1 温度湿度都采集
    buf[1]=0x00;  //0001 0000 0000 0000  bit10=0 温度14bit,bit8,9=00,湿度=14bit
  HAL_I2C_Mem_Write(&hi2c3, ADDR_HDC1080, (uint8_t)HDC1080_Configuration, I2C_MEMADD_SIZE_8BIT, buf, 2, 100); 
    

//    HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)0x02, I2C_MEMADD_SIZE_8BIT, (uint8_t *)Manu_Id, 2,1000); //0x5449 是正确的
//    Usart8_SendData(Manu_Id,2);
}

(4)STM32的HAL库IIC设置注意事项

A: 在HAL_I2C_Mem_Read函数中的I2C_MEMADD_SIZE_8BIT一定要设置为I2C_MEMADD_SIZE_8BIT模式,因为器件手册中要求必须是I2C_MEMADD_SIZE_8BIT模式;

B:可以先读取器件的ID,通过串口显示一下,如果读取的ID是正确的,那说明IIC接口的HAL库与芯片通讯之间是正常的。

(5)STM32的HAL库 一个函数读取温度和湿度代码

void Get_HDC1080Value(float *rt,float *rh)
{
    uint16_t temp,humi;
    uint8_t buf[4];//读取数据的缓存
    HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)HDC1080_TempAddress, I2C_MEMADD_SIZE_8BIT, (uint8_t *)buf, 4,1000); //读取4个,前两个是温度,后两个是湿度
    temp = buf[0] << 8;
    temp |= buf[1];

    humi = buf[2] << 8;
    humi |= buf[3];
    
    //ut 和 uh 为从HDC1080中读取出的原始温湿度值,这里根据芯片手册中的公式进行转换。
    *rt = temp / pow(2.0, 16.0) * 165.0 - 40.0; //'C
    *rh = humi / pow(2.0, 16.0) * 100.0; //%RH  

}

3.HDC1080数据采集核心技术点

编程手册里面数了要等待数据转换完成,但是直接使用STM32的hal库HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)HDC1080_TempAddress, I2C_MEMADD_SIZE_8BIT, (uint8_t *)buf, 4,1000);

是没有等待的时间的,

需要在Stm32f4xx_hal_i2C.c里面修改

static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)
{
  /* Enable Acknowledge */
  SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);

  /* Generate Start */
  SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);

  /* Wait until SB flag is set */
  if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK)
  {
    if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START)
    {
      hi2c->ErrorCode = HAL_I2C_WRONG_START;
    }
    return HAL_TIMEOUT;
  }

  /* Send slave address */
  hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress);

  /* Wait until ADDR flag is set */
  if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK)
  {
    return HAL_ERROR;
  }

  /* Clear ADDR flag */
  __HAL_I2C_CLEAR_ADDRFLAG(hi2c);

  /* Wait until TXE flag is set */
  if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
  {
    if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
    {
      /* Generate Stop */
      SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
    }
    return HAL_ERROR;
  }

  /* If Memory address size is 8Bit */
  if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
  {
    /* Send Memory Address */
    hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress);
  }
  /* If Memory address size is 16Bit */
  else
  {
    /* Send MSB of Memory Address */
    hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress);

    /* Wait until TXE flag is set */
    if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
    {
      if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
      {
        /* Generate Stop */
        SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
      }
      return HAL_ERROR;
    }

    /* Send LSB of Memory Address */
    hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress);
  }

  /* Wait until TXE flag is set */
  if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
  {
    if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
    {
      /* Generate Stop */
      SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
    }
    return HAL_ERROR;
  }
    if(hi2c ==&hi2c3) //温湿度传感器 需要一个延时
            HAL_Delay(20);

  /* Generate Restart */
  SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);

  /* Wait until SB flag is set */
  if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK)
  {
    if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START)
    {
      hi2c->ErrorCode = HAL_I2C_WRONG_START;
    }
    return HAL_TIMEOUT;
  }

  /* Send slave address */
  hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress);

  /* Wait until ADDR flag is set */
  if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK)
  {
    return HAL_ERROR;
  }

  return HAL_OK;
}

3. 到此,所有问题都解决了。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐