devfom 0 1 сентября, 2011 Опубликовано 1 сентября, 2011 · Жалоба Добрый день. Есть микроконтроллер 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 только когда нужно что-то передать. После конфигурирования, мне необходимо инициализировать девайс, но это невозможно т.к шина занята. Спасибо за любые идеи. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KARLSON 1 1 сентября, 2011 Опубликовано 1 сентября, 2011 (изменено) · Жалоба А до того как подключили девайс к шине, на шине какие уровни по напряжению? И зря так делаете P5OUT |= BIT4; Вы управляйте направлением порта а не его логикой. OUT = 0; а потом либо DIR |= BIT4; либо DIR &= ~BIT4; Изменено 1 сентября, 2011 пользователем KARLSON Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 1 сентября, 2011 Опубликовано 1 сентября, 2011 · Жалоба Во-первых, вам правильно сделали замечание насчет управления лог.1 записью в P5OUT. Шина I2C управляется открытым коллектором или открытым стоком. Поэтому лог.1 нужно формировать, запрограммировав пин как вход, а не как выход с лог.1. Во-вторых, в нормальном состоянии на шине I2C лог.1, а вы как-то странно заканчиваете цикл Bus clear выдавая лог.0 на SCL. Это неправильно. нужно освободить SCL, установив лог.1 в конце Bus clear. В-третьих, Bus clear нужно выполнять до инициализации модуля I2C. Ну или после процедуры Bus clear (ре)инициализировать его вновь. Ну и в-четвертых, "глупый" вопрос. У вас вообще pull-up резисторы на шине имеются? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
devfom 0 2 сентября, 2011 Опубликовано 2 сентября, 2011 (изменено) · Жалоба А до того как подключили девайс к шине, на шине какие уровни по напряжению? И зря так делаете P5OUT |= BIT4; Вы управляйте направлением порта а не его логикой. OUT = 0; а потом либо DIR |= BIT4; либо DIR &= ~BIT4; К сожалению уровни посмотреть не могу, пишут под собранную железку и никуда не добраться. Во-первых, вам правильно сделали замечание насчет управления лог.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; } Спасибо. Изменено 2 сентября, 2011 пользователем devfom Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mib383 0 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Во-первых, вам правильно сделали замечание насчет управления лог.1 записью в P5OUT. Шина I2C управляется открытым коллектором или открытым стоком. Поэтому лог.1 нужно формировать, запрограммировав пин как вход, а не как выход с лог.1. Насчет этого не очень понятно. Если порт поставить на вход, то как тогда подавать импульсы? П.С. Такая же проблема Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KARLSON 1 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба регистр OUT = 0, как для вывода SCL так и для вывода SDA. На этих линиях должны быть резисторы подвешенные к 3 В, примерно 5-15 кОм. Что бы сделать логическую "1" на линии, нужно порт сделать входом, PxDIR &= ~BITx; что бы сделать логический "0" необходимо порт сделать выходом, PxDIR |= BITx; А лучше использовать аппаратный I2C. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mib383 0 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Я и так аппаратный использую. Но в 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KARLSON 1 9 июня, 2012 Опубликовано 9 июня, 2012 (изменено) · Жалоба Я же написал наоборот. Вход это 1, выход это 0. Аппаратный я использовал во втором семействе. Никаких проблем не было. Если Вы мастер, то и SCL и SDA дёргать надо, если нет то только SDA. И почему так делать лучше, чем через OUT = 0/1 Когда у slave будет 0, а вы раз так и OUT = 1 сделаете, то получится КЗ по питанию. 3В на GND и скорее всего порты выгорят. Изменено 9 июня, 2012 пользователем KARLSON Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mib383 0 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Спасибо. Но, честно говоря все равно не очень понятно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KARLSON 1 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Что именно не понятно? Пока вы отвечали, я редактировал своё предыдущее сообщение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mib383 0 9 июня, 2012 Опубликовано 9 июня, 2012 (изменено) · Жалоба Ну допустим, почему если я мастер, нужно дергать обе линии, а не только SCL. Ведь в спецификации этого нет... И вы говорите, что использовали аппаратный, и bus clear делать не приходилось? Если так, может у меня в программе не все гладко... Изменено 9 июня, 2012 пользователем mib383 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
mib383 0 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба Обнаружил, что после выставления адреса и настройки i2c на передачу нужна задержка перед стартовым состоянием. Не могу понять почему? Снимаю вопрос) Разобрался, дело было не в этом Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
controller_m30 1 9 июня, 2012 Опубликовано 9 июня, 2012 · Жалоба На MSP430F5342 делаю BusClear так... 1. При инициализации портов настраиваю линию порта SCL в out, а SDA в in. 2. Делаю 10 тактов SCL в последовательности 1,0;1,0;... 1,0 3. Перевод SDA в out, уровень SDA=0. 4. Сигнал STOP - SCL=1 и после этого SDA=1 5. Перевод выводов под управление модуля USCI записью 1 в порт PSEL. Все изменения уровней делаются с задержкой чтоб соблюсти скорость не выше 100кГц. Работает такой BusClear у меня уверенно. Проц находится в непрерывном опросе трёх IIC устройств, сброс и снятие питания делается часто (откл. батареек, подключение к программатору и проч.) - шина I2C всё время доступна. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
controller_m30 1 10 июня, 2012 Опубликовано 10 июня, 2012 · Жалоба Есть ещё предположение, что иногда 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 попадёт уже в точку :rolleyes: :excl: Вот ещё что... У меня все устройства I2C не запускают никаких действий по сигналу STOP, потому я применяю STOP для BusClear (а одно устройство даже требует STOP для завершения обмена - иначе оно за себя не ручается (барометр BMP085) ). А если на шине I2C есть флешка - то лучше наверное ограничиться классическим BusClear из только из 9 тактов SCL... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться