|
HMC5843 Honeywell digital compass, I2C communication trouble (MSP430) |
|
|
|
Dec 7 2009, 19:46
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(rezident @ Dec 7 2009, 20:34)  Чтении?  Вроде как запись по осциллограмме получается. Адрес 0x3C=0b00111100. Или я ошибаюсь? Выходит сама м/с растягивает SCL.  Но почему она выдает NACK на запись я не знаю.  Ты не на ту осциллограмму смотрел. Чтение у меня вторая осциллограмма в этой теме. ПРОРЫВ ! Проблема решена, причина найдена (неправильное программирование I2C модуля MSP430) ! (подробнее позже) Сейчас борюсь с тем что при чтении выдает два байта вместо одного, опишу решение обязательно. ================================================================================ Изначально идея состояла в том что бы не использовать прерывания для чтения данных компаса. Не хотелось городить глобальные переменные,флаги, счетчики, делать "роботу" в прерывании... и прочую ерунду - зачем если можно подождать (пусть и в активном ожидании) соответствующих флагов. Моей главной ошибкой было то что я ждал бита UCTXSTT - ждал пока передастся START и адрес Славы (ну логично же! ) Код UCB0CTL1 |= UCTXSTT | UCTR; // Send START, SLAVE ADDR with WRITE // while (UCB0CTL1 & UCTXSTT); а потом уже записывал адрес регистра в буфер передатчика. А не надо было его ждать (почему - не знаю, ведь написано же, флаг очищается после того как передастся START и адрес Славы) Но еще, после передачи устанавливается флаг прерывания передатчика (UCB0TXIFG) сигнализирующий о том что можно записывать данные в буфер передатчика, мол заряжай давай. А понял я когда у меня уже вскипел моск, и я перебрав все варианты (и даже перепробовав разные резисторы) все же решил создать ISR и включить прерывания. Где то глубоко внутри терзало меня сомнение что примеры все написаны с использованием прерываний но я отмахивал это сомнение в конец очереди, так как не очень мне нравиться как сделаны примеры) ... вот рабочая функция, может кому пригодиться: Код #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  - спасибо ребята ! А также Форуму Electronix.ru - давно я так не подсаживался...
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
Dec 8 2009, 18:53
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(Alexashka @ Dec 8 2009, 18:57)  Таки объясните откуда Nax брался? Таймаут в слейве?  Думаю так: Из за того что я ждал больше положенного 9-клок задерживался со стороны микроконтроллера, и компас на нас забивал, потом, когда мы все же давали 9-й клок компасу уже было на нас начхать вот он и делал NACK. На самом деле делать NACK - значит ничего не делать на шине, а вот для ACK надо при девятом клоке удерживать SDA в низком состоянии.
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
Dec 8 2009, 21:11
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(rezident @ Dec 8 2009, 23:02)  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
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
Dec 9 2009, 08:23
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(rezident @ Dec 9 2009, 03:52)  Как я понял, у вас не писался следующий байт в регистр передатчика (не то условие проверяли, UCTXSTT вместо UCBxTXIFG), потому SCL тормозился. Это верно. Цитата(rezident @ Dec 9 2009, 03:52)  А потом у вас генерировалось STOP-условие, невзирая на отсутствие флага UCNACKIFG. Так? Нет, флаг UCNACKIFG был, я его обнаруживал и давал STOP что бы освободить шину. Собственно из за этого флага невозможно было передать байт для записи (адрес регистра компаса)
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
Dec 9 2009, 13:47
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 3-06-06
Пользователь №: 17 742

|
Буквально на днях боролся с аппаратным I2C на процессоре F1611, в итоге так и не смог его заставить работать (точнее, смог, но были какие-то паранормальные ошибки). Осциллографа под рукой, к сожалению, не было, поэтому точно сказать что происходило на шине не могу, но по косвенным признакам не формировался STOP после передачи заданного числа байт, приходилось формировать его вручную. Читал Errat-у по этому камню, там куча проблем с I2C, видимо, я на одну из них и напоролся.
Вылечилось все только программной реализацией I2C..
--------------------
Good News Everyone!
|
|
|
|
|
Dec 9 2009, 14:07
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(Pavel V. @ Dec 9 2009, 15:47)  Читал Errat-у по этому камню, там куча проблем с I2C, видимо, я на одну из них и напоролся.
Вылечилось все только программной реализацией I2C.. Таки да, граблей с I2C там хватает. Перед тем как вскипятить себе мозг на MSP430F2471 я работал с MSP430F2274 (eZ430-RF2500) хотел подключить туда компас. В Errata проблема не описана но при работе линия SCL всегда была в нуле - что я только не делал. http://e2e.ti.com/forums/p/9665/51804.aspx#51804Поделись ка программной реализацией I2C пожалуйста ?
Причина редактирования: Излишнее цитирование.
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
Dec 9 2009, 14:28
|

Местный
  
Группа: Свой
Сообщений: 211
Регистрация: 3-06-06
Пользователь №: 17 742

|
Цитата(Kaplinsky @ Dec 9 2009, 17:07)  Поделись ка программной реализацией I2C пожалуйста ? Прикрепил к сообщению библиотечку. Использую ее для работы с часами PCF8563, весьма стабильно и предсказуемо, в отличие от аппаратной реализации Использовать примерно так: Код 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 ( 1.05 килобайт )
Кол-во скачиваний: 46
--------------------
Good News Everyone!
|
|
|
|
|
Feb 1 2011, 08:04
|
Участник

Группа: Участник
Сообщений: 56
Регистрация: 29-09-10
Пользователь №: 59 820

|
Преречитываю в который раз как увлекательный роман. Надо было пройти этим путём, чтобы оценить. КЛАСС!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|