Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7S128: снова TWI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
vet
По непонятной причине портится последний байт при чтении данных из устройства (I2C FRAM).

Процедура чтения, запускающая обмен по прерываниям:
Код
  //buf - буфер чтения, len - сколько байт читать

  if (len>1) {
    *AT91C_TWI_CR = AT91C_TWI_START;
    *AT91C_TWI_IER = AT91C_TWI_RXRDY | AT91C_TWI_NACK | AT91C_TWI_OVRE;
  }
  else {
    *AT91C_TWI_CR = AT91C_TWI_START | AT91C_TWI_STOP;
    *AT91C_TWI_IER = AT91C_TWI_TXCOMP;
  }
  WAIT(semaphore, timeout); //ждать окончания приёма


Обработчик прерывания TWI; показано только чтение, обработка ошибок убрана:
Код
void TWI_ISRHandler() {
  unsigned int status;

  status = *AT91C_TWI_SR;    //маска событий
  status &= *AT91C_TWI_IMR;

  *AT91C_AIC_IVR   = 0;                /* Debug variant of vector read (protect mode is used)  */
  *AT91C_AIC_ICCR  = 1<<AT91C_ID_TWI;  /* Clear TWI interrupt                                  */

  if (status&AT91C_TWI_TXCOMP) { //STOP передан, дождаться последнего байта
    *AT91C_TWI_IDR = 0xFFFFFFFF;
    *AT91C_TWI_IER = AT91C_TWI_RXRDY;
  }

  if (status&AT91C_TWI_RXRDY) {  //принят байт
    char n = *AT91C_TWI_RHR;    //очистить приемник, снять RXRDY
    *buf++ = n; //записать принятый байт в буфер
    if (len>1) {
      if (--len==1) {     //принят предпоследний байт - послать STOP и принять последний байт
        *AT91C_TWI_IDR = 0xFFFFFFFF;
        *AT91C_TWI_CR = AT91C_TWI_STOP;
        *AT91C_TWI_IER = AT91C_TWI_TXCOMP;
      }
    }
    else {                       //принят последний байт
      *AT91C_TWI_IDR = 0xFFFFFFFF;
      SIGNAL(semaphore);    //завершить чтение, вернуть управление вызывающей процедуре
    }
  }

  *AT91C_AIC_EOICR = 0;                /* Signal end of interrupt                              */
}


Если читаю из уст-ва один байт, ошибок нет. Если несколько - последний байт считывается неверно. Посоветуйте, как с этим бороться?
zhek
Вот и я до TWI добрался. Два дня парюсь, уже думаю сделать его программно, ножками дергать. Вопрос такой: удалось заставить его работать? У меня по коду (выше) есть предположения, но он, наверное, изменился?

Вообще толково придумано, что надо каждый байт отслеживать и суметь твй вовремя заткнуть, а то будет колбасить до посинения. И еще статус читать нельзя, а то "may be lost".
zhek
И, похоже, прерывания не по всякому флагу можно делать
vet
По теме - обошёлся приёмом лишнего байта с последующим его игнорированием. В остальном код не изменился.
aaarrr
А зачем на предпоследнем байте прерывания приема запрещать?
Похоже, тут ваш байт и теряется.
vet
Он принимается после посылки STOP и последующего обнаружения AT91C_TWI_TXCOMP; но принимается неправильный байт.
Есть мнение, что при приёме нескльких байт с устройства надо поменять местами эти две стадии, но проверить сейчас не могу - проект закончен, и пока что я к ARM не возвращался.
aaarrr
Цитата(vet @ Apr 12 2006, 13:38) *
Он принимается после посылки STOP и последующего обнаружения AT91C_TWI_TXCOMP; но принимается неправильный байт.
Есть мнение, что при приёме нескльких байт с устройства надо поменять местами эти две стадии, но проверить сейчас не могу - проект закончен, и пока что я к ARM не возвращался.


Правильное мнение, но и с прерываниями так обращаться все же не стоит.
Одна из возможных причин потери байта описана в errat'е.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.