|
|
  |
MSP430 и I2C. Постоянно - UCBBUSY. |
|
|
|
Sep 1 2011, 09:10
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-06-11
Пользователь №: 65 710

|
Добрый день. Есть микроконтроллер MSP40F5438 и не могу побороть проблему замкнутого цикла while( UCB1STAT & UCBBUSY ); Поиск показал, что я не одинок, и нашел информацию о том, что необходимо реализовывать I2C Bus Clear, из спецификации. Для этого написал простой цикл( здесь, и далее я использую UCB1, у которого PORT5.4 - SCL, PORT3.7 - SDA): Код P5DIR |= BIT4; P5SEL &= ~BIT4; P5OUT &= ~BIT4; for( pulseCounter = 0; pulseCounter < 9; pulseCounter++ ) { P5OUT |= BIT4; __delay_cycles( 100 ); P5OUT &= ~BIT4; __delay_cycles( 100 ); } P5OUT |= BIT4; P5SEL |= BIT4; После его выполнения, шина по прежнему остается занятой. Микроконтроллер работает на частоте 25МГц поэтому __delay_cycles( 100 ); дает задержку в 5мкс. Как все таки правильно делать ресет шины? Единственное, что пока я нашел, что шина становится свободной, как только я переподключаю девайс с которым общаюсь. Протокол обмена с девайсом прост - изначально контроллер и девайс находятся в режиме в slave-receiver, а переключаются в master-transmitter только когда нужно что-то передать. После конфигурирования, мне необходимо инициализировать девайс, но это невозможно т.к шина занята. Спасибо за любые идеи.
|
|
|
|
|
Sep 2 2011, 07:25
|
Группа: Новичок
Сообщений: 8
Регистрация: 15-06-11
Пользователь №: 65 710

|
Цитата(KARLSON @ Sep 1 2011, 16:53)  А до того как подключили девайс к шине, на шине какие уровни по напряжению? И зря так делаете P5OUT |= BIT4; Вы управляйте направлением порта а не его логикой. OUT = 0; а потом либо DIR |= BIT4; либо DIR &= ~BIT4; К сожалению уровни посмотреть не могу, пишут под собранную железку и никуда не добраться. Цитата(rezident @ Sep 1 2011, 17:37)  Во-первых, вам правильно сделали замечание насчет управления лог.1 записью в P5OUT. Шина I2C управляется открытым коллектором или открытым стоком. Поэтому лог.1 нужно формировать, запрограммировав пин как вход, а не как выход с лог.1. Во-вторых, в нормальном состоянии на шине I2C лог.1, а вы как-то странно заканчиваете цикл Bus clear выдавая лог.0 на SCL. Это неправильно. нужно освободить SCL, установив лог.1 в конце Bus clear. В-третьих, Bus clear нужно выполнять до инициализации модуля I2C. Ну или после процедуры Bus clear (ре)инициализировать его вновь. Ну и в-четвертых, "глупый" вопрос. У вас вообще pull-up резисторы на шине имеются? Pull-up резисторы есть. Т.е выходит, что цикл инициализации USCI в режим I2C начинать с UCB1STAT & UCBBUSY, и если вернет истину, то делать сброс, а потом конфигурировать? Я заметил дебаггером, что флаг UCBBUSY устанавливается уже после инициализации, а не до того. В этом случае делаем Bus clear, и после него инициализировать все заново? Поправил Bus clear функцию: Код void vI2CBusClear() { char pulseCounter = 0; P5SEL &= ~BIT4; P5OUT &= ~BIT4; for( pulseCounter = 0; pulseCounter < 9; pulseCounter++ ) { P5DIR ^= BIT4; __delay_cycles( 100 ); } P5DIR &= ~BIT4; P5SEL |= BIT4; } Спасибо.
Сообщение отредактировал devfom - Sep 2 2011, 07:28
|
|
|
|
|
Jun 9 2012, 03:59
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177

|
Во-первых, вам правильно сделали замечание насчет управления лог.1 записью в P5OUT. Шина I2C управляется открытым коллектором или открытым стоком. Поэтому лог.1 нужно формировать, запрограммировав пин как вход, а не как выход с лог.1. Насчет этого не очень понятно. Если порт поставить на вход, то как тогда подавать импульсы?
П.С. Такая же проблема
|
|
|
|
|
Jun 9 2012, 04:42
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177

