stm32fxx_hal_i2c.c解讀之HAL_I2C_Mem_Write

  • 2022 年 9 月 19 日
  • 筆記

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 );

image
該函數是通過阻塞模式將一定數量的數據寫入目標地址器件中目標暫存器地址中去。

該函數的參數一共有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的定義如下圖所示
    image
接下來我們看該函數是如何實現功能的:

image

首先定義了一個32位的變數tickstart,將目前時鐘計數的值賦給它,HAL_GetTick()函數實現了取當前時鐘計數的功能,我們看它的源程式碼

image
HAL_GetTick()函數位於stm32f1xx_hal.c文件中,可以看到HAL_GetTick()函數就完成了一個功能返回uwTick,而uwTick即為時鐘計數值,當完成初始化HAL庫後,uwTick每1ms增加1,溢出後歸零。我們可以在程式碼的不同位置分別取當前的uwTick的值,將兩個值相減即為中間程式碼運行時間。

再回到源程式碼:

image
assert_param()是一個參數校驗函數,它的作用是檢驗輸入參數是否符合要求。

接下來判斷I2C是否準備好,如果i2c準備就緒,就進入下一環節,如果沒有,則返回HAL_BUSY。

如果I2C準備就緒,則等待匯流排空閑,通過函數I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart)實現,我們來看看此函數的源碼:
image
本函數位於stm32f1xx_hai_i2c.c文件的6876行,它實現了一個這樣的功能:判斷在一個時間間隔內,某標誌位是否等於某值,如果是則返回HAL_OK;如否,則配置hi2c結構體參數並返回HAL_ERROR。

image

_HAL_LOCK(hi2c)實現了對資源的鎖定,我們來看它的源程式碼

image
它位於stm32f1xx_hal_def.h文件內,它實現了這樣一個功能:判斷—_HANDLE_結構體中的成員Lock的值是否等於HAL_LOCKED,如果是,則返回HAL_BUSY,表示資源已被佔用;如果否,則給Lock賦值HAL_LOCKED,表示本資源已被佔用。

再回到源碼:

image
標藍的程式碼實現了這樣一個功能:檢測I2C是否被使能,如果沒被使能,則使能。

下一段程式碼:

image

可以看到,注釋對這段程式碼的解釋是失能Pos,這個Pos是什麼意思呢?讓我們看STM32手冊裡面的解釋