【问题标题】:AVR: main()/ISR interferenceAVR:main()/ISR 干扰
【发布时间】:2019-06-17 10:53:48
【问题描述】:

我在 C 中的 ATmega168(从机)上使用 I2C(使用 avr-gcc 编译),但这可能是关于中断的一般问题。

在我的 C 程序中,我有一个 uint8_t i2c_buffer[32] 类型的全局变量,用于存储一些传感器和配置数据。每当总线主机读取或写入从机时,I2C-ISR 也会访问该数组。 由于通信是在硬件中驱动的,因此向 ram(我的 I2C 缓冲区变量)的传输是由中断触发的。

我知道,由于 ISR 和我的主例程之间的竞争条件,不小心从 ISR 和主例程访问变量可能会导致数据损坏,但我不确定如何正确处理这个问题。 有人告诉我在 main 访问有问题的变量时禁用中断。 这将保护变量免受损坏,但另一方面这不会导致数据丢失吗? 如果主设备尝试在中断被禁用的情况下发送数据怎么办?

我猜,由于 I2C 接口仍然启用,输入字节至少会写入 TWDR。那是对的吗? 如果是:有没有办法在主例程完成访问变量后立即触发 ISR?

而且:如果一个实例(ISR 或主实例)只读取而不写入缓冲区的特定部分,这个问题是否仍然存在?

【问题讨论】:

    标签: c interrupt avr i2c


    【解决方案1】:

    一般来说你需要在主进程(主程序)中创建一个临界区。当您的主程序访问共享变量时,您需要禁用中断。

    你有一个现成的标准解决方案:

     #include <util/atomic.h>
    
     /* ....*/ 
    
     ATOMIC_BLOCK(ATOMIC_FORCEON)
     {
         /* potentially non atomic opeartions */
     }
    

    【讨论】:

    • 非常感谢!如果在中断被禁用的情况下主机发送,I2C-ISR 是否会在 ATOMIC_BLOCK 完成后触发?如果设置了 TW 中断标志​​ (TWINT) 并且启用了 TW 中断,则立即执行 ISR。设置 TWINT 并启用全局中断时是否相同?
    • 就是这样。只有原子块受到保护
    • 好的!最后一个问题:当使用ATOMIC_BLOCK 时,这实际上会在运行时禁用中断(就像cli(); 那样)还是在编译期间以任何不同的方式将块“变成原子”。如果我在 for 循环中访问我的变量,我会在每次迭代中“ATOMIC_BLOCK”还是将整个循环包装起来?
    • 尽量缩短禁用 ISR 的时间
    • @SimSon:“如果全局中断状态在进入 ATOMIC_BLOCK 之前不确定,则应使用参数 ATOMIC_RESTORESTATE 而不是 ATOMIC_FORCEON 执行。ATOMIC_BLOCK 通过操作全局中断状态 (I) 位来操作SREG 寄存器。” Source
    猜你喜欢
    • 1970-01-01
    • 2015-02-09
    • 2012-07-17
    • 2015-02-12
    • 2011-04-02
    • 2020-04-01
    • 2017-08-27
    • 2012-11-02
    • 1970-01-01
    相关资源
    最近更新 更多