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

2 Resident: Паузы при чтении нет, как видно на осциллограмме.
Чтении? :cranky: Вроде как запись по осциллограмме получается. Адрес 0x3C=0b00111100. Или я ошибаюсь?

В чем же дело ?
Выходит сама м/с растягивает SCL. :laughing: Но почему она выдает NACK на запись я не знаю. :(

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


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

Чтении? :cranky: Вроде как запись по осциллограмме получается. Адрес 0x3C=0b00111100. Или я ошибаюсь?

Выходит сама м/с растягивает SCL. :laughing: Но почему она выдает NACK на запись я не знаю. :(

Ты не на ту осциллограмму смотрел. Чтение у меня вторая осциллограмма в этой теме.

 

 

ПРОРЫВ !

Проблема решена, причина найдена (неправильное программирование I2C модуля MSP430) !

(подробнее позже)

 

Сейчас борюсь с тем что при чтении выдает два байта вместо одного, опишу решение обязательно.

 

 

================================================================================

 

Изначально идея состояла в том что бы не использовать прерывания для чтения данных компаса.

Не хотелось городить глобальные переменные,флаги, счетчики, делать "роботу" в прерывании... и прочую ерунду - зачем если можно подождать (пусть и в активном ожидании) соответствующих флагов.

 

Моей главной ошибкой было то что я ждал бита UCTXSTT - ждал пока передастся START и адрес Славы (ну логично же! )

 

  UCB0CTL1 |= UCTXSTT | UCTR;                   // Send START, SLAVE ADDR with WRITE
//  while (UCB0CTL1 & UCTXSTT);

 

а потом уже записывал адрес регистра в буфер передатчика.

А не надо было его ждать (почему - не знаю, ведь написано же, флаг очищается после того как передастся START и адрес Славы)

Но еще, после передачи устанавливается флаг прерывания передатчика (UCB0TXIFG) сигнализирующий о том что можно записывать данные в буфер передатчика, мол заряжай давай.

 

А понял я когда у меня уже вскипел моск, и я перебрав все варианты (и даже перепробовав разные резисторы) все же решил создать ISR и включить прерывания. Где то глубоко внутри терзало меня сомнение что примеры все написаны с использованием прерываний но я отмахивал это сомнение в конец очереди, так как не очень мне нравиться как сделаны примеры)

 

...

:rolleyes:

 

вот рабочая функция, может кому пригодиться:

 

#define NACK_TX -1
#define NACK_RX -2

int I2C_Read(unsigned char addr, unsigned char *data, int cnt){
int result,i;  

  result = 0;

  UCB0CTL1 |= UCTXSTT | UCTR;                   // Send START, SLAVE ADDR with WRITE
//  while (UCB0CTL1 & UCTXSTT);
  
  
  while (!(IFG2 & UCB0TXIFG)) if (UCB0STAT & UCNACKIFG){
                                result = NACK_TX;
                                goto STOP;
                              }
  UCB0TXBUF = addr;
  
  while (!(IFG2 & UCB0TXIFG)) if (UCB0STAT & UCNACKIFG){
                                result = NACK_TX;
                                goto STOP;
                              }
  
  UCB0CTL1 &= ~UCTR;
  UCB0CTL1 |= UCTXSTT;                            // Send START, SLAVE ADDR with WRITE

  for (i=0;i<cnt;i++){
  
    while (!(IFG2 & UCB0RXIFG)) if (UCB0STAT & UCNACKIFG){
                                  result = NACK_RX;
                                  goto STOP;
                                }
  
    data[i] = UCB0RXBUF; 
    
  }//for
  
STOP:  
  UCB0CTL1 |= UCTXSTP;
  while (UCB0CTL1 & UCTXSTP);                     // Ensure stop condition got sent

  if (IFG2 & UCB0RXIFG) UCB0RXBUF;
  
  return result;
  
}//I2C_Read

 

Благодарю всех кто откликнулся: Alexashka, jam, rezident :cheers: - спасибо ребята !

А также Форуму Electronix.ru - :a14:

 

давно я так не подсаживался...

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


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

Таки объясните откуда Nax брался? Таймаут в слейве? :)

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


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

Таки объясните откуда Nax брался? Таймаут в слейве? :)

 

Думаю так: Из за того что я ждал больше положенного 9-клок задерживался со стороны микроконтроллера, и компас на нас забивал, потом, когда мы все же давали 9-й клок компасу уже было на нас начхать вот он и делал NACK. На самом деле делать NACK - значит ничего не делать на шине, а вот для ACK надо при девятом клоке удерживать SDA в низком состоянии.

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


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

когда мы все же давали 9-й клок компасу уже было на нас начхать вот он и делал NACK. На самом деле делать NACK - значит ничего не делать на шине, а вот для ACK надо при девятом клоке удерживать SDA в низком состоянии.
ACK - ACKnowledge (подтверждение), NACK - No ACKnowledge (отсутствие подтверждения). Согласно спецификации I2C, минимальная частота обмена на шине не ограничена, т.е. шина по сути полностью статическая. В отличие от SMBUS, например. Так что slave "начхать" на дешифрацию своего адреса никак не может (не имеет права), если только у него не аварийная ситуация при которой он не может корректно функционировать. Так что ваши догадки выглядят не очень убедительно. Может вы функцию инициализации модуля USCI еще до кучи приведете?

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


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

