Перейти к содержанию
    

Впервые для себя запускаю TWI на sam7s.

 

Использована атмеловская lib_twi

 

Запись

int AT91F_TWI_WriteSingle(const AT91PS_TWI pTwi,
                        int SlaveAddr,
                        char *data)
{
    unsigned int end = 0, status, err=0;

    /* Enable Master Mode */
  //  AT91C_BASE_TWI->TWI_CR = AT91C_TWI_MSEN;

    /* Set the TWI Master Mode Register */
    AT91C_BASE_TWI->TWI_MMR =  (SlaveAddr<<16 ) & ~AT91C_TWI_MREAD;

    /* Write the data to send into THR. Start conditionn DADDR and R/W bit
       are sent automatically */
    AT91C_BASE_TWI->TWI_THR = *data;
    
    AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START;

    /* NACK errata handling */
    /* Do not poll the TWI_SR */
    /* Wait 3 x 9 TWCK pulse (max) 2 if IADRR not used, before reading TWI_SR */
    /* From 400Khz down to 1Khz, the time to wait will be in µs range.*/
    /* In this example the TWI period is 1/400KHz */
   AT91F_TWI_WaitMicroSecond (40);

    while (!end)
    {
      status = AT91C_BASE_TWI->TWI_SR;
      if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
      {
        err++;
        end=1;
      }
    /*  Wait for the Transmit ready is set */
      if ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
        end=1;
    }
    AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;
    /* Wait for the Transmit complete is set */
    status = AT91C_BASE_TWI->TWI_SR;
    while (!(status & AT91C_TWI_TXCOMP))
      status = AT91C_BASE_TWI->TWI_SR;

    return err;
}

 

Инициализация (вызывается для 100кГц)

void AT91F_TWI_Open(int TwiClock)
{
    /* Configure TWI PIOs */
    AT91F_TWI_CfgPIO ();

    /* Configure PMC by enabling TWI clock */
    AT91F_TWI_CfgPMC ();

    /* Reset the TWI */
    AT91C_BASE_TWI->TWI_CR = AT91C_TWI_SWRST;

    
    /* Configure TWI in master mode */
    AT91F_TWI_Configure (AT91C_BASE_TWI);


    /* Set TWI Clock Waveform Generator Register */
  //AT91C_BASE_TWI->TWI_CWGR=0x047575;
    AT91F_SetTwiClock(TwiClock);
}

 

Расчёт делителей

void AT91F_SetTwiClock(int TwiClock)
{
  unsigned int cldiv,ckdiv=1;

  /* CLDIV = ((Tlow x 2^CKDIV) -3) x Tmck */
  /* CHDIV = ((THigh x 2^CKDIV) -3) x Tmck */
  /* Only CLDIV is computed since CLDIV = CHDIV (50% duty cycle) */
          cldiv = ( (MCK/(2*TwiClock))-3 ) / pow(2,ckdiv);
  while (  cldiv> 255 )
  {
   ckdiv++;
   cldiv = ( (MCK/(2*TwiClock))-3 ) / pow(2,ckdiv);

  }
  AT91C_BASE_TWI->TWI_CWGR =(ckdiv<<16)|((unsigned int)cldiv << 8)|(unsigned int)cldiv;
}

 

 

Проблема в том, что процедура передачи просто виснит, очевидно не получая из статус регистра TXRDY. TWI инициализирован приведённой выше процедурой.

Я не ошибаюсь, считая, что "железные" проблемы никак не влияют на работу модуля внутри?

Пока не идёт речи о корректности передачи, лишь о факте того, что статус регистр не ведёт себя должным образом.

Есть ли вероятность что модуль битый напрочь?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Запускал TWI на AT91SAM7A3 проблем не было.

Но у меня функция AT91F_SetTwiClock() маленько по другому была.

И еще что цепляется на шину?

Резисторы подтягивающие стоят?

Изменено пользователем Хомяк

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Запускал TWI на AT91SAM7A3 проблем не было.

Но у меня функция AT91F_SetTwiClock() маленько по другому была.

И еще что цепляется на шину?

Резисторы подтягивающие стоят?

 

Эту функцию я правил чуть чуть, думал, мало ли...

 

Подтяжка стоит. Только влияет ли это на процесс обновления регистров самого TWI ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сразу бросается в глаза, что Вы делаете при передаче принудительно START|STOP. По DS на at91Sam7X от октября 2007г., этого делать не надо. А может быть и нельзя. Я тоже долго мучил TWI и столкнулся с проблемой - если при передаче принудительно дернуть START, то последующая операция чтения глючит. Ни старт, ни стоп при передаче не надо включать.

 

Эту функцию я правил чуть чуть, думал, мало ли...

 

Подтяжка стоит. Только влияет ли это на процесс обновления регистров самого TWI ?

 

Влияет. Встречал реализацию (не помню в каком камне), когда аппаратный i2c сильно глючил без подтяжки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сразу бросается в глаза, что Вы делаете при передаче принудительно START|STOP. По DS на at91Sam7X от октября 2007г., этого делать не надо. А может быть и нельзя. Я тоже долго мучил TWI и столкнулся с проблемой - если при передаче принудительно дернуть START, то последующая операция чтения глючит. Ни старт, ни стоп при передаче не надо включать.

