Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: twi(i2c)-интерфейс
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
namelos
Доброе время суток всем.
Разрабатываю систему измерения и контроля температуры на 36 датчиков, состоящую из 3 контроллеров(slaves) на 12 датчиков(опрос, контроль, вкл./выкл. реле) и контроллера(master) отображения информации на GLCD и ввода данных на рабочие контроллеры(запись в eeprom). Коммуникация главного контроллера осуществляется по twi(i2c)-интерфейсу.
Пока работаю с макеткой. Нашел bug при обрывaнии линии twi, зависает главный контроллер, т.к. TWI Interrupt не был обнулен, т.е не произошло нормального завершения передачи информации.
Вопрос такой, уважаемые эмбеддеры, для контроля работы twi обязательно использовать еще таймер, который при зависании квитирует Interrupt?
И еще, slaves посылают пакеты в 40 байт, обязательна ли при такой длине пакета crc проверка?
Заранее всем спасибо.
umup
да, TWI на АВР часто глухо виснет при замыканиях/обрывах/помехах на линии. проверка обязательна. можно реализовать TWI программно с контролем состояния линии. и зачем аж 4 контроллера ? с одним будет надежнее - расстояние между контроллерами наверно небольшое.
namelos
Цитата(umup @ Nov 22 2007, 19:29) *
да, TWI на АВР часто глухо виснет при замыканиях/обрывах/помехах на линии. проверка обязательна. можно реализовать TWI программно с контролем состояния линии. и зачем аж 4 контроллера ? с одним будет надежнее - расстояние между контроллерами наверно небольшое.

umup, спасибо за ответ.
Что-то я не понял, вы какую проверку имеете ввиду? И если можно по подробнее про TWI с контролем состояния линии.
Использую 3 контроллера для 3 обьектов, в свою очередь, для каждого обьекта возможна различная конфигурация и настройка сенсоров. Надеюсь разместить все контроллеры на одной платине.
Dog Pawlowa
Цитата(namelos @ Nov 22 2007, 19:41) *
umup, спасибо за ответ.
Что-то я не понял, вы какую проверку имеете ввиду? И если можно по подробнее про TWI с контролем состояния линии.
Использую 3 контроллера для 3 обьектов, в свою очередь, для каждого обьекта возможна различная конфигурация и настройка сенсоров. Надеюсь разместить все контроллеры на одной платине.


Родное немецкое слово "платИна" smile.gif
На какое расстояние передаете? С какой скоростью?
defunct
Цитата(umup @ Nov 22 2007, 18:29) *
да, TWI на АВР часто глухо виснет при замыканиях/обрывах/помехах на линии. проверка обязательна.

Несогласен с этим утверждением.
Ничего не виснет просто так. Скорее всего просто не обрабатывается какое-то из состояний линии, чаще всего некоторые игнорируют обработку ошибочных ситуаций (состояние 0x00), что и приводит к "зависанию".

Цитата
контроля работы twi обязательно использовать еще таймер, который при зависании квитирует Interrupt?

определенно - нет.
Лучше напишите i2c драйвер в режиме прерываний с обслуживанием всех 32х состояний линии. Проблем с TWI модулем тогда будет - ровно 0.
umup
defunct
никак не могу понять - как отловить завершение Stop condition ?
IgorKossak
Цитата(umup @ Nov 22 2007, 22:08) *
defunct
никак не могу понять - как отловить завершение Stop condition ?

Хоть я и не defunct, но отвечу.
Stop condition это единственное состояние, завершения которого не нужно отлавливать. Оно выполняется безусловно.
namelos
Спасибо, defunct. A как насчет crc-проверки после пересылки пакета? Или для i2c протокола это необязательно?


Цитата(Dog Pawlowa @ Nov 22 2007, 21:02) *
Родное немецкое слово "платИна" smile.gif
На какое расстояние передаете? С какой скоростью?

smile.gif
Скорость установил 100кбит/с, надеюсь уложиться до 10см.
defunct
Цитата(namelos @ Nov 22 2007, 23:50) *
A как насчет crc-проверки после пересылки пакета? Или для i2c протокола это необязательно?