ACK - ACKnowledge (подтверждение), NACK - No ACKnowledge (отсутствие подтверждения). Согласно спецификации I2C, минимальная частота обмена на шине не ограничена, т.е. шина по сути полностью статическая. В отличие от SMBUS, например. Так что slave "начхать" на дешифрацию своего адреса никак не может (не имеет права), если только у него не аварийная ситуация при которой он не может корректно функционировать. Так что ваши догадки выглядят не очень убедительно. Может вы функцию инициализации модуля USCI еще до кучи приведете?

 

ОК, Слава дешифровал свой адрес, готов выдать ACK но 9-го клока все нет и нет. ( ну по крайней мере у меня других идей нет почему оно не работало раньше)

 

инициализация I2C:

 

void I2C_Init(unsigned char s_addr){
  P3SEL |= 0x06;

  UCB0CTL1 |= UCSWRST;
  
  UCB0CTL0 = UCMST | UCMODE_3 | UCSYNC;
  UCB0CTL1 = UCSSEL_3 + UCSWRST;

/* BASE FREQ (SMCLK) 8 Mhz
  0x0020 - 400 Kbs
  0x0050 - 100 Kbs
  0x0320 - 10 Kbs
  0x1F40 - 1 Kbs  */  
  
  UCB0BR0 = 0x50;
  UCB0BR1 = 0x00;
  
  UCB0I2COA = 0x01;
  UCB0I2CSA = s_addr;
  
  UCB0CTL1 &= ~UCSWRST;                     // Clear SW reset, resume operation
  IFG2 &= ~ (UCB0TXIFG | UCB0RXIFG);
    
}//I2C_Init

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


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

ОК, Слава дешифровал свой адрес, готов выдать ACK но 9-го клока все нет и нет.
Как я понял, у вас не писался следующий байт в регистр передатчика (не то условие проверяли, UCTXSTT вместо UCBxTXIFG), потому SCL тормозился. А потом у вас генерировалось STOP-условие, невзирая на отсутствие флага UCNACKIFG. Так?

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


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

Как я понял, у вас не писался следующий байт в регистр передатчика (не то условие проверяли, UCTXSTT вместо UCBxTXIFG), потому SCL тормозился.

Это верно.

 

А потом у вас генерировалось STOP-условие, невзирая на отсутствие флага UCNACKIFG. Так?

Нет, флаг UCNACKIFG был, я его обнаруживал и давал STOP что бы освободить шину.

Собственно из за этого флага невозможно было передать байт для записи (адрес регистра компаса)

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


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

Буквально на днях боролся с аппаратным I2C на процессоре F1611, в итоге так и не смог его заставить работать (точнее, смог, но были какие-то паранормальные ошибки). Осциллографа под рукой, к сожалению, не было, поэтому точно сказать что происходило на шине не могу, но по косвенным признакам не формировался STOP после передачи заданного числа байт, приходилось формировать его вручную. Читал Errat-у по этому камню, там куча проблем с I2C, видимо, я на одну из них и напоролся.

 

Вылечилось все только программной реализацией I2C..

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


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

Читал Errat-у по этому камню, там куча проблем с I2C, видимо, я на одну из них и напоролся.

 

Вылечилось все только программной реализацией I2C..

Таки да, граблей с I2C там хватает.

Перед тем как вскипятить себе мозг на MSP430F2471 я работал с MSP430F2274 (eZ430-RF2500) хотел подключить туда компас. В Errata проблема не описана но при работе линия SCL всегда была в нуле - что я только не делал.

http://e2e.ti.com/forums/p/9665/51804.aspx#51804

 

Поделись ка программной реализацией I2C пожалуйста ?

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


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

Поделись ка программной реализацией I2C пожалуйста ?

 

Прикрепил к сообщению библиотечку. Использую ее для работы с часами PCF8563, весьма стабильно и предсказуемо, в отличие от аппаратной реализации :unsure:

 

Использовать примерно так:

 

uint8_t pcf8563_get_byte(uint8_t addr)
{
    i2cStart();
    i2cWrite(0xA2);
    i2cWrite(addr);
    i2cStart();
    i2cWrite(0xA3);
    uint8_t ret = i2cRead(0);
    i2cStop();

    return ret;
}

void pcf8563_set_byte(uint8_t addr, uint8_t value)
{
    i2cStart();
    i2cWrite(0xA2);
    i2cWrite(addr);
    i2cWrite(value);
    i2cStop();
}

 

Удачи!

i2c.zip

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


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

Преречитываю в который раз как увлекательный роман. Надо было пройти этим путём, чтобы оценить. КЛАСС!

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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