реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Странная работа TWI
kelebeithel
сообщение Oct 1 2016, 10:14
Сообщение #1





Группа: Новичок
Сообщений: 1
Регистрация: 13-08-16
Пользователь №: 92 944



Добрый день! Сел осваивать 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
Go to the top of the page
 
+Quote Post
Jury093
сообщение Oct 1 2016, 22:24
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 959
Регистрация: 11-01-06
Из: Санкт-Петербург
Пользователь №: 13 050



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

разделите задачу на две части:
- к мастеру подцепите любой доступный чип (gpio expander, rtc, eeprom) и отладьте протокол для мастера
- с отлаженным мастером разберетесь с протоколом слейва
и уж если не имеете/умеете отладчика, то вместо светодиода полезно поднять консоль, что для мастера, что для слейва, тогда существенно быстрее поймете, где проблема..
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 06:25
Рейтинг@Mail.ru


Страница сгенерированна за 0.01698 секунд с 7
ELECTRONIX ©2004-2016