1.作用
- 防止編譯器最佳化對該變數的訪問過程,確保每次訪問都能得到最新的值。
- 編譯器通常會對程式碼進行最佳化,例如將變數的值儲存在暫存器中,以減少對記憶體的訪問
2.應用
場景:1.硬體暫存器 2.中斷服務程式中的變數 3.多執行緒程式中的共享變數
//stm32f407xx.h
typedef struct
{
__IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */
__IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */
__IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */
__IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */
} DMA_TypeDef;
//core_cm4.h
#ifdef __cplusplus // C和C++編譯器區分一下 _I 的宏定義
#define __I volatile /*!< Defines 'read only' permissions */
#else
#define __I volatile const /*!< Defines 'read only' permissions */
#endif
#define __O volatile /*!< Defines 'write only' permissions */
#define __IO volatile /*!< Defines 'read / write' permissions */
/* 強呼叫於結構體成員M = member */
#define __IM volatile const /*! Defines 'read only' structure member permissions */
#define __OM volatile /*! Defines 'write only' structure member permissions */
#define __IOM volatile /*! Defines 'read / write' structure member permissions */
3. 解釋說明
- __O、_IO 都表示 volatile,變數訪問不可被最佳化,只是用不同識別符號來區別訪問許可權
- __I表示輸入暫存器(只讀),不可被軟體修改,但可被硬體更新,__O表示輸出暫存器(只寫),__IO表示可讀寫暫存器
- __I:volatile const __O:volatile __IO:volatile
- 輸入暫存器:例如一個溫度感測器連線到MCU,感測器的輸出連線到一個輸入暫存器,可以讀取該輸入暫存器的值獲得溫度值,當然還有狀態資訊或其他外部輸入訊號的應用場景
- 輸出暫存器:用於向外部硬體傳送資料,典型的輸出暫存器用於控制外設、傳送資料或觸發特定的硬體操作
- 輸入輸出暫存器:用於需要雙向資料傳輸的外設,例如GPIO、U(S)ART、I2C和SPI介面等
- 根據作用分類可分為:狀態暫存器、控制暫存器、資料暫存器,跟MCU匯流排類似(地址匯流排、控制匯流排、資料匯流排)