реклама на сайте
подробности

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Помогите советом. I2C, Мож кто сталкивался.
SasaVitebsk
сообщение Jun 18 2007, 08:43
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(zltigo @ Jun 18 2007, 10:37) *
Нет, любым кусочком. Я почти всегда пишу не страницами а по 32 байта, дабы не разбираться, какой чип стоит или в некоторых случаях кусками равными размеру записи а не страницы.


И я том же. К тому же дальнейшее увеличение размера записываемой страницы практически не даст существенного выигрыша. А память - всегда дефицит. smile.gif

Всем спасибо за участие. Информации мне теперь достаточно. Пока беру таймаут. Выясню причину, - обязательно напишу.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 18 2007, 11:04
Сообщение #32


кекс
******

Группа: Свой
Сообщений: 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, что всей страници сразу, что одного байта - одинаково.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jun 18 2007, 12:21
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 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
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jun 18 2007, 21:35
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Кое что прояснилось. Буду, конечно ещё дальше копать.

Мега48 работает в том числе в качестве часов реального времени. Когда я пытался минимизировать её потребление, то столкнулся с проблемой, что засыпает она не сразу и как бы некоторое время работает хотя питание уже отрублено. Чтобы уменьшить ёмкость кондёра, который позволил бы переключиться на батарейное питание, я практически всегда сплю. Просыпается она по часам, таймеру и I2C. Думаю с этим связаны некоторые сбои. Походу она иногда отвечает не на свой адрес. Почему так происходит я пока не знаю. Но это явно мешает работе 24с. При снижении частоты до 150кГц страничное чтение EEPROM начинает устойчиво работать. Хотя запись - ещё нет. Конечно можно попробовать и дальше снижать частоту шины, дабы добиться устойчивой работы и на записи и на чтении, но меня это не устраивает.

Попробую провести ряд экспериментов чтобы выяснить почему это происходит в принципе. Где собака порылась. Или попробую ввести значительную задержку после старта, чтобы она успела просыпаться и правильно реагировать на адрес. Пока короче не знаю. По описанию, она должна нормально работать с I2C во время сна. Пока я этого не наблюдаю.

Я, конечно несколько схалявил с обработкой I2C слэйва. Все состояния не обрабатывал. Посчитал не нужным. С точки зрения Меги640, - мега48 представляет собой микруху памяти типа 24с01 с левым адресом 0x16/0x17.

Обработчик могу привести - он не большой. Можно было бы посмотреть чужой. Может я что-то не верно сделал. Хотя вроде бы работает.

Да и ещё инфа для размышления. Во время чтения, - обращение к м48 происходит. Во время записи - нет, до завершения записи.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 18 2007, 22:06
Сообщение #35


кекс
******

Группа: Свой
Сообщений: 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)?
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jun 18 2007, 22:42
Сообщение #36


Гуру
******

Группа: Свой
Сообщений: 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)// Выключить батарейку
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 18 2007, 23:37
Сообщение #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 и посмотреть когда туда попадает)
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 18 2007, 23:57
Сообщение #38


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



1. нужно обязательно добавить обработку состояния Bus Error ((TWSR & 0xF8)==0x00)
там обработка отличается
TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEA)|(1<<TWEN);

2. попробуйте вместо:
TWCR=TWI_OK; // Подтвердить приём

написать так:
TWCR;
TWCR=TWI_OK;

может быть поможет (это не шутка!)
Go to the top of the page
 
+Quote Post
mrcashe
сообщение Jun 19 2007, 04:54
Сообщение #39


Участник
*

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



Кстати говоря, на такой шине при поллинге надо обязательно выдавать стоп-условие вне зависимости от того, есть ACK или нет. Устройств-то несколько! И не нужно заморачивать себе голову всеми этими задержками, так как они плывут по температуре и от возраста, а использовать только поллинг и в побайтовом случае, и в блочном. По сути дела, побайтовая запись - это ни что иное, как запись блока размером 1 байт, которая всё равно приводит к перезаписи страницы целиком.
О пуллапах. На 1 МГц 10к вполне достаточно, всю жизнь ставлю и всё ОК (тьфу-тьфу...).
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jun 19 2007, 08:19
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 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. smile.gif

