Перейти к содержанию
    

Странная работа TWI

Добрый день! Сел осваивать 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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прерывания дальше уже не срабатывают, то есть слэйв не подтверждает передачу ему адреса. И дальше все стопорится. Самое характерное, что если прописать в обработчике прерываний все коды возможных ошибок то он не заходит ни по одному из них. Форумчане, помогите разобраться с ситуацией

разделите задачу на две части:

- к мастеру подцепите любой доступный чип (gpio expander, rtc, eeprom) и отладьте протокол для мастера

- с отлаженным мастером разберетесь с протоколом слейва

и уж если не имеете/умеете отладчика, то вместо светодиода полезно поднять консоль, что для мастера, что для слейва, тогда существенно быстрее поймете, где проблема..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...