Думаю что обязательно, как раз для случаев когда на линии возникает ошибка (помеха искажающая данные)..
Но это уже забота того модуля кому предназначался пакет.
umup
IgorKossak
а если нужно отловить момент завершения формирования STOP ?
defunct
Цитата(umup @ Nov 23 2007, 14:12) *
а если нужно отловить момент завершения формирования STOP ?

Для слейва - состояние 0xA0 (STOP or repeated START)
для мастера смотрите состояния - arbitration lost / bus error (для случая если стоп не может быть послан). Стоп состояние мастеру отлавливать не нужно, т.к. он его посылает.
IgorKossak
Цитата(umup @ Nov 23 2007, 13:12) *
IgorKossak
а если нужно отловить момент завершения формирования STOP ?

Дополню сказанное defunct.
Со стороны мастера. Перед посылкой команды стоп не должно быть ошибок в линии (анализируется опросом состояния).
Команда стоп как таковая срабатывает аналогично команде установки состояния порта и сигнал появляется на линии в следующий (или через один, не помню точно) такт МК. Срабатывает безусловно. Для этого состояния, в отличие от других, и прерывание не предусмотрено.
namelos
Цитата(IgorKossak @ Nov 23 2007, 17:43) *
Перед посылкой команды стоп не должно быть ошибок в линии (анализируется опросом состояния).
Команда стоп как таковая срабатывает аналогично команде установки состояния порта и сигнал появляется на линии в следующий (или через один, не помню точно) такт МК. Срабатывает безусловно. Для этого состояния, в отличие от других, и прерывание не предусмотрено.

А как проверить состояние линии?
При разьединении сигнального кабеля TWI как раз в этом месте у меня происходит зависание master контроллера. Определил, что TWSR = 0x58, но почему то команда в момент прерывания
Код
ISR (TWI_vect)
{
switch(TWSR)
{
case 0x58: // Data byte has been received and NACK transmitted
TWCR = (1<<TWEN)|                          // TWI Interface enabled
             (0<<TWIE)|(1<<TWINT)|                  // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|       // Initiate a STOP condition. TWSTO reset
             (0<<TWWC);
}
}

не выполняется и опрос TWI порта не просходит, т.к TWIE не обнуляется.
Код
if( !(TWCR & _BV(TWIE)) )
    {
            //Check if the last opeation was OK
        if(twi_statusReg.lastReceiveOK) // Last transmission competed successfully.
            twi_get_data_message ( ...);
        
        twi_start_data_transceiver();
    }


Что можно предпринять?
bodja74
Цитата(namelos @ Nov 23 2007, 21:16) *
А как проверить состояние линии?

...
Что можно предпринять?


1 Любая проверка ,есть ли связь ,опредляется по НАСК или АСК.
2 Если мастер получает НАСК ,он должен выставить СТОП ,если слейв получает НАСК он должен прекратить передачу и перейти на ожидание старта со своим адресом.
3 Со стопом там тоже не все чисто ,так как проверки флага там нет стоит сделать задержку не менее одного такта шины,или обеспечить таковую между пакетами ,вставив какую нибудь обработку кода.В противном случае легко перейдем в ступор.Хотя может в новых камнях это продебажили - незнаю.
4 Зависон у Вас от того ,что Вы пропустили пару раз подряд НАСК и никак на это не отреагировали.
namelos
Цитата(bodja74 @ Nov 23 2007, 23:00) *
3 Со стопом там тоже не все чисто ,так как проверки флага там нет стоит сделать задержку не менее одного такта шины,или обеспечить таковую между пакетами ,вставив какую нибудь обработку кода.В противном случае легко перейдем в ступор.Хотя может в новых камнях это продебажили - незнаю.

несовсем понятно...начало transreceive пакета реализуется только в случае недействительного TWI Interrupt (TWIE =0)
Цитата(bodja74 @ Nov 23 2007, 23:00) *
4 Зависон у Вас от того ,что Вы пропустили пару раз подряд НАСК и никак на это не отреагировали.

