'I2C master transmitter using interrupt
I'm using atmega32 and trying to make master transmitter using interrupt, but it causes an infinite jumping to the interrupt because the TWINT(I2C flag) is always set when there is no I2C operation and it's cleared only in operation period, how can I solve this problem?
here is the master code, it increments PORTD every second, when a button is pressed it sends the current state of PORTD to the slave microcontroller and an interrupt occurs and portb is increased by two, what really happens is that after sending the start signal it keeps jumping to the interrupt continuously(portb is incremented continuously)without transmitting anything.
#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;
}
Solution 1:[1]
in AVR when I activate the interrupt , the flag is cleared automatically before jumping to ISR.
According to the documentation, the flag is not cleared automatically:
The TWINT Flag must be cleared by software by writing a logic one to it. Note that this flag is not automatically cleared by hardware when executing the interrupt routine. Also note that clearing this flag starts the operation of the TWI, so all accesses to the TWI Address Register (TWAR), TWI Status Register (TWSR), and TWI Data Register (TWDR) must be complete before clearing this flag.
Even if the TWI concept is pretty simple, implementing it is not straightforward. Take another look at the ATMega32 datasheet. The communication sequence is explained in detail there.
Also keep in mind, that you clear interrupt flags (set to 0) by writing a "1".
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Rev |
