设置位和将逻辑1写入位有什么区别?

auk*_*kxn 1 c embedded bit-manipulation

我正在研究Atmel ATMega的TWI和示例代码错误.它说中断标志TWINT必须通过向其写入逻辑1来清除,所以我想在C中发送START条件是这样的

TWCR |= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
Run Code Online (Sandbox Code Playgroud)

但是在示例代码中它是这样的

TWCR = (1<<TWINT)|(1<<TWSTA|(1<<TWEN)
Run Code Online (Sandbox Code Playgroud)

在Atmel页面上也有人说TWCR |=(1<<TWINT)清除中断标志是错误的方法 http://www.atmel.com/webdoc/AVRLibcReferenceManual/FAQ_1faq_intbits.html 所以在设置位和写入之间有什么不同,因为它是使用不对TWCR |=(1<<TWINT)

我正在使用Atmel 2549 8位微控制器的数据表.示例代码取自第24.6节

Lun*_*din 5

如何正确写入寄存器是根据具体情况完成的.您所指的链接是指通过写入1清除的中断标志寄存器.

假设您有8位寄存器,REG带有两个标志.你想清除lsb标志.如果你写

#define FLAG0 0x01
#define FLAG1 0x02
...
REG = FLAG0;
Run Code Online (Sandbox Code Playgroud)

然后,这将转换为"REG中的机器代码,将值1写入位0",这将正确地清除该标志.

如果你这样做REG |= FLAG0,那么程序将首先读取寄存器并将读取值存储在临时位置.假设寄存器的值为0x03,两个标志都置位.您的代码将0x01写入此临时位置,但由于按位OR,它还将保留其他非相关标志的值.因此,您最终将值0x03写回REG,清除所需的标志和不相关的标志.

中断标志寄存器非常精巧,因为它们可以通过与C编程不能很好地结合的各种奇怪逻辑来实现,例如"通过写1清除"或"通过标记设置读取清除".因此,我强烈建议总是反汇编清除这些标志的C代码,并检查代码实际执行的操作.