Почему не отреагировал, вот :
Код
TWCR = (1<<TWEN)|                          // TWI Interface enabled
             (0<<TWIE)|(1<<TWINT)|                  // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|       // Initiate a STOP condition. TWSTO reset
             (0<<TWWC);

Контроллер не зависает, он из состояния interrupt не выходит, а точнее выходит, но TWIE не обнуляет.
singlskv
Цитата(namelos @ Nov 23 2007, 22:34) *
Контроллер не зависает, он из состояния interrupt не выходит, а точнее выходит, но TWIE не обнуляет.

Покажите полный код работы с i2c на мастере.

ИМХО, в ситуациях обрыва/коротыша на линиях i2c, иногда без таймаутов не
обойтись...
Это касается только мастера...
Слейву пофиг на обрыва/коротыш если обработаны все состояния внутреннего i2c автомата...
namelos
Код

ISR (TWI_vect)
{
    static uint8_t twi_ptr_Buf;
    switch (TWSR)
      {
        // START or Repeated START has been transmitted
        case TW_START:  case TW_REP_START:       
            twi_ptr_Buf= 0;                     // Set buffer pointer to the TWI Address location
        
        // SLA+W or Data byte has been tramsmitted and ACK received
        case TW_MT_SLA_ACK: case TW_MT_DATA_ACK:      
            
            if (twi_ptr_Buf < twi_msgSize)
          {
                TWDR = twi_Buf[twi_ptr_Buf++];
                TWCR = (1<<TWEN)|                      // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|               // Enable TWI Interupt and clear the flag to send byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|    //
               (0<<TWWC);
                      //  
          }
            else                    // Send STOP after last byte
          {
                twi_statusReg.lastTransmitOK = TRUE;   // Set status bits to completed successfully.
                TWCR = (1<<TWEN)|                        // TWI Interface enabled
               (0<<TWIE)|(1<<TWINT)|                  // Disable TWI Interrupt and clear TWINT the flag
               (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|    // Initiate a STOP condition.
               (0<<TWWC);                            
          }
      break;
        
        // Data byte has been received and ACK tramsmitted
        case TW_MR_DATA_ACK:      
          twi_Buf[twi_ptr_Buf++] = TWDR;
            // SLA+R has been tramsmitted and ACK received
            case TW_MR_SLA_ACK:      
      
            if (twi_ptr_Buf <(uint8_t) (twi_msgSize-1) )            // Detect the before last byte to NACK it.!!!!
          {
                TWCR = (1<<TWEN)|                             // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send ACK after reception
               (0<<TWWC);
                                                  
          }
            //Send NACK after next reception
            else                    
          {
                TWCR = (1<<TWEN)|                                 // TWI Interface enabled
               (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag to read next byte
               (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|           // Send NACK after reception
               (0<<TWWC);
                    
                                 //
          }    
          break;
        
        case TW_MR_DATA_NACK:     // Data byte has been received and NACK transmitted
          
            twi_Buf[twi_ptr_Buf] = TWDR;                    //here will be last byte saved
          twi_statusReg.lastReceiveOK = TRUE;          // Set status bits to completed successfully.
      
            TWCR = (1<<TWEN)|                          // TWI Interface enabled
             (0<<TWIE)|(1<<TWINT)|                  // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|       // Initiate a STOP condition. TWSTO reset
             (0<<TWWC);
        
            __asm__ volatile("nop");
            __asm__ volatile("nop");

            TWCR = (1<<TWEN)|                          // TWI Interface enabled
             (0<<TWIE)|(0<<TWINT)|                  // Disable TWI Interrupt and clear the flag
             (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|       // Initiate a STOP condition. TWSTO reset
             (0<<TWWC);
                                    //
      break;      
        
        case TW_MR_ARB_LOST:          // Arbitration lost
      TWCR = (1<<TWEN)|                                 // TWI Interface enabled
             (1<<TWIE)|(1<<TWINT)|                      // Enable TWI Interupt and clear the flag
             (0<<TWEA)|(1<<TWSTA)|(0<<TWSTO)|           // Initiate a (RE)START condition.
             (0<<TWWC);
                                            //
      break;

        case TW_MT_SLA_NACK:      // SLA+W has been tramsmitted and NACK received
            case TW_MR_SLA_NACK:      // SLA+R has been tramsmitted and NACK received    
                case TW_MT_DATA_NACK:     // Data byte has been tramsmitted and NACK received
                        case TW_NO_INFO:          // No relevant state information available; TWINT = ”0”
                            case TW_BUS_ERROR:        // Bus error due to an illegal START or STOP condition
                                default:    
                            
                                twi_state = TWSR;      // Store TWSR and automatically sets clears noErrors bit.
                                                     // Reset TWI Interface
                          TWCR = (1<<TWEN)|                  // Enable TWI-interface and release TWI pins
                         (0<<TWIE)|(1<<TWINT)|              // Disable Interupt
                         (0<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|   // No Signal requests
                         (0<<TWWC);

                    //delay 100µs
                        _delay_ms (0.1);//100
                            TWCR = (1<<TWEN)|                          // TWI Interface enabled
                     (0<<TWIE)|(0<<TWINT)|                  // Disable TWI Interrupt and clear the flag
                     (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|       // Initiate a STOP condition. TWSTO reset
                     (0<<TWWC);
    }                      

}
инt main(void)
{
for(;;)
{

    if( !(TWCR & _BV(TWIE)) )
    {
            //Check if the last opeation was OK
        if(twi_statusReg.lastReceiveOK) // Last transmission competed successfully.
            twi_get_data_message ( );        
    
        twi_start_data_transceiver( ...);
    }        
}

}


добавил 2 нопа, стал обнуляться TWIE. Потом перестал обнуляться TWIE после ERROR- добавил delay. А сейчас повисает slave, он держит SCL на нуле. Разбираюсь пока. Всем спасибо большое за интерес к моей теме.
bodja74
Цитата(namelos @ Nov 23 2007, 22:34) *
несовсем понятно...начало transreceive пакета реализуется только в случае недействительного TWI Interrupt (TWIE =0)

Не путайте TWIE с TWINT smile.gif
В момент записи TWINT=1 ,TWINT сбрасываетя в 0 ,и дожидаемся на нем 1 как завершение выполнения команды или можем перейти на прерывание.
Цитата
Контроллер не зависает, он из состояния interrupt не выходит, а точнее выходит, но TWIE не обнуляет.

Ну прям сказки smile.gif
(0<<TWIE) и при этом ,постоянно залетает в прерывание smile.gif,скорее всего эта команда и не обрабатывается .
namelos
Цитата(bodja74 @ Nov 24 2007, 00:33) *
Не путайте TWIE с TWINT smile.gif
В момент записи TWINT=1 ,TWINT сбрасываетя в 0 ,и дожидаемся на нем 1 как завершение выполнения команды или можем перейти на прерывание.

Код с atmelskого сайта АN315, кстати я как раз их и не путую. С помощью TWIE я контролирую конец передачи пакета.
bodja74
Цитата(namelos @ Nov 23 2007, 23:38) *
Код с atmelskого сайта АN315, кстати я как раз их и не путую. С помощью TWIE я контролирую конец передачи пакета.


Ваууу!
По TWIE вы контролируете конец передачи пакета или конец выполнения команды smile.gif
namelos
Повторюсь, пакета данных. Если вы посмотрите на Interrupt рутину, там TWIE обнуляется при ошибке, послан весь пакет и TW_MR_DATA_NACK, что означает конец приема пакета.
bodja74
Все ,что может быть понято неправильно ,понимается неправильно. :D

Цитата(namelos @ Nov 23 2007, 22:34) *
несовсем понятно...начало transreceive пакета реализуется только в случае недействительного TWI Interrupt (TWIE =0)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.