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

 
 
> зависание TWI
Штефан Виталий
сообщение Mar 25 2008, 07:11
Сообщение #1





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



Прошу помощи в освоении шины TWI.
Связываю 2 атмеги 8535, подтяжка резисторы 3к3, длина мене 10см скрость 120 000 кварц 6мег, есть пауза 0.1с перед запуском интерфейса при включении.
Реализованно чтение (мастер читает данные на слейве). Контролирую состояния TWSR через терминалку на слейве и 7ми сегментом индикаторе на мастере.
В какой-то момент связь между мастером и слейвом прекращается, момент этот может прийти через 5с работы, а может всю ночь простоять (не устойчиво). Выражается это в пропадании прерываний, очень редко перед повисом слейв генерит состояние 0, чаще все зависает с нормальными последними состояниями TWSR на мастете 0x50, на слейве 0xB8. На шине SCL наблюдается 1 а на SDA 0 (чаще всего). Пытался оживить интерфейс вписывая TWCR=0x94 или TWCR=0x84 потом пробывал TWCR=0x00 пауза 1с TWCR=0x84. После этого условия старта (кажется 0xE5), потом пробывал перезагружать сторожевиком (при исчезновении прерываний) безтолку. Помогает восстановить связь только аппаратный резет. Тк самопроизвольное зависание контроллера можно ждать очень долго, то я его вешал коротя отверткой сигнальные линии.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Vix
сообщение Feb 24 2009, 12:50
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 24-06-05
Пользователь №: 6 281



Причину не понял, происходит следующее: после записи или чтения массива в/из шины I2C, линия SDA остается в нуле.
Вылечил путем принудительной выдачи импульсов на линию SCL. Схема: ATmega128 (master) + FM24CL64 + DS1307. Скорость 100 кбод.
Код
void i2cSendStop(void)
{  
    TWCR = (i2cCheck() & TWCR_CMD_MASK) | _BV(TWINT) | _BV(TWEA) | _BV(TWSTO);
}

uint8_t i2cCheck(void){
    uint8_t temp = TWCR;
    if(!(PIND & _BV(PD1))){
        TWCR = 0;
        uint8_t i = 0;
        PORTD &= ~_BV(PD0);
        while(!(PIND & _BV(PD1))){
            DDRD |= _BV(PD0);
            Delay_5us();
            DDRD &= ~_BV(PD0);
            Delay_5us();
            i++;
            if(i > 15) break;    //Fatal error, число 15 от фонаря. В моем случае i не более 2
        }
        PORTD |= _BV(PD0);
    }
    return temp;
}
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 22:19
Рейтинг@Mail.ru


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