Влияет. Встречал реализацию (не помню в каком камне), когда аппаратный i2c сильно глючил без подтяжки.

 

Принудительный старт выставил ради эксперимента. Убрал обратно. Дело в том, что SCL SDA линии красоты ради были подключены через MAX3002 чтобы синхронизировать уровни с 5В, что собственно не диктуется необходимостью (выводы sam7s к 5в терпимы, подтяжка внешняя, 100К припаял для начала). Ради уменьшения глючности отрезал дорожки от MAX3002, соеденил с 5В частью шины напрямую. При инициализации выходит что ключи на ножках sam7s256 открыты, на шине нулевой уровень. Цикл так же виснит. :crying:

Изменено пользователем Goofy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Принудительный старт выставил ради эксперимента. Убрал обратно. Дело в том, что SCL SDA линии красоты ради были подключены через MAX3002 чтобы синхронизировать уровни с 5В, что собственно не диктуется необходимостью (выводы sam7s к 5в терпимы, подтяжка внешняя, 100К припаял для начала). Ради уменьшения глючности отрезал дорожки от MAX3002, соеденил с 5В частью шины напрямую. При инициализации выходит что ключи на ножках sam7s256 открыты, на шине нулевой уровень. Цикл так же виснит. :crying:

 

А 100К не много? Рекомендуют от 5 до 10 ставить. А почему бы не попробовать остановить цикл во время висяка и не посмотреть что лежит в TWI_SR?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А 100К не много? Рекомендуют от 5 до 10 ставить. А почему бы не попробовать остановить цикл во время висяка и не посмотреть что лежит в TWI_SR?

 

Обстановка изменилась.

Для sam7s обязательным судя по всему является

 

AT91C_BASE_PIOA->PIO_MDER=AT91C_PA4_TWCK|AT91C_PA3_TWD;

 

Резисторы переставил на 10к. Однако верхний уровень сигнала явно не 5 вольт. Зависание прекратилось когда на шину подцепил приёмное устройство. Попытка заглянуть в сигнал осцилографом (25рF, TWI инициализируется под частоту 50гц) снова вешает цикл и ничего не наблюдается. Будем разбираться ...

Изменено пользователем Goofy

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я на TWI вешал 24LC256

подтягивал 2к

 

Привожу свой код

Кварц 16МГц работал на частоте квалца , без ФАПЧ

 

//==============================================================================
//  Функция             : AT91F_SetTwiClock
//  Описание            :
//  входные параметры   :
//  выходные параметры  :
//==============================================================================
void AT91F_SetTwiClock(void)
{
  int sclock;

  /* Here, CKDIV = 1 and CHDIV=CLDIV  ==> CLDIV = CHDIV = 1/4*((Fmclk/FTWI) -6)*/

  sclock = (10*MCK /AT91C_TWI_CLOCK);
  if (sclock % 10 >= 5)
      sclock = (sclock /10) - 5;
  else
      sclock = (sclock /10)- 6;
  sclock = (sclock + (4 - sclock %4)) >> 2;    // div 4

  AT91C_BASE_TWI->TWI_CWGR    = ( 1<<16 ) | (sclock << 8) | sclock;
}
//==============================================================================
//  Функция             : AT91F_TWI_Open
//  Описание            :
//  входные параметры   :
//  выходные параметры  :
//==============================================================================
void AT91F_TWI_Open(void)
{
  AT91F_TWI_CfgPIO();                     // configure TWI PIOs
  AT91F_TWI_CfgPMC();                     // enable clock TWI
  AT91F_TWI_Configure (AT91C_BASE_TWI);   // configure in MASTER mode
  AT91F_SetTwiClock();
}
//==============================================================================
//  Функция             : AT91F_TWI_WriteByte
//  Описание            :
//  входные параметры   :
//  выходные параметры  :
//==============================================================================
int AT91F_TWI_WriteByte(const AT91PS_TWI pTwi ,int mode, int int_address, char *data2send, int nb)
{
  unsigned int status,counter=0,error=0;

  // Set TWI Internal Address Register
  if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address;

  // Set the TWI Master Mode Register
  pTwi->TWI_MMR = mode & ~AT91C_TWI_MREAD;
  if(nb <2)
  {
    pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN | AT91C_TWI_STOP;
    pTwi->TWI_THR = *data2send;
  }
  else
  {
    // Set the TWI Master Mode Register
    for(counter=0;counter<nb;counter++)
    {
      pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;
      if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP;
      status = pTwi->TWI_SR;
      if ((status & ERROR) == ERROR) error++;
      while (!(status & AT91C_TWI_TXRDY))
      {
        status = pTwi->TWI_SR;
        if ((status & ERROR) == ERROR) error++;
      }
      pTwi->TWI_THR = *(data2send+counter);
   }
  }
  status = pTwi->TWI_SR;
  if ((status & ERROR) == ERROR) error++;
  while (!(status & AT91C_TWI_TXCOMP))
  {
    status = pTwi->TWI_SR;
    if ((status & ERROR) == ERROR) error++;
  }
  return error;
}
//==============================================================================
//  Функция             : AT91F_TWI_ReadByte
//  Описание            :
//  входные параметры   :
//  выходные параметры  :
//==============================================================================
int AT91F_TWI_ReadByte(const AT91PS_TWI pTwi ,int mode, int int_address, char *data, int nb)
{
  unsigned int status,counter=0,error=0;

  // Set TWI Internal Address Register
  if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address;

  // Set the TWI Master Mode Register
  pTwi->TWI_MMR = mode | AT91C_TWI_MREAD;

  // Start transfer
  if (nb == 1)
  {
    pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_STOP;
    status = pTwi->TWI_SR;
    if ((status & ERROR) == ERROR) error++;
    while (!(status & AT91C_TWI_TXCOMP))
    {
      status = pTwi->TWI_SR;
      if ((status & ERROR) == ERROR) error++;
    }
    *(data) = pTwi->TWI_RHR;
   }
   else
   {
     pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;
     status = pTwi->TWI_SR;
     if ((status & ERROR) == ERROR) error++;

     // Wait transfer is finished
     while (!(status & AT91C_TWI_TXCOMP))
     {
       status = pTwi->TWI_SR;
       if ((status & ERROR )== ERROR) error++;
        if(status & AT91C_TWI_RXRDY)
        {
      *(data+counter++) = pTwi->TWI_RHR;
      if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP;
    }
     }
   }
   return 0;
}
//==============================================================================
//  Функция             :
//  Описание            :
//  входные параметры   :
//  выходные параметры  :
//==============================================================================
void TWI_ReadByte(const AT91PS_TWI pTwi ,int mode, char *data, int nb)
{
  unsigned int status,counter=0;
  // Set TWI Internal Address Register
  // without internal address ??????
  //if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address;

  // Set the TWI Master Mode Register
  // Use MS 7 bits as mode ??????
  pTwi->TWI_MMR = mode | AT91C_TWI_MREAD;

  // Start transfer
  if (nb == 1)
  {
    pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_STOP;
    status = pTwi->TWI_SR;
    //if ((status & ERROR) == ERROR) error++;
    while (!(status & AT91C_TWI_TXCOMP));
    *(data) = pTwi->TWI_RHR;
  }
  else
  {
    pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;
    status = pTwi->TWI_SR;
    // Wait transfer is finished
    while (!(status & AT91C_TWI_TXCOMP))
    {
      AT91F_DBGU_Printk("\n\rTEST_AT91F_TWI_ReadByte_1");
      if(status & AT91C_TWI_RXRDY)
      {
         *(data+counter++) = pTwi->TWI_RHR;
         AT91F_DBGU_Printk("\n\rTEST_AT91F_TWI_ReadByte_2");
         if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP;
         //AT91F_DBGU_Printk("\n\rTEST_AT91F_TWI_ReadByte_3");
      }
    }
  }
}

Изменено пользователем Хомяк

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проблема решилась.

При отсутствии устройства на шине по запрашиваемому адресу, цикл виснит. Буду вводить таймауты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проблема решилась.

При отсутствии устройства на шине по запрашиваемому адресу, цикл виснит. Буду вводить таймауты.

Какое-то время назад тут уже подымалась тема TWI. Тема для меня больная, но повторяться не буду, только выводы:

 

Хотите иметь надежное устройство- делайте софтовый TWI. Чтобы Ваше устройство работало так, как хотите Вы и не зависало от каждой иголки на шине.

 

Подчеркну, это мой личный выстраданный опыт, никому свое мнение навязывать не буду.

Причем это я на других АРМах грыз (AT91RM9200). Но "чуйствую", что уши у проблемы те же.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

всё будет хорошо господа! читайте документ:

http://electronix.ru/forum/index.php?act=A...st&id=16553

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Влияет. Встречал реализацию (не помню в каком камне), когда аппаратный i2c сильно глючил без подтяжки.

а не в процессорах ли ST ?

в подтверждение могу сказать что на STM32 при инициализации TWI в случае неправильной подтяжки

мастер встает в такое кривое состояние что потом никогда не может сгенерировать start condition

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вот у меня такая ситуация, на STM32 не может сгенерировать start,

подтяжка 5 к, на шине еепромка, виснет только при чтении из еепромки,

что поменять с подтяжкой?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

всё будет хорошо господа! читайте документ:

http://electronix.ru/forum/index.php?act=A...st&id=16553

Terrabyte а может быть Вы сможете подитожить инфу по работе i2c ?

и выложить ее на всеобщее обозрение в виде FAQ ?

Готов выдать Вам еще несколько мыслей, но хотелось бы на выходе получить готовую

апликайшен про то как нужно пользоваться i2c на samxxxxx....

Сам буду ей пользоваться..... :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

ИМХО, TWI на SAM7 все же неработоспособен. У меня есть несколько "почти работающих" вариантов, но все они благополучно сыпятся на попытке общения с SAA7113. Софтверный во сто крат лучше, поверьте :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...