|
Я и так аппаратный использую. Но в msp340f47187, насколько я понимаю, нет аппаратного BusClear. Поэтому приходится перенастраивать порты (SEL = 0), а после давать импульсы. Или я где-то не прав... И... насколько я понимаю, импульсы нужно подавать только на SCL? в спецификации написано:
... If the data line (SDA) is stuck LOW, the master should send nine !!clock pulses!!...
И, может быть, задаю глупый вопрос: объясните почему если порт настроен на вход, то будет лог 0, а если на выход, то будет лог 1?
И почему так делать лучше, чем через OUT = 0/1
|
|
|
|
|
Jun 9 2012, 04:43
|

Знающий
   
Группа: Свой
Сообщений: 604
Регистрация: 5-05-06
Из: Нижегородская обл.
Пользователь №: 16 819

|
Я же написал наоборот. Вход это 1, выход это 0. Аппаратный я использовал во втором семействе. Никаких проблем не было. Если Вы мастер, то и SCL и SDA дёргать надо, если нет то только SDA. Цитата(mib383 @ Jun 9 2012, 08:42)  И почему так делать лучше, чем через OUT = 0/1 Когда у slave будет 0, а вы раз так и OUT = 1 сделаете, то получится КЗ по питанию. 3В на GND и скорее всего порты выгорят.
Сообщение отредактировал KARLSON - Jun 9 2012, 04:49
--------------------
Кризис - это не отсутствие денег, а отсутствие идей! Учитесь и никаких кризисов не будет.
|
|
|
|
|
Jun 9 2012, 04:47
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177

|
Спасибо. Но, честно говоря все равно не очень понятно.
|
|
|
|
|
Jun 9 2012, 04:57
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177

|
Ну допустим, почему если я мастер, нужно дергать обе линии, а не только SCL. Ведь в спецификации этого нет...
И вы говорите, что использовали аппаратный, и bus clear делать не приходилось? Если так, может у меня в программе не все гладко...
Сообщение отредактировал mib383 - Jun 9 2012, 05:01
|
|
|
|
|
Jun 9 2012, 07:04
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 4-04-12
Пользователь №: 71 177

|
Обнаружил, что после выставления адреса и настройки i2c на передачу нужна задержка перед стартовым состоянием. Не могу понять почему?
Снимаю вопрос) Разобрался, дело было не в этом
|
|
|
|
|
Jun 10 2012, 05:46
|
Местный
  
Группа: Участник
Сообщений: 356
Регистрация: 24-02-09
Пользователь №: 45 309

|
Есть ещё предположение, что иногда STOP в конце BusClear может не сработать - если подчинённое устройство выдаст в это время ACK на шину (если ведомый IIC был как Slave Transmitter). Потому, для надёжности я добавил сегодня STOP ещё ДО 10 тактов на линии SCL, а линию SDA использую как открытый коллектор чтоб уменьшить энергопотребление. В итоге всё выглядит так: 1. Бит Pout(SDA)=0 (для будущей имитации открытого коллектора на линии SDA с применением регистра Pdir). 2. Pdir(SCL)=1, Pout(SCL)=0. 3. Pdir(SDA)=1 на линиях SCL и SDA получился ноль - исходная позиция для STOP. 4. Pout(SCL)=1, Pdir(SDA)=0 провёл первый STOP на шине. 5. 10 тактов SCL в последовательности 1,0;1,0;... 1,0 6. Pdir(SDA)=1 на линиях SCL и SDA ноль - исходная позиция для второго STOP. 7. Pout(SCL)=1, Pdir(SDA)=0 провёл второй STOP на шине. 8. Перевод выводов под управление модуля USCI записью 1 в порт PSEL. В таком виде BusClear наверное ещё надёжнее. Если первый STOP придётся на ACK подчинённого, то после 10 тактов на линии SCL, второй STOP попадёт уже в точку  Вот ещё что... У меня все устройства I2C не запускают никаких действий по сигналу STOP, потому я применяю STOP для BusClear (а одно устройство даже требует STOP для завершения обмена - иначе оно за себя не ручается  (барометр BMP085) ). А если на шине I2C есть флешка - то лучше наверное ограничиться классическим BusClear из только из 9 тактов SCL...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|