stm32fxx_hal_i2c.c解读之HAL_I2C_Mem_Write
HAL_I2C_Mem_Write()函数位于stm32fxx_hal_i2c.c文件的2432行,源代码对该函数的解释如下图
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 );
该函数是通过阻塞模式将一定数量的数据写入目标地址器件中目标寄存器地址中去。
该函数的参数一共有7个,将他们的特性列入下表格:
参数名 | 参数数据类型 | 参数解释 |
---|---|---|
hi2c | I2C_HandleTypeDef * | hi2c是一个结构体指针,它包含了特定I2C设备的配置信息 |
DevAddress | uint16_t | 目标器件的地址,七位地址必须左对齐 |
MemAddress | uint16_t | 目标器件的目标寄存器地址 |
MemAddSize | uint16_t | 目标器件内部寄存器地址数据长度 |
pData | uint8_t* | 一个8位的指针,指向待写的数据 |
Size | uint16_t | 待传数据的数量 |
Timeout | uint32_t | 等待时间 |
- 结构体I2C_HandleTypeDef的定义如下图所示
接下来我们看该函数是如何实现功能的:
首先定义了一个32位的变量tickstart,将目前时钟计数的值赋给它,HAL_GetTick()函数实现了取当前时钟计数的功能,我们看它的源代码
HAL_GetTick()函数位于stm32f1xx_hal.c文件中,可以看到HAL_GetTick()函数就完成了一个功能返回uwTick,而uwTick即为时钟计数值,当完成初始化HAL库后,uwTick每1ms增加1,溢出后归零。我们可以在代码的不同位置分别取当前的uwTick的值,将两个值相减即为中间代码运行时间。
再回到源代码:
assert_param()是一个参数校验函数,它的作用是检验输入参数是否符合要求。
接下来判断I2C是否准备好,如果i2c准备就绪,就进入下一环节,如果没有,则返回HAL_BUSY。
如果I2C准备就绪,则等待总线空闲,通过函数I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart)实现,我们来看看此函数的源码:
本函数位于stm32f1xx_hai_i2c.c文件的6876行,它实现了一个这样的功能:判断在一个时间间隔内,某标志位是否等于某值,如果是则返回HAL_OK;如否,则配置hi2c结构体参数并返回HAL_ERROR。
_HAL_LOCK(hi2c)实现了对资源的锁定,我们来看它的源代码
它位于stm32f1xx_hal_def.h文件内,它实现了这样一个功能:判断—_HANDLE_结构体中的成员Lock的值是否等于HAL_LOCKED,如果是,则返回HAL_BUSY,表示资源已被占用;如果否,则给Lock赋值HAL_LOCKED,表示本资源已被占用。
再回到源码:
标蓝的代码实现了这样一个功能:检测I2C是否被使能,如果没被使能,则使能。
下一段代码:
可以看到,注释对这段代码的解释是失能Pos,这个Pos是什么意思呢?让我们看STM32手册里面的解释