C语言 使用中断的 I2C 主变送器



我正在使用atmega32并尝试使用中断使主发射器,但它会导致无限跳转到中断,因为TWINT(I2C标志)总是在没有I2C操作时设置并且仅在操作期间清除,如何解决这个问题?

这是主代码,它每秒递增 PORTD,当按下按钮时,它将 PORTD 的当前状态发送到从属微控制器并发生中断并且 portb 增加 2,真正发生的是发送开始信号后它不断跳转到中断(portb 连续递增)而不传输任何东西。

#define F_CPU 8000000UL
#include <avr/io.h>
#include<util/delay.h>
#include <avr/interrupt.h >
void i2c_master_init()
{TWSR=0;
TWBR=0x47;
TWCR=(1<<TWEN); 
}
void i2c_start()
{
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
while((TWCR & (1<<TWINT))==0);  
}
void i2c_send(unsigned char data)
{
TWDR=data;
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE);  
}
void i2c_stop()
{
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);   
}

ISR(TWI_vect)
{   PORTB+=2;                      // PORTB+=2 when an interrupt occurs
}

int main(void)
{
DDRD=0xff;
DDRB=0b11111110;
sei();
i2c_master_init();
i2c_start();
i2c_send(0b00000010);          //sending SLA+W

while(1)
{  
if((PINB & 1)==0)             //check if the button is pressed
{i2c_send(PORTD);         //send the current state of PORTD
while((PINB & 1)==0);     //wait until the button is released
}   
_delay_ms(1000);
PORTD++;                      //increment PORTD every second    
}
return 0;
}

在 AVR 中,当我激活中断时,该标志在跳转到 ISR 之前会自动清除。

根据文档,该标志不会自动清除:

TWINT标志必须由软件通过为其编写逻辑来清除。请注意,在执行中断例程时,硬件不会自动清除此标志。另请注意,清除此标志将启动 TWI 的操作,因此在清除此标志之前,必须完成对 TWI 地址寄存器 (TWAR)、TWI 状态寄存器 (TWSR) 和 TWI 数据寄存器 (TWDR) 的所有访问。

即使TWI概念非常简单,实现它也不是简单的。再看看 ATMega32 数据表。通信顺序在那里详细解释。

另请记住,通过编写"1"来清除中断标志(设置为 0)。