c - 使用中断处理程序时如何避免使用全局变量?

标签 c embedded global-variables microchip

我主要是自学 C 语言。我对嵌入式微 Controller 进行编程。 (以 dsPIC33fj128gp804 为例) 我通常使用全局变量,而我读过的所有内容都谴责使用全局变量,就像它们是瘟疫一样。我一直在努力减少使用,但有一种情况我不知道如何不使用全局变量。

微 Controller 配备中断。中断是硬件外部触发的事件。当中断被触发时,主代码的执行停止,当前的工作变量被保存,一个预先分配的函数被执行,然后主代码从它停止的地方重新开始。因为中断是一个可以随时触发的独立函数,所以不能将任何内容传入或传出该函数。

例如,当 UART 硬件接收到一个字节的数据时,该数据需要在被覆盖之前移出硬件缓冲区。

void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void)
{
    GlobalVariable = U2RXREG; // Move data to global variable
    IFS4bits.U2RXIF = 0; // Clear the UART2 Receive Interrupt Flag
}

有没有办法在没有全局变量的情况下做到这一点,或者这是一个异常(exception)?

最佳答案

您应该区分具有外部链接的全局变量和文件范围静态变量。你可以用后者解决你的问题。

static volatile int shared_variable ;

int getShared(){ return shared_variable ; }

static void isr_handler()
{
    shared_variable++ ;
}

因此在上面的示例中,对翻译单元外部共享变量的唯一访问是通过访问函数getShared()。这种方法当然依赖于使用单独的编译,但这并不是坏事,原因有很多。

有关避免全局变量的其他技术,以及为什么要这样做的解释,请参阅 Jack Ganssle 的 A Pox on Globals

另一件需要考虑的事情,也是全局变量在这种情况下特别有问题的一个原因是共享变量必须是原子的或在临界区中访问。例如,在 16 位 dsPIC 上,32 位访问不是原子的,在这种情况下,可以在访问函数中放置必要的保护,而如果它是全局的,则必须单独保护每个访问:

例如:

static volatile uint32_t shared_variable ;

int getShared()
{ 
    uint32_t ret ;

    _disable_interrupts() ;
    ret = shared_variable ;
    _enable_interrupts() ;

    return ret ;
}

关于c - 使用中断处理程序时如何避免使用全局变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27204242/

相关文章:

c++ - 在 MatLab 中执行 CUDA mexfunction 期间尝试保存到 .txt 时出错

c - 在c中过滤数组的聪明方法

c - 64 位可执行文件的运行速度比 32 位版本慢

C 结构体,其中元素跨越字节边界并放置在下一个字节中

c++ - 在函数内部 malloc 一个全局变量是错误的吗?

c - 如何在编译时打印结构成员的偏移量?

将 uint32 变量转换为位域 - 未定义的行为?

linux - qt-embedded-linux绘图库是定点的吗?

mysql - 如何在 mysql 中设置 bulk_insert_buffer_size?

PHP 作用域、$GLOBALS 和单例