2 singlskv - первое попробую, а второе IAR выбросит. Напишет оператор не имеет смысла. При любой оптимизации. Да и я бы, по честному выбросил. Прости, но я в шаманство не верю. Предпочитаю причину найти.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 19 2007, 08:41
Сообщение #41


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(SasaVitebsk @ Jun 19 2007, 12:19) *
2 singlskv - первое попробую, а второе IAR выбросит.

не выбросит, не имеет таких правов smile.gif
при описании регистров там везде понатыкано volatile
а это просто чтение регистра перед тем как его записать
Цитата
Прости, но я в шаманство не верю. Предпочитаю причину найти.

Я тоже долго не верил, пока в ходе длительных боев с i2c не убедился
в этом сам.
На самом деле это нужно делать только при одном состоянии на шине
и только при определенных условиях.

Да, кстати, пример работы с i2c по прерываниям есть в avrlib.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Jun 30 2007, 00:37
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Всем спасибо за участие. В любом случае я узнал новые для себя вещи (в плане 24с). И переработал программу. Работает намного быстрее, естественно.

Если кого интересует, то хомут найден. Хомут забавный. У меня подряд шли два буфера (IAR разместил). Приёмный буфер 485 и I2C. Буфер I2C общий на запись и чтение, так как данные операции не идут совместно. Буфер 485 достаточно сложный я делаю по привычке. Размер более двух размеров пакетов. Подкачка начинается задолго до полного опустошения буфера (так как надо успеть принять пакет целиком и сверить КС до полного опустошения буфера). Естественно он не инициализируется. Ну и указатели я тоже не инициализирую а выравниваю. Таким образом закачка продолжается с того места на котором остановилась предыдущая.
При написании я хомутнул и задействовал на 1 байт больше размера вх буфера (при переходе по кольцу). В результате пока я пишу побайтно (то есть буфер I2C не использую) то всё замечательно, а как только начинаю использовать, то происходят единичные сбои в момент перехода по кольцу и одновременной записи в EEPROM. В связи с описанными выше особенностями, сбои проявлялись достаточно хаотично. В разных местах и в разное время. smile.gif

Кстати раз уж зашёл разговор об этом. Подскажите спецы кто как работает в Си. Можно работать с массивами и указателями. Что эффективней?

А то у меня кое где массивы, а кое где указатели. Смотрю IAR достаточно эффективно компилит, но всё равно думается если индекс массива более 1 байта (в смысле менее разрядности процессора), то наверное всётаки лучше с указателями работать. Кто выскажется по данному вопросу?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jun 30 2007, 01:07
Сообщение #43


кекс
******

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



Цитата(SasaVitebsk @ Jun 30 2007, 03:37) *
А то у меня кое где массивы, а кое где указатели. Смотрю IAR достаточно эффективно компилит, но всё равно думается если индекс массива более 1 байта (в смысле менее разрядности процессора), то наверное всётаки лучше с указателями работать. Кто выскажется по данному вопросу?

Что удобнее - то и используйте.
Как по мне, для кольцевых буферов с байтовым доступом удобнее работать с индексами. Код получается более естественный (при проходе через 0), текущий размер свободного места можно определить формулой (без доп переменных).
Для списковых, пакетных - с указателями.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jun 30 2007, 04:15
Сообщение #44


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(SasaVitebsk @ Jun 30 2007, 03:37) *
А то у меня кое где массивы, а кое где указатели. Смотрю IAR достаточно эффективно компилит, но всё равно думается если индекс массива более 1 байта (в смысле менее разрядности процессора), то наверное всётаки лучше с указателями работать. Кто выскажется по данному вопросу?

При разборе с указателями букав меньше smile.gif
Но использую и то, и другое.
Кстати или не кстати - при использовании протоколов запрос-ответ стараюсь использовать линейные буфера вместо циклических - так проще прописать автоматы приема-передачи.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
sensor_ua
сообщение Jul 1 2007, 06:26
Сообщение #45


Профессионал
*****

Группа: Свой
Сообщений: 1 266
Регистрация: 22-04-05
Из: Киев
Пользователь №: 4 387



Цитата
Можно работать с массивами и указателями. Что эффективней?

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


--------------------
aka Vit
Go to the top of the page
 
+Quote Post

4 страниц V  < 1 2 3 4 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 03:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.01515 секунд с 7
ELECTRONIX ©2004-2016