|
Помогите советом. I2C, Мож кто сталкивался. |
|
|
|
 |
Ответов
(1 - 49)
|
Jun 17 2007, 13:37
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(SasaVitebsk @ Jun 17 2007, 17:20)  ...удалено.... А какая частота шины i2c ? 3,9K может быть многовато при большом количестве устройств(емкость шины). Попробуйте уменьшить до 2,7 или даже до 1,5. У меня при pullup 4,7 отказывалось работать при 400KHz с FRAM, а при 1,5K завелось на 1,4MHz (не с Atmega).
Сообщение отредактировал zltigo - Jun 17 2007, 13:47
|
|
|
|
|
Jun 17 2007, 14:18
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Jun 17 2007, 18:04)  То:singlskv - насточтельная просьба избегать совершенно не нужных цитирований. Эээ... привычка, когда отвечаешь в длинной ветке нужно обозначить кому отвечаешь. В данном случае это конечно было не нужно Цитата мне попалась в свое время отладочная борда от Olimex, где болгарские друзья вообще не развели один из подтягивающих резисторов (кажется SDA) к Микрочиповской EEPROM. Каким чудом на утечках хоть на пониженной частоте со сташными сбоями, но работало непонятно! Ну все-таки наверное работало на внутреннем пулапе ? Вроде как i2c по стандарту умеет тянуть только вниз, и если вобще нет пулапа то там должен быть всегда 0. Хотя конечно реализации на разных контроллерах могут достаточно сильно отличатся от стандарта
|
|
|
|
|
Jun 17 2007, 16:33
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(SasaVitebsk @ Jun 17 2007, 20:15)  Экспериментировал от 1МГц до 100кГц. На высоких скоростях колличество сбоев увеличивается, но до определённого порядка. Начиная примерно с 360кГц количество сбоев от тактовой частоты не зависит. пулап все-таки попробуйте поменьше, хотя бы просто для эксперимента Цитата Только запись пакетную делал один раз. Но задержки ставил большие. А сейчас впритык. Сам уже не знаю где рыть. Пока ни одной ошибки не нашёл. Создаётся ощущение что проблема с вызывом прерываний в определённых местах. Так как ошибки проявляются только при значительных объёмах (практически непрерывной работе) передаваемой от I2C инфы. Возможно из-за софтового I2C. Задержки между каждым пакетом или между обращениями к разным устройствам ? Ошибки только с 24с512 или с mega48 тоже ? На mega48 обработка через прерывания ? Ошибки с 24xx случайно происходят не после общения с мегой без паузы ? Какая частота ошибок (примерно) ? Ну и код общения через i2c(на мегах) лучше конечно покажите... Для редко возникающих ошибок знаю одну багу/фичу...
|
|
|
|
|
Jun 17 2007, 17:24
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Jun 17 2007, 21:00)  Никаких фокусов - сигнал при рассмотрении осциллографом был жутчайший, но как-то иногда понимался взаимодействующими сторонами. Ну а иметь хорошие I2C контроллеры Филипса положение обязывает  . Положение то обязывает, но вот попробуйте объяснить мне, откуда там в сигнале могли единички появлятся при полном отсутствии пулапов. То что на i2c сигналы тянутся только к 0, принципиально, т.к. иначе сложно реализовать мультимастер.
|
|
|
|
|
Jun 17 2007, 18:13
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Jun 17 2007, 20:24)  но вот попробуйте объяснить мне, откуда там в сигнале могли единички появлятся при полном отсутствии пулапов. Нормального сигнала не было, но наводки с соседнего клока были по этим фронтам оно все как-то жило. Цитата То что на i2c сигналы тянутся только к 0.... Я не запрашивал курс ликбеза и объяснений почему не могло работать, то, что хоть хреново, но работало на моих глазах.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 17 2007, 18:44
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Jun 17 2007, 22:13)  Нормального сигнала не было, но наводки с соседнего клока были по этим фронтам оно все как-то жило. Я не запрашивал курс ликбеза и объяснений почему не могло работать, то, что хоть хреново, но работало на моих глазах. Ну я вобще-то и не собирался устраивать ликбез, только вот для меня осталось странным, что получив подобный результат Вы не разобрались в чем была фишка... Ну не должно было там быть единички, а Вы говорите что была и все было "Ok"... P.S. Раскажите откуда все-таки 1ки появились...
|
|
|
|
|
Jun 17 2007, 18:53
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Jun 17 2007, 21:44)  ... только вот для меня осталось странным, что получив подобный результат Вы не разобрались в чем была фишка... А чего странного? Мне эта 'фишка' без надобности - угробил несколько часов (начинал дома копаться и боролся с нежеланием искать сетевой шнур от осциллографа), потом увидел кашу, выяснил, что и резистор и место для него отсутствуют, как класс, грязно выругался по-болгарски  , запаял прямо на корпус AT24 первый попавшийся выводной резистор и все. Цитата P.S. Раскажите откуда все-таки 1ки появились... Читайте предыдущий пост.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 17 2007, 18:54
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(bodja74 @ Jun 17 2007, 20:04)  А софтовый I2C следит за SCL при растяжке ACK слейвом? У меня один мастер. Я не сталкивался с таким. Уточните откуда может быть растяжка. И 24c512 и mega48 - аппаратно формируют сигналы. Насчёт ошибок у м48 информации нет. Я пока это проконтролировать не могу. Необходимо на ней писать специальную отладочную программу чтобы это увидеть. Так, на вскидку, на ней ошибок нет. Ночь длинная. Проведу сейчас дополнительные исследования, тогда доложу о результатах. По поводу уменьшения резисторов - что-то нет веры: должно и так работать, по-моему. Средний примерный объём ошибокЖ 1-2 на 3к инфы
|
|
|
|
|
Jun 17 2007, 19:31
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(zltigo @ Jun 17 2007, 22:53)  А чего странного? Мне эта 'фишка' без надобности - угробил несколько часов (начинал дома копаться и боролся с нежеланием искать сетевой шнур от осциллографа), потом увидел кашу, выяснил, что и резистор и место для него отсутствуют, как класс, грязно выругался по-болгарски  , запаял прямо на корпус AT24 первый попавшийся выводной резистор и все. Читайте предыдущий пост. Дык а фишка заключается в том, что Вы неразобравшись в Вашем конкретном случае начинаете советовать остальным (неразобравшись в чем у Вас была проблемма) как нужно организовывать обмен по i2c другим... вот это и странно... Цитата Радиоканал? С каких частот у нас радио начинается знаете? Ну а даже заваленые 10ns фронты LPX2000 великолетно наводятся на идущую параллельно висящую дорожку. Знаю, но к приему сигнала по i2c без пулапов это не имеет никакого значения. Ладно, если Вы не против довайте попробуем отвлечся  и ответить на вопрос автора. Цитата(SasaVitebsk @ Jun 17 2007, 22:54)  И 24c512 и mega48 - аппаратно формируют сигналы. Вы понимаете что аппаратно формируемые сигналы от 24xx и от ATmegaxx имеют по крайней мере разную форму ? Все зависит от софта на Атмега...
|
|
|
|
|
Jun 17 2007, 19:36
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(singlskv @ Jun 17 2007, 22:24)  ...что Вы неразобравшись ... начинаете советовать остальным (неразобравшись в чем у Вас была проблемма) как нужно организовывать обмен по i2c другим... Я разобрался в том, что: 1. AT24 очень НЕ КРИТИЧНА к качеству сигналов и шаманство с уменьшению pullup-ов маловероятно приведет к результату. 2. AT24 не имеет проблем с блочным режимом, по крайней мере при работе с железным I2C контроллером. Кроме того, я разобрался в чем была конкретная проблема с конкретной платой. О чем и написал - перечитайте пост №3. Если Вам привиделись какие-то "советы" - это Ваши проблемы.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 17 2007, 20:23
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Я, к примеру, совершенно не удивился сообщению zltigo. И совершенно не понимаю что вас в нём удивляет? I2C - статическая шина. Следовательно поступающие сигналы не должны быть привязаны ко времени. Если подтяжки нет, то наводки на этих ножках рано или поздно но уложатся в нужный сигнал, как ни крути. Один раз я столкнулся со случаем работы контроллера дисковода (ВГ93) при обрезанном сигнале управления (то ли RD то ли WR уже не помню, но помню что совершенно необходимый). Тот милый человек, который смотрел эту плату до меня зачем-то перерезал его с помощью лезвия. Наверное потом хотел соплю кинуть, да подзабыл. Когда я нашёл настоящую неисправность и запустил злополучный синклер, то выяснил что дисковод работает, но только длинные файлы не читает. Причина выяснилась достаточно быстро. Анализирую ноги ВГ93 было обнаружено, что одна просто болтается в воздухе. Как я писал выше дисковод полностью работал и короткие файлы читал исправно. zltigo спасибо за информацию Ваш пост я понял. 2 singlskv. Также спасибо. Я правда не совсем понял фразу Цитата Вы понимаете что аппаратно формируемые сигналы от 24xx и от ATmegaxx имеют по крайней мере разную форму ? Все зависит от софта на Атмега... Софт на м48 писал, естественно я сам. Наверное Вы имели ввиду не "разную форму", а "работают по разному". Это, безусловно, я понимаю. Ещё раз повторяю. Если работа с at24 идёт побайтно, то никаких проблем не возникает. Два изделия работают круглосуточно больше месяца. 2 zltigo. При блочной записи. Записываю 32 байта. Границы верны. То есть принципиально всё пишется правильно. Вопрос достаточно ли одной задержки 10мс после записи страницы? Точнее части страницы. Помню в какой-то мне приходилось задержку на запись делать = Twr * число записываемых байт. Правда это в какой-то младшенькой памяти было.
|
|
|
|
|
Jun 17 2007, 20:38
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(SasaVitebsk @ Jun 17 2007, 21:54)  Средний примерный объём ошибокЖ 1-2 на 3к инфы А попробовать исключить возможное влияние прерываний? - Может, что-то банально портится во время прерывания. У Вас, насколько я помню, система прерываний достаточно требовательная. Может там что накосячили  Во всяком случае у меня при софтовом мастере и работе с EEPROM сбоев не бывает. И еще - есть такая особенность, что время записи некоторых микросхем существенно возрастает. Если бит готовности не обрабатывается, а используется банальная задержка "с запасом", может оказаться так, что по мере старения микросхемы этого запаса может не хватать. Спокойной ночи
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 17 2007, 23:51
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(SasaVitebsk @ Jun 18 2007, 02:18)  Скажи а страницу я обязан полностью записывать (там 128 байт). Насколько я помню там просто копируется вся страница в озу потом модифицируется и записывается. То есть по моим понятиям я могу сколько угодно записать. Работать должна. Или я не прав? Почему может 24с всегда отвечать? После записи страницы надо ждать 5ms для чипов с маркировкой "A", и 10ms без "A".. Код U8 AT24_AttemptWrite( U16 Address, U8 *pData, U8 count) { U8 retval = NACK; U8 repcount = 12; // (A package - write op timeout - 5ms, not (A) package - 10ms)
while (repcount-- && (retval != ACK)) { i2c_MemTransfer(AT24_DevAddress + SLA_W, Address, count, pData); retval = i2c_WaitCompleteOperation(); if (retval) // operation NACK'ed Kernel_WaitMS( 1 ); } return retval; } Цитата Сбои возникают как при чтении, так и при записи. Их характер - случайный и хаотический. Возможно сбои связаны с тем, что у вас не обрабатывается либо неправильно обрабатывается какое-то из состояний шины. Например, при блочном чтении, очень важно устанавливать NACK перед приемом последнего байта данных. Цитата Для этого я ввёл буфер на 32 байта и начал писать/читать блоками по 32 байта. На меге640 лучше не скупиться на буфер и сделать его размером байт в 200 (про запас) чтобы можно было размещать страницы целиком.
|
|
|
|
|
Jun 18 2007, 07:24
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(SasaVitebsk @ Jun 18 2007, 02:18)  ...Пока меня устроит запись побайтная. Время некритично, но неприятно... А драматическое уменьшение ресурса не смущает? Про бит готовности - это у меня терминология выпала под вечер  ACK, конечно же. Еще раз предупреждаю про задержку - дело в том, что для микросхем какого-то производителя очень критично, если повторная запись страницы начинается раньше, чем закончилась предыдущая. Во всяком случае это было лет 6 назад и у меня были серьезные проблемы. Микросхема выходила из строя в течение дня.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jun 18 2007, 07:37
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(SasaVitebsk @ Jun 18 2007, 02:18)  Скажи а страницу я обязан полностью записывать (там 128 байт). Нет, любым кусочком. Я почти всегда пишу не страницами а по 32 байта, дабы не разбираться, какой чип стоит или в некоторых случаях кусками равными размеру записи а не страницы. Цитата(defunct @ Jun 18 2007, 02:51)  После записи страницы надо ждать 5ms для чипов с маркировкой "A", и 10ms без "A".. Уже писал - я не разбираюсь с буковками на чипе и не жду. Банально повторяется посылка START до получения ACK. Какой-либо задержки не используется в принципе. Прокладок-задержек между циклами опроса, как в Вашем примере, тоже, поскольку работаю по прерываниям и там автомат самостоятельно непрерывно молотит. Чипы производители оборудования точно ставят разные и разных производителей.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 18 2007, 11:04
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(zltigo @ Jun 18 2007, 10:37)  Какой-либо задержки не используется в принципе. Прокладок-задержек между циклами опроса, как в Вашем примере, тоже, поскольку работаю по прерываниям и там автомат самостоятельно непрерывно молотит. в примере нет задержки для системы, там задержка операции записи. Kernel_WaitMS(x) передает управление другим задачам, на время x. i2c у меня тоже работает по прерыванию. Цитата Уже писал - я не разбираюсь с буковками на чипе и не жду. Банально повторяется посылка START до получения ACK. Какой-либо задержки не используется в принципе. Тем самым занимаете i2c шину на тупое ожидание At24. У меня к примеру на шине несколько устройств, и пока AT24 выполняет запись, шина используется для обмена с другими устройствами. Цитата Нет, любым кусочком. Я почти всегда пишу не страницами а по 32 байта, дабы не разбираться, какой чип стоит или в некоторых случаях кусками равными размеру записи а не страницы. Бесспорно любым кусочком можно писать. Но почему 32 байта? чтобы страница объемом в 128 байт записывалась в 4 раза дольше? Время записи для AT24, что всей страници сразу, что одного байта - одинаково.
|
|
|
|
|
Jun 18 2007, 12:21
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(defunct @ Jun 18 2007, 14:04)  в примере нет задержки для системы, там задержка операции записи. Я вижу. Про задержку для системы я не говорил, а задержка для устройства есть. Цитата Тем самым занимаете i2c шину на тупое ожидание At24. При нескольких устойствах, естественно, оптимальная организация может быть иной. Какой, надо думать в каждом конкретном случае. Цитата Бесспорно любым кусочком можно писать. Но почему 32 байта? чтобы страница объемом в 128 байт записывалась в 4 раза дольше? Уже обьяснял - в наиболее частом варианте, дабы не разбираться со страничной организацией конкретного чипа поставленного производителем оборудования (а меньше 32 не встречал), или в зависимости от размера единичной записи, которую надо записать сразу не дожидаясь когда будет дополнение до размера страницы.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 18 2007, 21:35
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Кое что прояснилось. Буду, конечно ещё дальше копать.
Мега48 работает в том числе в качестве часов реального времени. Когда я пытался минимизировать её потребление, то столкнулся с проблемой, что засыпает она не сразу и как бы некоторое время работает хотя питание уже отрублено. Чтобы уменьшить ёмкость кондёра, который позволил бы переключиться на батарейное питание, я практически всегда сплю. Просыпается она по часам, таймеру и I2C. Думаю с этим связаны некоторые сбои. Походу она иногда отвечает не на свой адрес. Почему так происходит я пока не знаю. Но это явно мешает работе 24с. При снижении частоты до 150кГц страничное чтение EEPROM начинает устойчиво работать. Хотя запись - ещё нет. Конечно можно попробовать и дальше снижать частоту шины, дабы добиться устойчивой работы и на записи и на чтении, но меня это не устраивает.
Попробую провести ряд экспериментов чтобы выяснить почему это происходит в принципе. Где собака порылась. Или попробую ввести значительную задержку после старта, чтобы она успела просыпаться и правильно реагировать на адрес. Пока короче не знаю. По описанию, она должна нормально работать с I2C во время сна. Пока я этого не наблюдаю.
Я, конечно несколько схалявил с обработкой I2C слэйва. Все состояния не обрабатывал. Посчитал не нужным. С точки зрения Меги640, - мега48 представляет собой микруху памяти типа 24с01 с левым адресом 0x16/0x17.
Обработчик могу привести - он не большой. Можно было бы посмотреть чужой. Может я что-то не верно сделал. Хотя вроде бы работает.
Да и ещё инфа для размышления. Во время чтения, - обращение к м48 происходит. Во время записи - нет, до завершения записи.
|
|
|
|
|
Jun 18 2007, 22:06
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(zltigo @ Jun 18 2007, 15:21)  (а меньше 32 не встречал), FYI: Код switch(aDevType) { case AT24C01: case AT24C02: AT24_PageSize = 8; break; case AT24C04: case AT24C08: case AT24C16: AT24_PageSize = 16; break; case AT24C32: case AT24C64: AT24_PageSize = 32; break; case AT24C128: case AT24C256: AT24_PageSize = 64; break; case AT24C512: AT24_PageSize = 128; break; default: retval = NACK; AT24_PageSize = 128; break; Цитата Обработчик могу привести - он не большой. Можно было бы посмотреть чужой. Может я что-то не верно сделал. Хотя вроде бы работает. Приводите, может что-то заметим... Цитата Да и ещё инфа для размышления. Во время чтения, - обращение к м48 происходит. Во время записи - нет, до завершения записи. Имеется в виду ложное обращение (всмысле ложное срабатывание m48)?
|
|
|
|
|
Jun 18 2007, 22:42
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Код //Инициализация порта TWI void TWI_Init(void) { TWI_DDR &= ~(1<<SDA); // SDA на ввод TWI_PORT |= (1<<SDA); // подпереть TWI_DDR &= ~(1<<SCL); // SCL на ввод TWI_PORT |= (1<<SCL); // подпереть TWCR=TWI_OK; // Режим Slave } Код #pragma vector=TWI_vect // I2C __interrupt static void i2c(void) { uint8_t static AdrStatus; // Смещение внутри структуры
switch(TWSR & 0xF8){ case TWI_ADDR_W: // Приняли свой адрес Flag.ErrIIC=0; Flag.AdrIIC=1; break; case TWI_DATA_W: // Читаем Адрес структуры или саму структуру (Установка времени) if(Flag.AdrIIC){ // Читаем Адрес структуры Flag.AdrIIC=0; // Сбросили признак AdrStatus=TWDR & 0x1f; // установить смещение } else{ // Читаем саму структуру (Установка времени) if(AdrStatus>13){ AdrStatus=0; // Игнорировать ошибки break; // Недопустить запись в область ячеек памяти } *(&Status.Year+AdrStatus++)=TWDR; // Записать и перейти на следующий Flag.SetDay=1; // Был установлен день } break; case TWI_WP: // Стоп или повторный старт case TWI_STOP: // Стоп case TWI_A_STOP: // Стоп if(Flag.SetDay){ // Если было установлено время, то LastDay=LastDayOfMonth[Status.Month]; // Определим последний день месяца Flag.SetDay=0; // Сбросить признак } break; case TWI_ADDR_R: // Читаем case TWI_DATA_R: // Читаем TWDR= *(&Status.Year+AdrStatus++); // Прочитать и перейти на следующий if(AdrStatus>13)AdrStatus=0; // Игнорировать ошибки break; default: Flag.ErrIIC=1; // Иначе ошибка } TWCR=TWI_OK; // Подтвердить приём } Код //==== I2C ===== TWAR=0x16; // Адрес Slave = 16/17 Код #define FCLK 8000000 // Частота контроллера #define TCLK 125 // Частота контроллера в нс
#define VERSIJA 0x18 // Версия ПО 1.8
#define INT0 2 // Нога INT0 #define INT0_PIN PIND // Порт INT0
//======================================== //======== TWI =========== #define TWI_ADDR_W 0x60 // Передача "Адрес + W" #define TWI_DATA_W 0x80 // Передача "Записать данные" #define TWI_WP 0xa0 // Передача "Записать данные и стоп"
#define TWI_ADDR_R 0xa8 // Передача "Адрес + R" #define TWI_DATA_R 0xb8 // Передача "Читать данные" #define TWI_STOP 0xc0 // Передача "Читать стоп" #define TWI_A_STOP 0xc8 // Передача "Читать стоп"
#define TWI_OK 0xc5 // Подтверждение приёма
#define SDA 0x4 // Линия порта SDA #define SCL 0x5 // Линия порта SCL #define TWI_PORT PORTC // Порт I2C #define TWI_DDR DDRC // Порт I2C
#define PWR_BAT 0x1 // Включение батарейного питания #define BAT_PORT PORTC // Порт включения батарейного питания #define PWR_BAT_ON BAT_PORT |= (1<<PWR_BAT)// Подключить батарейку #define PWR_BAT_OFF BAT_PORT &= ~(1<<PWR_BAT)// Выключить батарейку
|
|
|
|
|
Jun 18 2007, 23:37
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(SasaVitebsk @ Jun 19 2007, 01:42)  default: Flag.ErrIIC=1; На первый взгляд никакого криминала нет. По дефолту попробуйте сделать переинициализацию шины TWCR = (1 << TWIE); // twen - 0 TWDR = 0; TWAR = SLAVE_ADDRESS; TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA); (и конечно же под отладкой поставить точку останова на default case и посмотреть когда туда попадает)
|
|
|
|
|
Jun 19 2007, 04:54
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 21-07-06
Из: Владивосток
Пользователь №: 18 987

|
Кстати говоря, на такой шине при поллинге надо обязательно выдавать стоп-условие вне зависимости от того, есть ACK или нет. Устройств-то несколько! И не нужно заморачивать себе голову всеми этими задержками, так как они плывут по температуре и от возраста, а использовать только поллинг и в побайтовом случае, и в блочном. По сути дела, побайтовая запись - это ни что иное, как запись блока размером 1 байт, которая всё равно приводит к перезаписи страницы целиком. О пуллапах. На 1 МГц 10к вполне достаточно, всю жизнь ставлю и всё ОК (тьфу-тьфу...).
|
|
|
|
|
Jun 19 2007, 08:19
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(mrcashe @ Jun 19 2007, 07:54)  Кстати говоря, на такой шине при поллинге надо обязательно выдавать стоп-условие вне зависимости от того, есть ACK или нет. Устройств-то несколько! И не нужно заморачивать себе голову всеми этими задержками, так как они плывут по температуре и от возраста, а использовать только поллинг и в побайтовом случае, и в блочном. По сути дела, побайтовая запись - это ни что иное, как запись блока размером 1 байт, которая всё равно приводит к перезаписи страницы целиком. О пуллапах. На 1 МГц 10к вполне достаточно, всю жизнь ставлю и всё ОК (тьфу-тьфу...). Я сразу поставил стоп-условие. Хотябы для того, чтобы линии возвращались в исходное. Проблема в том, что я не вижу случаев "неответа" при записи. Она всегда отвечает ASK. Точнее кто-то отвечает. Сегодня буду рэзать и выяснят. 2 defunct спасибо попробую. Надо бы два компа и два JTAG ICE MK2.  2 singlskv - первое попробую, а второе IAR выбросит. Напишет оператор не имеет смысла. При любой оптимизации. Да и я бы, по честному выбросил. Прости, но я в шаманство не верю. Предпочитаю причину найти.
|
|
|
|
|
Jun 19 2007, 08:41
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(SasaVitebsk @ Jun 19 2007, 12:19)  2 singlskv - первое попробую, а второе IAR выбросит. не выбросит, не имеет таких правов  при описании регистров там везде понатыкано volatile а это просто чтение регистра перед тем как его записать Цитата Прости, но я в шаманство не верю. Предпочитаю причину найти. Я тоже долго не верил, пока в ходе длительных боев с i2c не убедился в этом сам. На самом деле это нужно делать только при одном состоянии на шине и только при определенных условиях. Да, кстати, пример работы с i2c по прерываниям есть в avrlib.
|
|
|
|
|
Jun 30 2007, 00:37
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Всем спасибо за участие. В любом случае я узнал новые для себя вещи (в плане 24с). И переработал программу. Работает намного быстрее, естественно. Если кого интересует, то хомут найден. Хомут забавный. У меня подряд шли два буфера (IAR разместил). Приёмный буфер 485 и I2C. Буфер I2C общий на запись и чтение, так как данные операции не идут совместно. Буфер 485 достаточно сложный я делаю по привычке. Размер более двух размеров пакетов. Подкачка начинается задолго до полного опустошения буфера (так как надо успеть принять пакет целиком и сверить КС до полного опустошения буфера). Естественно он не инициализируется. Ну и указатели я тоже не инициализирую а выравниваю. Таким образом закачка продолжается с того места на котором остановилась предыдущая. При написании я хомутнул и задействовал на 1 байт больше размера вх буфера (при переходе по кольцу). В результате пока я пишу побайтно (то есть буфер I2C не использую) то всё замечательно, а как только начинаю использовать, то происходят единичные сбои в момент перехода по кольцу и одновременной записи в EEPROM. В связи с описанными выше особенностями, сбои проявлялись достаточно хаотично. В разных местах и в разное время.  Кстати раз уж зашёл разговор об этом. Подскажите спецы кто как работает в Си. Можно работать с массивами и указателями. Что эффективней? А то у меня кое где массивы, а кое где указатели. Смотрю IAR достаточно эффективно компилит, но всё равно думается если индекс массива более 1 байта (в смысле менее разрядности процессора), то наверное всётаки лучше с указателями работать. Кто выскажется по данному вопросу?
|
|
|
|
|
Jun 30 2007, 04:15
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(SasaVitebsk @ Jun 30 2007, 03:37)  А то у меня кое где массивы, а кое где указатели. Смотрю IAR достаточно эффективно компилит, но всё равно думается если индекс массива более 1 байта (в смысле менее разрядности процессора), то наверное всётаки лучше с указателями работать. Кто выскажется по данному вопросу? При разборе с указателями букав меньше  Но использую и то, и другое. Кстати или не кстати - при использовании протоколов запрос-ответ стараюсь использовать линейные буфера вместо циклических - так проще прописать автоматы приема-передачи.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Jul 1 2007, 06:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Можно работать с массивами и указателями. Что эффективней? Массив имеет длину и её можно узнать. Указателю на начало масива (имени массива) нельзя присваивать значения (соответственно тяжело потерять  ), а по сути работа с ним идёт как с обычным указателем и смещением. Т.е. эквивалентно a[i] и *(a+i) и i[a] Хотя и бывают некоторые ограничения - так размер массива в ИАРе для АВР раньше (не смотрел что там сейчас), соответственно допустимый диапазон индексов, был ограничен длиной не более, чем __SIGNED_INT_MAX__ - вероятно дабы не загружать моск компилеру (что, ИМХО, вполне оправданно), но с указателем можно было работать арифметикой до __UNSIGNED_INT_MAX__, а может и больше (для __flash), но не проверял и не вчитывался в доку глубже  С указателем можно работать как с массивом char array[]="Preved!"; char * ptr = &array[1]; char x; x = ptr[4] ; //x = *(ptr+4); или x = 'd';
--------------------
aka Vit
|
|
|
|
|
Jul 1 2007, 08:35
|
Участник

Группа: Участник
Сообщений: 17
Регистрация: 21-07-06
Из: Владивосток
Пользователь №: 18 987

|
Цитата Подскажите спецы кто как работает в Си. Можно работать с массивами и указателями. Что эффективней? Я стараюсь работать только с указателями. При программировании для МК это несколько экономит ресурсы. Допустим, есть некая структура: Код typedef struct { int id; void * p; } some_struct_t; и есть некая константа, задающая размер буфера (читай: массива): Код enum { some_buffer_size = 20 }; Разместим сам буфер: Код some_struct_t some_buffer[some_buffer_size]; Теперь вариант перебора с применением индекса: Код int i; for (i = 0; i < some_buffer_size; ++i) { printf("%i %p\n", some_buffer[i].id, some_buffer[i].p); } Перебор с применением указателя: Код some_struct_t * p; for (p = some_buffer; p < some_buffer+some_buffer_size; ++p) { printf("%i %p\n", p->id, p->p); } Как видим, в первом случае индексирование выполняется дважды за цикл, т.е. всего 40 раз! А что есть индексирование? Это умножение(!) индекса на размер элемента массива и суммирование его с указателем на массив. Конечно, в случае массива символов размер элемента массива == 1, так что можно просто прибавлять индекс к адресу массива, но в случае массивов с размером элементов в 5 байт придётся именно умножать. Во втором же случае размер элемента массива просто прибавляется к текущему значению указателя, что может быть на порядок (а то и 2 порядка) эффективнее. С другой стороны, если не требуется итерация по всему буферу, а нужен именно произвольный доступ к элементу с определённым индексом, то можно с одинаковым успехом воспользоваться обоими методами, как и показал sensor_ua. Цитата Массив имеет длину и её можно узнать. Это что-то новое. Размер массива в Си, вообще говоря, невозможно узнать динамически. Соответственно, код, сгенерированный компилятором, не имеет возможности детектировать выход за пределы массива. Если Вы имеете ввиду sizeof() , то он возвращает размер объекта в байтах, что обычно не то, что нужно в повседневной жизни. Более того, полагаться на этот оператор просто опасно. В различных компиляторах он может выдавать различные значения благодаря различному выравниванию элементов. Если массив размещается статически, то всегда заводите константу, содержащую его размер и пользуйтесь только ею для задания и определения размера массива. Если массив размещается динамически, то определите переменную (а ещё лучше - функцию) для определения его размера. Для изменения размера определите соотвествующую функцию.
|
|
|
|
|
Jul 1 2007, 10:36
|
Профессионал
    
Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387

|
Цитата Это что-то новое. Размер массива в Си, вообще говоря, невозможно узнать динамически. Соответственно, код, сгенерированный компилятором, не имеет возможности детектировать выход за пределы массива. Если Вы имеете ввиду sizeof() , то он возвращает размер объекта в байтах, что обычно не то, что нужно в повседневной жизни. Более того, полагаться на этот оператор просто опасно. В различных компиляторах он может выдавать различные значения благодаря различному выравниванию элементов. Если массив размещается статически, то всегда заводите константу, содержащую его размер и пользуйтесь только ею для задания и определения размера массива. Если массив размещается динамически, то определите переменную (а ещё лучше - функцию) для определения его размера. Для изменения размера определите соотвествующую функцию. Это относится к категории вредных советов. Действительно sizeof - оператор, вычисляемый во время компиляции. Действительно может давать значение с учётом утечек памяти при выравнивании. Нормальные компиляторы позволяют указывать явно что и как выравнивать. Во время компиляции он превращается в целую константу, значение которой равно размеру типа или объекта (в байтах). Ещё - в C89 и C++ действительно не поддерживаются массивы переменной длины, но в С99 всвязи с введением массивов переменной длины применение sizeof к таковым приводит в к тому, что значение sizeof получает во время выполнения. Что касается контроля выхода за пределы - тут без наличия этих величин пределов в Си нечего делать. Что касается "нужного в повседневной жизни", то, как понимаю имеется в виду sizeof(array)/sizeof(array[0]) - ничего сдесь нет сложного - классический пример.
--------------------
aka Vit
|
|
|
|
|
Jul 1 2007, 13:09
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(mrcashe @ Jul 1 2007, 11:35)  В различных компиляторах он может выдавать различные значения благодаря различному выравниванию элементов. Если массив размещается статически, то всегда заводите константу, содержащую его размер и пользуйтесь только ею для задания и определения размера массива. Как уже отметил sensor_ua, не надо заводить никаких констант. Гораздо безопаснее применять макрос #define COUNT( arr ) ( sizeof( arr ) / sizeof( (arr)[0] ) ) Цитата Как видим, в первом случае индексирование выполняется дважды за цикл, т.е. всего 40 раз! для процессоров таких как AVR, компилятор соптимизирует операции индексирования. (добавит неявный указатель на структуру) Для процессоров с индексной адресацией, абсолютно не важно сколько раз происходит индексирование: MOV eax, [ebx + esi * x + offset]
|
|
|
|
|
  |
4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0
|
|
|