我多次听说全局变量可以是"危险的";如果不谨慎使用。保护全局变量的一种方法(或指示读取器与这些全局变量相关的代码的哪个部分(是使用struct并将所有全局变量作为成员放入其中。
用术语";全球保护";我指的是不能从一些xxx源文件中意外修改global的值。使用struct,您可以向读者(或您自己(阐明该全局结构的成员可能在哪里使用,因此变量功能的不确定性较小。
我试图在我的项目中实现这一点,我认为这是一个好主意,因为我计划在未来使用更多的ISR。为了防止意图不明确或代码错误,使用了全局变量保护的上层方法。但得出的结论是,如果必须访问结构内部的结构,新的变量组织看起来会更糟,因为代码的可读性在很大程度上会降低(我的观点(。
以下是我用于按钮去抖动的代码片段。XORing两个成员看起来像一个讨厌的长";蛇;但如果不需要某些可变组织(结构内部(,则可以写成CCD_ 1。
/*** 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(以及全局(数量的增加而导致复杂的问题。
对于这种需求,还有其他选择吗?在使用ISR时,我应该倾向于使用指针和静态变量来避免全局变量吗?
阅读https://www.embedded.com/a-pox-on-globals.
你的出发前提是一个谬论,你仍然有一个全局,它只是碰巧是一个结构。怀疑全球是";坏";,你必须了解问题是什么以及如何解决它们。这不是一个单一的问题,它们不可能通过一种技术来解决,在这种情况下,你提出的技术根本不是解决方案。
ISR共享和状态数据对象应在与ISR本身相同的源文件中声明为静态(如果您愿意,可以在结构中声明,这是有意义的,即变量是相关的(。如果数据对象是共享的,那么同一个源应该包括访问器函数,并且您在标头中声明的是访问器,而不是数据对象。
然后,访问者可以包括处理数据一致性和原子访问的代码,以及施加读/写限制和范围检查等。
此外,当您需要调试对任何共享数据对象的访问时,访问器为您提供了一个放置断点的位置,以捕获任何和所有访问。
除了上面Globals中的A Pox文章,您还可以阅读https://www.embedded.com/introduction-to-the-volatile-keyword/.您的ISR共享数据必须至少声明为volatile
。