John851 0 3 мая, 2010 Опубликовано 3 мая, 2010 · Жалоба Добрый вечер, у меня такая проблемка: mega8 и tiny2313 соединены по I2C. У меги8 интерфейс реализован на модуле TWI (Master), а у tiny2313 на USI(Slave). Оба МК работают от внешних кварцев на 8МГц. Сделал я небольшой протокол по которому мега 8 отсылает байт tiny2313. Он принимает этот байт и решает че делать в зависимости от него: включить или выключить светодиод на одной из ног. Программа которую я зашил в мегу должна была в бесконечном цикле отправлять сначала байт включить светодиод, ждать секунду, затем отправлять выключить светодиод, потом опять ждать секунду и тд. Проблема состоит в том что когда я все запустил, светодиод загорался и погасал в рэндомном порядке, так как практически через раз мастер пропускал ACK, слэйв пропускал или принимал с ошибками байт от мастера (все это я наблюдал на отладочных светодиодах). Вообщем мучался я мучался часа 4, все перепробовал и вот в конце решил сменить частоту шины со 100 Кгц до 400КГц. Врезультате все заработало. Может кто объяснить почему мне помогла смена частоты? Неужели это все из за обрезанного по возможностям USI? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Duhas 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба или из-за ужасной кривости конструкции.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
John851 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба всмысле? USI кривое или у меня монтаж кривой? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Duhas 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба я про монтаж/разводку и прочее... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
John851 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба хм ну так то у меня все собрано на макетной плате, длина шины I2C не более 2 см(2 проводка витой пары), никакой пайки нет, так что я думаю что монтаж тут нипричем ЗЫ модуль TWI меги работает прекрасно с термодатчиком, который тоже I2C (на любой скорости) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skripach 5 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба Резисторы есть? и какие? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
John851 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба есть 10ком Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба есть 10ком Может всё таки от одного кварца оба затактировать Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
John851 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба не вижу смысла тогда в создании I2C, это сейчас они у меня на расстоянии 2 см, а если мне потребуется 15 см или более метра? я же не смогу затактировать их от одного кварца. CKPOT фьюз ксати подключал/отключал разницы нет никакой на 100Кгц Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба не вижу смысла тогда в создании I2C, это сейчас они у меня на расстоянии 2 см, а если мне потребуется 15 см или более метра? я же не смогу затактировать их от одного кварца. Понятно. Пересчёт частоты сами делаете или в теле программы? Т.е. ldi temp,SYSCLK/(2*SCL_Freq)-8;TWI Bit Rate Register - TWBR sts TWBR,temp ;+ Частота TWI=384 Кгц Так автоматом , только значения подставляй Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
John851 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба доверил это дело библиотечной функции, вот ее код void i2cSetBitrate(u16 bitrateKHz) { u08 bitrate_div; // set i2c bitrate // SCL freq = F_CPU/(16+2*TWBR)) #ifdef TWPS0 // for processors with additional bitrate division (mega128) // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) // set TWPS to zero cbi(TWSR, TWPS0); cbi(TWSR, TWPS1); #endif // calculate bitrate division bitrate_div = ((F_CPU/1000l)/bitrateKHz); if(bitrate_div >= 16) bitrate_div = (bitrate_div-16)/2; outb(TWBR, bitrate_div); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба доверил это дело библиотечной функции, вот ее код к сожалению тут не помогу, но по-моему у меня короче. Только наверное надо поменять в SYSCLK/(2*SCL_Freq)-8 . SYSCLK на F_CPU и SCL_Freq на bitrateKHz т.к. они у тебя наверняка описаны, но может кто-то и использовал и там всё в порядке. А так-то твои значения для 400 = 0x02 и для 100 = 0x20 Prescaler=0 Попробуй напрямую подставить Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
John851 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба да я хотел уже было эту функцию основательно проверить, но времени пока нет на проверку Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ILYAUL 0 4 мая, 2010 Опубликовано 4 мая, 2010 · Жалоба да я хотел уже было эту функцию основательно проверить, но времени пока нет на проверку И кстати , не смотрел DS для меги8 , но у неё точно регистр TWBR расположен в области ввода-вывода? P.S Посмотрел , там Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kool 0 6 мая, 2010 Опубликовано 6 мая, 2010 · Жалоба Вы хотя бы код проложили к сообщению. А то гадать "почему не работает" сложно. Хотя в модуле мастера TWI есть один подводный камень: Перед очередной посылкой условия "старт" нужно проверять, завершилось ли формирование на шине предыдущего условия "стоп", т.е. проверять бит TWSTO на равность "0". Так как контроллер устанавливает флаг TWINT сразу после того, как на шине началось формирование условия "стоп", не дожидаясь его завершения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться