Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STR91xFA ARM9 и I2C
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Zandy
Контроллер работает в режиме "Master receiver". Надо принять один байт. Т. е. после приема первого байта выставить "non-acknowledge" и передать стоповую посылку. В документации по поводу "non-acknowledge" сказано следующее: (цитата) "Note: In order to generate the non-acknowledge pulse after the last received data byte, the ACK bit must be cleared just before reading the second last data byte."
Так вот, в чем вопрос. Когда надо очищать ACK бит? Ведь принимаемый байт всего один.
Привожу кусок из примера драйвера I2C (нашел в примерах к Keilу)

Код
     case I2C_EVENT_MASTER_BYTE_RECEIVED:           // EV7

      if ( Rx_Idx == BUFFER_SIZE-2 )
      {
        // Send STOP Condition
        I2C_AcknowledgeConfig (I2C1, DISABLE);
      }  
      if ( Rx_Idx == BUFFER_SIZE-1 )    
      // Send STOP Condition
      I2C_GenerateSTOP(I2C1, ENABLE);
      I2C1_Buffer_Rx[Rx_Idx] = I2C_ReceiveData(I2C1);  
      Rx_Idx++;
      
      break;

В случае единичного байта BUFFER_SIZE = 1 и соответственно условие if ( Rx_Idx == BUFFER_SIZE-2 ) никогда не будет выполняться и отсутствие подтверждения никогда не будет передано.
Так как же быть? Читать два байта, а второй не принимать во внимание?
Два байта принимается нормально, но чтение второго байта уже идет с инкрементированного адреса. (читаю настройки аудиокодека).
Zandy
Прошу прощения, мой вопрос настолько бездарно глуп и очевиден, что никто не отвечает, или просто надо ждать, когда подтянутся более сведующие в этом вопросе товарищи?
Savrik
Цитата(Zandy @ May 3 2010, 20:05) *
Прошу прощения, мой вопрос настолько бездарно глуп и очевиден, что никто не отвечает, или просто надо ждать, когда подтянутся более сведующие в этом вопросе товарищи?


smile.gif а мы все ждали, что Вы загуглитеwink.gif
Ладно.. В спецификации указано, что передача одного байта имеет такой формат(на пальцах): ведущий формирует сигнал СТАРТ-бит, потом происходит передача байта(8 битsmile.gif ), потом один бит подтверждение ACK - приемник удерживает линию в низком состоянии. Подтверждение обязательное.
В конце передачи идет СТОП-бит.
Цитата
Если в пересылке участвует ведущий-приёмник, то он должен сообщить об окончании передачи ведомому-передатчику путем не подтверждения последнего байта.

http://www.itt-ltd.com/reference/ref_i2c.html
Zandy
Savrik, спасибо, конечно, но вы не совсем поняли вопрос. Речь не о передаче, а о приеме мастером, а точнее, о второй фазе приема после рестарта.

Там расклад такой: Сначала мастер дает "рестарт", потом посылает слейв-адрес, бит "чтение", ждет acknowledge от slave. Далее идет прием первого байта. После него уже мастер посылает acknowledge. Далее прием второго байта, опять посылка acknowledge мастером и т. д. В конце последнего принимаемого байта, мастер должен выдать non-acknowledge, и завершить всю процедуру стопом.

Так вот, все это классика, которая ни в комментариях ни в разжевывании не нуждается!!!

Мой вопрос другого касается (см. выше). Еще раз. В документации на контроллер написано: "Note: In order to generate the non-acknowledge pulse after the last received data byte, the ACK bit must be cleared just before reading the second last data byte." Когда я должен очистить ACK bit в случае приема одного единственного байта???!!! Не очищать его я тоже не могу. Ведь ACK bit устанавливается в 1 автоматически и на зануленной SDA линии STOP просто не пройдет. Вот в чем вопрос. Именно тут у меня в мозгах замутнение.
Kane
Цитата(Zandy @ May 3 2010, 23:44) *
"Note: In order to generate the non-acknowledge pulse after the last received data byte, the ACK bit must be cleared just before reading the second last data byte." Когда я должен очистить ACK bit в случае приема одного единственного байта???!!!


Наверное, флаг посылки ACK в этом случае вообще выставлять не надо. "Наверное" - потому, что нормально запустить I2C у нас так и не получилось. Уж больно они намудрили с контроллером i2c, пришлось делать дерганьем ножек. :-(
Zandy
Цитата(Kane @ May 11 2010, 18:21) *
Наверное, флаг посылки ACK в этом случае вообще выставлять не надо. "Наверное" - потому, что нормально запустить I2C у нас так и не получилось. Уж больно они намудрили с контроллером i2c, пришлось делать дерганьем ножек. :-(


Я разобрался-таки. Нашел примерчик работы с EEPROMом по I2C. Non-ack передавать конечно надо, иначе прием циклится. А передавать его надо сразу после первого события EV5 при передаче адреса читаемого регистра.
Насчет дергания ножками, это уж слишком... круто. biggrin.gif
Kane
Можно подробнее, как вы передаете non-ack, заодно может примерчик покажете?
В контроллере управление сигналом ack ведётся через бит ACK регистра I2C_CR. В моем понимании, нулевое значение бита и есть отправка сигнала non-ack. Поэтому при чтении одного байта, сразу после отправки i2c-адреса с битом чтения, мы бит ACK не устанавливаем.
Zandy
Цитата(Kane @ May 19 2010, 22:12) *
Можно подробнее, как вы передаете non-ack, заодно может примерчик покажете?
В контроллере управление сигналом ack ведётся через бит ACK регистра I2C_CR. В моем понимании, нулевое значение бита и есть отправка сигнала non-ack. Поэтому при чтении одного байта, сразу после отправки i2c-адреса с битом чтения, мы бит ACK не устанавливаем.


Вот посмотрите примерчик. https://my.st.com/public/STe2ecommunities/m.../I2C_EEPROM.zip Сделано по-дубовому, но все, как на ладони. Конкретно ответ содержится в функции void I2C_EE_BufferRead(u8* pBuffer, u8 ReadAddr, u16 NumByteToRead) из файла i2c_ee.c
Kane
Смотрел этот пример ранее - у меня он не работает. :-) Закопипастил их код, попробовал вызвать функцию I2C_EE_BufferRead. При чтении буфера виснет на самых первых строках:
Код
/* Send START condition */
  I2C_GenerateStart (I2C0, ENABLE);
  
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C0,I2C_EVENT_MASTER_MODE_SELECT));

Дело в том, что у меня почему-то выставляется другая комбинация бит в событии. По их примеру должны выставиться (I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_M_SL | I2C_FLAG_SB), на самом деле у меня выставляются (I2C_FLAG_EVF | I2C_FLAG_M_SL | I2C_FLAG_SB). Почему так без понятия, если смотреть осциллографом команда start генерится, pull-up резисторы есть.
Zandy
Цитата(Kane @ May 26 2010, 17:27) *
Смотрел этот пример ранее - у меня он не работает. :-) Закопипастил их код, попробовал вызвать функцию I2C_EE_BufferRead. При чтении буфера виснет на самых первых строках:
Код
/* Send START condition */
  I2C_GenerateStart (I2C0, ENABLE);
  
  /* Test on EV5 and clear it */
  while(!I2C_CheckEvent(I2C0,I2C_EVENT_MASTER_MODE_SELECT));

Дело в том, что у меня почему-то выставляется другая комбинация бит в событии. По их примеру должны выставиться (I2C_FLAG_EVF | I2C_FLAG_BUSY | I2C_FLAG_M_SL | I2C_FLAG_SB), на самом деле у меня выставляются (I2C_FLAG_EVF | I2C_FLAG_M_SL | I2C_FLAG_SB). Почему так без понятия, если смотреть осциллографом команда start генерится, pull-up резисторы есть.


У меня все прекрасно работает. К чему вы цепляете I2C? У вас не выставляется I2C_FLAG_BUSY. А это значит, что шина занята чем-то другим и соединение со slave - ус-вом не может быть установлено. Так что, скорее всего надо искать проблему не внутри контроллера, а снаружи. Все-таки посмотрите более внимательно на посылку старта двухлучевиком.
Какая у вас скорость? какие стоят резисторы? какая общая емкость на шине I2C?
Kane
Цитата(Zandy @ May 31 2010, 12:12) *
У вас не выставляется I2C_FLAG_BUSY. А это значит, что шина занята чем-то другим...


Пишу сейчас по памяти, но вроде мы пришли к выводу что, к сожалению, это ничего не значит. :-) Шину смотрели осциллографом: свободна, сигнал start генерится, все его временные соотношения соблюдаются. А busy - нет. :-( К шине подключены 24LC256 + сигнал SCL заведен на FPGA, установлены резисторы 4.7к, емкость не измеряли. Пробовали разные скорости от 400 до 90 Кбит/с. В общем, забив на этот busy, контроллер i2c у нас работал. Но при тестировании, нам удавалось его загонять в такие режимы, из которых он выходил только по передергиванию питания на всем устройстве. В нашем случае такое поведение не приемлемо, поэтому пришлось делать ручную реализацию.
Zandy
Да, действительно, I2C работает как-то не так.
Я вот например не могу отловить бит AF (Acknowledge failure) после фиксации события передачи адреса (ENDAD = 1) в цикле, в случае, когда slave не подтверждает Acknowledge.
Kane
Сталкивались и с таким. :-) Дело в том, что сначала ставится AF, потом ENDAD и при чтении статуса AF сбрасывается. Скорее всего вы в программе 1. ждете флаг ENDAD; 2. потом проверяете AF. Необходимо сменить последовательность проверок, либо ORить прочитанные статусы, а потом уж анализировать что пришло.
Zandy
Цитата(Kane @ Jun 3 2010, 17:02) *
Сталкивались и с таким. :-) Дело в том, что сначала ставится AF, потом ENDAD и при чтении статуса AF сбрасывается. Скорее всего вы в программе 1. ждете флаг ENDAD; 2. потом проверяете AF. Необходимо сменить последовательность проверок, либо ORить прочитанные статусы, а потом уж анализировать что пришло.


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