Добрый день! Сел осваивать TWI и захотел попробовать реализовать работу с ним через прерывания. Написал приведенную ниже программу. Есть две меги 328p, одна прошита как мастер, вторая как слейв, код обоих ниже. Программа читает кнопку мастера и при нажатии отправляет кодовую посылку на другую мегу, которая по приеме кодовой посылки меняет состояние светодиода. В итоге залил нижеприведенные программы и начал отлаживать. Выяснил, что первая посылка происходит отлично, светодиод зажигается, и больше не гаснет. Первая посылка происходит и на стороне мастера, и на стороне слэйва без эксцессов. А вот на второй посылке в мастере срабатывает прерывание по Start Condition, и на этом все кончается. Прерывания дальше уже не срабатывают, то есть слэйв не подтверждает передачу ему адреса. И дальше все стопорится. Самое характерное, что если прописать в обработчике прерываний все коды возможных ошибок то он не заходит ни по одному из них. Форумчане, помогите разобраться с ситуацией
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define MASTER_ADDRESS (0b0100101)
#define SLAVE_ADDRESS (0b0100111)
#define LED_TOGGLE (0b00100010)
#define SLAVE
//Master
#ifdef MASTER
int current=0b00000010, previous=0b00000010, counter=0;
ISR(TWI_vect)
{
switch(TWSR)
{
case 0x08: //start
TWDR=SLAVE_ADDRESS<<1;
TWCR=0b11001101;
break;
case 0x18: //SLA+W transmitted, ACK recieved
TWDR=LED_TOGGLE;
counter+=1;
if(counter==2)
PORTB|=0b00000001;
else
PORTB&=0b11111110;
TWCR=0b10001111;
break;
case 0x20:
PORTB|=0b00000001;
break;
case 0x30:
PORTB|=0b00000001;
break;
case 0x38:
PORTB|=0b00000001;
break;
case 0x10:
PORTB|=0b00000001;
break;
case 0x28: //data transmitted, ACK recieved
TWCR=0b10011111;
break;
}
}
int main(void)
{
DDRB=0b00000001;
PORTB=0b00000010;
TWAR=MASTER_ADDRESS;
SREG|=0b10000000;
while (1)
{
if((PINB&0b00000010)==0b00000000)
_delay_ms(5);
current=PINB&0b00000010;
if((previous==0b00000010)&&(current==0b00000000))
{
TWCR=0b10100101;
}
previous=current;
}
}
#endif
#ifdef SLAVE
//Slave
int counterSlave=0;
ISR(TWI_vect)
{
switch(TWSR)
{
case 0x60:
TWCR=0b11000101;
break;
case 0x80:
if(TWDR==LED_TOGGLE)
counterSlave+=1;
TWCR=0b11000101;
break;
case 0xA0:
TWCR=0b01000101;
break;
}
}
int main(void)
{
DDRB=0b00000001;
PORTB=0b00000010;
SREG|=0b10000000;
TWAR=SLAVE_ADDRESS<<1;
TWCR=0b01000101;
while (1)
{
if ((counterSlave%2)==1)
PORTB|=0b00000001;
else
PORTB&=0b11111110;
}
}
#endif