Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Странная работа TWI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
kelebeithel
Добрый день! Сел осваивать TWI и захотел попробовать реализовать работу с ним через прерывания. Написал приведенную ниже программу. Есть две меги 328p, одна прошита как мастер, вторая как слейв, код обоих ниже. Программа читает кнопку мастера и при нажатии отправляет кодовую посылку на другую мегу, которая по приеме кодовой посылки меняет состояние светодиода. В итоге залил нижеприведенные программы и начал отлаживать. Выяснил, что первая посылка происходит отлично, светодиод зажигается, и больше не гаснет. Первая посылка происходит и на стороне мастера, и на стороне слэйва без эксцессов. А вот на второй посылке в мастере срабатывает прерывание по Start Condition, и на этом все кончается. Прерывания дальше уже не срабатывают, то есть слэйв не подтверждает передачу ему адреса. И дальше все стопорится. Самое характерное, что если прописать в обработчике прерываний все коды возможных ошибок то он не заходит ни по одному из них. Форумчане, помогите разобраться с ситуацией

CODE
#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
Jury093
Цитата(kelebeithel @ Oct 1 2016, 13:14) *
Прерывания дальше уже не срабатывают, то есть слэйв не подтверждает передачу ему адреса. И дальше все стопорится. Самое характерное, что если прописать в обработчике прерываний все коды возможных ошибок то он не заходит ни по одному из них. Форумчане, помогите разобраться с ситуацией

разделите задачу на две части:
- к мастеру подцепите любой доступный чип (gpio expander, rtc, eeprom) и отладьте протокол для мастера
- с отлаженным мастером разберетесь с протоколом слейва
и уж если не имеете/умеете отладчика, то вместо светодиода полезно поднять консоль, что для мастера, что для слейва, тогда существенно быстрее поймете, где проблема..
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.