解析HAL库函数中HAL_I2C_Mem_Write / HAL_I2C_Mem_Read中的DevAddress

在HAL库函数中的HAL_I2C_Mem_Write /HAL_I2C_Mem_Read两个函数的作用就是玩IIC设备中写入/读取多个直接的数据,

函数原型:

HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);

两个函传入的参数中都需要DevAddress, 以AT24C02为例,

/*
 * AT24C02 2kb = 2048bit = 2048/8 B = 256 B
 * 32 pages of 8 bytes each
 *
 * Device Address
 * 1 0 1 0 A2 A1 A0 R/W
 * 1 0 1 0 0  0  0  0 = 0XA0
 * 1 0 1 0 0  0  0  1 = 0XA1
 */
#define ADDR_24LCxx_Write 0xA0
#define ADDR_24LCxx_Read 0xA1

上面的这个是EEPROM设备的写地址和读地址,,一般是这种定义的,但是在野火的HAL案例中

#define EEPROM_ADDRESS       0xA0

这个是写地址,为什么不定义直接定义写地址和读地址呢?

我们来看看函数的实现,以HAL_I2C_Mem_Write 函数为例: DevAddress传递到该函数中:

/* Send Slave Address and Memory Address */
   if (I2C_RequestMemoryWrite(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK)

   {
     return HAL_ERROR;
   }

再进一步 DevAddress 传递到一个宏定义中:

/* Send slave address */

  hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress);

继续解析: 在stm32f1xx_hal_i2c.h中实现宏定义

#define I2C_7BIT_ADD_WRITE(__ADDRESS__)                   ((uint8_t)((__ADDRESS__) & (uint8_t)(~I2C_OAR1_ADD0)))

#define I2C_7BIT_ADD_READ(__ADDRESS__)                     ((uint8_t)((__ADDRESS__) | I2C_OAR1_ADD0))

现在可以看到,通过位操作,如果是读操作,就将传入的DevAddress处理成1010 0000;如果是写操作,即使传入的地址是0xA0,也不影响写操作,还是被处理成1010 0001;

因此我们在定义EEPROM的设备地址时,可以仅定义设备的读地址,也就是 七位IIC地址+1/0;

物联沃分享整理
物联沃-IOTWORD物联网 » 解析HAL库函数中HAL_I2C_Mem_Write / HAL_I2C_Mem_Read中的DevAddress

发表评论