我多次聽說,如果不謹慎使用全域變數可能是“危險的”。保護全域變數(或指示讀者與那些相關的代碼的哪一部分)的一種方法是使用 struct 并將所有全域變數作為成員放入其中。
對于術語“全域保護”,我指的是無法從某些 xxx 源檔案中意外修改 global 的值。使用 struct,您可以向讀者(或您自己)闡明可以在何處使用此全域結構的成員,因此變數功能的不確定性較小。
我嘗試在我的專案中實作這一點,我認為這是一個好主意,因為我計劃在未來使用更多的 ISR。為了防止意圖不明或代碼錯誤,使用了全域變數保護的上層方法。但得出的結論是,如果必須訪問 struct 內部的 struct 變數,新的變陣列織看起來更糟,因為代碼的可讀性在很大程度上降低了(我的意見)。
這是我用于按鈕去抖動的代碼片段。XOR 兩個成員看起來像一條討厭的長“蛇”,但可以寫成change = new ^ old好像不需要某些變陣列織(內部結構)。
/*** HEADER FILE ***/
/** Button state structure **/
typedef struct {
uint16_t old;
uint16_t new;
uint16_t change;
} state;
/** Protect ISR globals within structure **/
typedef struct {
state buttonState;
uint16_t isPortStable;
uint16_t countStableStates[BTN_COUNT];
uint32_t tick;
} debounceISR;
debounceISR DB; // !! Keep struct name short to affect readability as little as possible !!
/*** SOURCE FILE ***/
/* Read keyboard and check for transitions */
DB.buttonState.new = BTN_PORT;
DB.buttonState.change = DB.buttonState.new ^ DB.buttonState.old;
DB.buttonState.old = DB.buttonState.new;
從長遠來看,我想防止全域變數在用戶(編碼器)不知情的情況下進行干擾,并隨著一個專案中 ISR(以及全域變數)數量的增加而導致復雜的問題。
Are there any alternative options to such needs? Should I tend to use pointer and static variables in order to avoid globals when using ISRs?
uj5u.com熱心網友回復:
閱讀https://www.embedded.com/a-pox-on-globals。
你的起始前提是一個謬誤,你仍然有一個全域性,它只是一個結構。僅僅懷疑全域變數是“壞的”是不夠的,您必須了解問題是什么以及如何解決它們。這不是一個單一的問題,不能用一種技術解決,在這種情況下,你提出的技術根本不是解決方案。
ISR 共享和狀態資料物件應該在與 ISR 本身相同的源檔案中宣告為靜態(如果您愿意,可以在一個結構中并且這是有意義的 - 即變數是相關的)。如果資料物件是共享的,那么相同的源應該包括訪問器函式,并且是您在頭中宣告的訪問器,而不是資料物件。
然后訪問器可以包含處理資料一致性和原子訪問的代碼,以及施加讀/寫限制和范圍檢查等。
此外,當您需要除錯對任何共享資料物件的訪問時,訪問器為您提供了一個放置斷點以捕獲任何和所有訪問的地方。
除了上面的 A Pox in Globals 文章,您還可以閱讀https://www.embedded.com/introduction-to-the-volatile-keyword/。您的 ISR 共享資料必須volatile至少宣告。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/357608.html
標籤:c struct embedded global-variables isr
上一篇:二叉搜索樹根節點保持NULL
