Для 24С16 я сделал так:
//Для записи байта по адресу
void eeprom_write(unsigned short address, unsigned char data)
{
i2c_start();
i2c_write(EEPROM_BUS_ADDRESS | ((address>>8)&0b00000111)<<1);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(10);
}
////Для чтения байта по адресу
unsigned char eeprom_read(unsigned short address)
{
unsigned char data;
i2c_start();
i2c_write(EEPROM_BUS_ADDRESS | ((address>>8)&0b00000111)<<1);
i2c_write(address);
i2c_start();
i2c_write((EEPROM_BUS_ADDRESS | ((address>>8)&0b00000111)<<1)|1);
data=i2c_read(0);
i2c_stop();
return data;
}
Конечно можно упростить, но я оставил так!
Привет всем! Я понимаю, что тема уже отюзана и давно, но все же я споткнулся именно на адресации и не далее как два дня назад и бьюсь над это темой уже третий день. Итак, я НЕ ПОНИМАЮ, откуда почтенный народ взял, что память у именно этой МС (АТ24С16) разбита как 8 страниц по 256 байт???? Открываем его родной даташит на стр. 3 и внизу читаем " AT24C16A, 16K SERIAL EEPROM: Internally organized with 128 pages of 16 bytes each, the 16K requires an 11-bit data word address for random word addressing. "
Т.е. английским по белому написано, что страниц как раз 128 по 16 байт на странице! При чем после записи каждой страницы надо выдерживать паузу в 10 мс иначе нифига не запишет.
Пробовал писать данные как написано тут на форуме, т.е. сразу 100 байт подряд на определенную станицу. Потом считал то же самое и увидел, что записано только 16 байт при чем 6 раз переписывалось и записалось последние 4 байта, за которыми следуют предыдущие 10 байт. И далее чем 16 байт записано не было. А как только сделал все по даташиту, т.е. с разбивкой на страницы по 16 байт с паузой между страницами и о чудо! все записалось именно так как и планировалось.
Очень жду мнение тех, что реально работал ИМЕННО с ЭТОЙ МС, а не с 24с32 или 24с256.
Увидел, как прочитать 24с64. А как ее записать??? Бьюсь уже 3 часа и не выходит. С примером вроде все понятно, читаю/записываю 24с16 -все ок. Напишите кусок исходника ))
И еще вопрос: Могу ли я повесить на эту же шину температурный датчик, например lm75 или ds1621. Будут они работать вместе (24c64 и ds1621)??
Т.е. английским по белому написано, что страниц как раз 128 по 16 байт на странице! При чем после записи каждой страницы надо выдерживать паузу в 10 мс иначе нифига не запишет.
Можно и поллинговать.
Цитата:
Пробовал писать данные как написано тут на форуме, т.е. сразу 100 байт подряд на определенную станицу. Потом считал то же самое и увидел, что записано только 16 байт при чем 6 раз переписывалось и записалось последние 4 байта, за которыми следуют предыдущие 10 байт. И далее чем 16 байт записано не было.
В полном соответствии с ДШ. Превышение адреса (для этой МС) вызывает "возврат" на начальные адреса с перезаписью предыдущего контента. См. ДШ Write Operation стр. 8 А кто это по 100 байт в один присест пишет? В глаза ему хочу посмотреть.
Бьюсь уже 3 часа и не выходит. С примером вроде все понятно, читаю/записываю 24с16 -все ок.
Так они ж разные по ширине адреса. И блоки у них разные.
Цитата:
И еще вопрос: Могу ли я повесить на эту же шину температурный датчик, например lm75 или ds1621. Будут они работать вместе (24c64 и ds1621)??
Каждый класс устройств на шине I2C имеет свой адрес, прописанный изготовителем. С адресными расширениями внутри класса. Смотрите описания устройств и читайте описание I2C.
Я увидел пример именно чтения 24с64. А как в нее запиисывать не могу разобраться! Помогите в этом.
Вот те и пример чтения... и пример записи.....
Тут работа с 24C64Спойлер
Код:
//####################################################################################################################### //# //# ФУНКЦИИ РАБОТЫ С ПАМЯТЬЮ 24C64 //# //#######################################################################################################################
//ФУНКЦИЯ АДРЕСАЦИИ ПАМЯТИ 24C64 (установка внутреннего указателя) //АРГУМЕНТ - адрес в EEPROM void IICMemAdr (int EEAdr) { do { IICStart (); } while (IICByteWrite (0xA0));//писать в EEPROM
IICByteWrite ((uint8_t)(EEAdr >> 8));//старший байт адреса блока данных IICByteWrite ((uint8_t) EEAdr);//младший байт адреса блока данных }
//ФУНКЦИЯ ЧТЕНИЯ БАЙТА ДАННЫХ ИЗ МС 24C64 //АРГУМЕНТ - адрес байта данных в EEPROM //ЗНАЧЕНИЕ - байт данных char IICMemReadByte (int EEAdrRead) { IICMemAdr (EEAdrRead); IICStart (); IICByteWrite (0xA1);//читать из EEPROM char temp = IICByteRead (1);//читаем данные (без подтверждения) IICStop (); return temp; }
//ФУНКЦИЯ ЗАПИСИ БАЙТА ДАННЫХ В МС 24C64 //АРГУМЕНТ_1 - адрес байта данных в EEPROM //АРГУМЕНТ_2 - байт данных void IICMemWriteByte (int EEAdrWrite, char byte) { IICMemAdr (EEAdrWrite); IICByteWrite (byte);//пишем данные IICStop (); }
//ФУНКЦИЯ ЧТЕНИЯ БЛОКА ДАННЫХ ИЗ МС 24C64 //АРГУМЕНТ_1 - указатель на адрес загрузки в SRAM //АРГУМЕНТ_2 - адрес начала блока данных в EEPROM //АРГУМЕНТ_3 - длина блока данных void IICMemReadData (char* pAdrLoad, unsigned int EEAdrRead, unsigned int length) { IICMemAdr (EEAdrRead);//установка внутреннего указателя
IICStart (); IICByteWrite (0xA1);//читать EEPROM
while (1){
char temp; if (--length) temp = IICByteRead (0);//читаем данные с подтверждением else temp = IICByteRead (1);//читаем данные без подтверждения (последний байт)
*pAdrLoad++= temp;
if (! length){ IICStop (); return; } } }
//ФУНКЦИЯ ЗАПИСИ БЛОКА ДАННЫХ В МС 24C64 //АРГУМЕНТ_1 - указатель на адрес чтения из SRAM //АРГУМЕНТ_2 - адрес начала блока данных в EEPROM //АРГУМЕНТ_3 - длина блока данных void IICMemWriteData (char* pAdrSave, unsigned int EEAdrWrite, unsigned int length) { while (1){ IICMemAdr (EEAdrWrite); do{ IICByteWrite (*pAdrSave ++);//пишем данные в цикле EEAdrWrite ++; if (-- length == 0){//если указанная длина блока исчерпана - выход IICStop (); return; } } while ((char) EEAdrWrite & 0x1f);//проверка на выход из 32-х байтной страницы IICStop (); } }
//ФУНКЦИЯ ФОРМИРОВАНИЯ СОСТОЯНИЯ START ПО ИНТЕРФЕЙСУ IIC void IICStart (void) { IICDDR &=~(IICData | IICClc); Delay2Mks();
IICDDR |= IICData;//подтяжка data к нулю Delay2Mks();
IICDDR |= IICClc;//подтяжка clc к нулю Delay2Mks(); }
//ФУНКЦИЯ ФОРМИРОВАНИЯ СОСТОЯНИЯ STOP ПО ИНТЕРФЕЙСУ IIC void IICStop (void) { IICDDR |=(IICData | IICClc); Delay2Mks();
IICDDR &=~IICClc;//подтяжка data к нулю Delay2Mks();
IICDDR &=~IICData;//подтяжка clc к нулю Delay2Mks(); }
//ФУНКЦИЯ ЗАПИСИ БАЙТА ПО ИНТЕРФЕЙСУ IIC //АРГУМЕНТ - байт данных для вывода по IIC //ЗНАЧЕНИЕ - флаг подтверждения 0 (есть подтверждение) или 1 (нет подтверждения) char IICByteWrite (char byte) { for (char i = 0; i<8; i++) byte = IICBit (byte);
//ФУНКЦИЯ ЧТЕНИЯ БАЙТА ПО ИНТЕРФЕЙСУ IIC //АРГУМЕНТ - значение бита подтверждения (0 - есть подтверждение, 1 - нет подтверждения) //ЗНАЧЕНИЕ - принятый байт char IICByteRead (char bit) { char byte = 0xFF; for (char i = 0; i<8; i++) byte = IICBit (byte);
bit <<= 7; IICBit (bit);//передать значение бита подтверждения return byte;//возвращаем принятый байт }
//ФУНКЦИЯ ЗАПИСИ\ЧТЕНИЯ БИТА ПО ИНТЕРФЕЙСУ IIC //выводится значение старшего бита аргумента //принятый бит возвращается в младшем бите предварительно сдвинутого влево аргумента char IICBit (char byte) { if (byte & 0x80)//выводимый бит IICDDR &=~IICData;//вывод 1 на линию данных else IICDDR |= IICData;//вывод 0 на линию данных Delay2Mks();
IICDDR &=~IICClc;//старт строб импульса while (!(IICPIN & IICClc)){}//ожидание формирования строба Delay2Mks();
shads, большое спасибо. Я нашел только что русский даташит на 24с128 и мне стало понятно многое. Я только что записал и прочитал 24с64. Теперь мне хотелось бы понять про страницы. Что это за страницы и как располагаюстся мои байты в памяти?
Т.к. запись в флэш память занимает время, то обычно используется буфер, который позволяет быстро вогнать порцию данных... В 24С64 буфер равен 32 байта.. Если надо загонять в МС до 32-х байт, то информация помещается в этот буфер. После того как МС получила команду стоп, начинается фактическая запись в флэш память, эта процедура занимает определенное время, в течение которого флэшка не будет отвечать на внешние команды.....
Если надо записать в 24С64 больше данных чем размер буфера (32 байта), то происходит это так: 1. Инициализируем внутренний указатель флэш памяти, 2. Если МС не подтвердила чтение, идем опять на п1. 3. Выводим данные в флэш память, до адреса кратного 32-м, далее опять на п1. При этом конечно не забываем подсчитывать количество переданных байт.....
Товарищи. у кого нить есть проект под winavr? Бьюсь уже несколько дней с 24с16. Код взял тут _http://avrlab.com/node/84. Пишу и читаю так Спойлер
Код:
int main(void)//Основная программа
{ //Инициализация EEPROM EEOpen();
_delay_ms (15);//Небольшая задержка
//Конфигурируем модуль USART на скорость 115200кБит/с при частоте кварца 16МГц
USART_Init (8);//115200 16MHz
for(address=0; address<25; address++)//цикл с пределами памяти { int a = 77; EEWriteByte(address,a); _delay_ms (100);// задержка } while(1)//Вечный цикл { eeread ();//Выполняем чтение заданной области памяти из микросхемы EEPROM } _delay_ms (5000);// задержка
}
По уарту ничего не видно, а хотелось бы получить хоть какой нить результат.
Хороший код, ничего не скажешь Что Вы с ним хотите увидеть, если у Вас программа тупо циклится ?
Прошу прощения у Великого Гуру. Посмотрев на код фукции eeread Спойлер
Код:
void eeread (void)//Функция чтения данных из памяти EEPROM
{ for(address=0; address<25; address++)//цикл с адресами данных
{b = EEReadByte(address);//присваиваем переменной b прочитанный байт данных
USART_Transmit(b);//Передаем прочитанный байт по USART
}
USART_Transmit(0x0d);//переход в начало строки
USART_Transmit(0x0a);//переход на новую строку
}
я неосторожно подумал, что сия конструкция в майне вернет мне данные, записанные в первых 25 ячейках памяти. Если я неправ-прошу наставить на путь истинный
for(byte_mass=0; byte_mass<7; byte_mass++) // Запись первой половины блока (одной команды ДУ) { eep_write_1byte_page(0xA1, byte_block_cnt, data_ir_eep0[byte_block_cnt]);
Заголовок сообщения: Re: Ищу проекты c EEPROM at24cXX
Добавлено: Ср мар 16, 2016 07:59:16
Родился
Зарегистрирован: Ср мар 16, 2016 07:37:44 Сообщений: 2
Рейтинг сообщения:0
shads писал(а):
Если надо записать в 24С64 больше данных чем размер буфера (32 байта), то происходит это так: 1. Инициализируем внутренний указатель флэш памяти
Доброго дня! Можете поподробнее объяснить: что это за "внутренний указатель"? Как раз столкнулся с проблемой, что при записи большого массива данных приходится выдерживать 5 мс между порциями данных, иначе происходит запись некорректных данных. Не хотелось бы терять время впустую (пишется сразу по 1-2 Кб), поэтому как нужно правильно организовать проверку? Использую библиотеку: http://www.electroons.com/blog/hello-world/ Память: AT24C64. Спасибо!
Простой внутренний счётчик адреса. При чтении считаем от адреса инициализации до последнего адреса памяти(её размера), затем происходит переполнение и счётчик скатывается в нулевой адрес. При записи счётчик считает до 32-х байт(до размера страницы), затем скатывается в начальный адрес. Максимум что можно сделать - это писать целую страницу за раз. Для записи больших блоков советую применить флеш память из 25-й серии, там размер страницы от 256 байт и время программирования байта поменьше. А вообще у stm32 большая внутренняя перепрограммируемая память, зачем использовать медленную внешнюю?
Заголовок сообщения: Re: Ищу проекты c EEPROM at24cXX
Добавлено: Ср мар 16, 2016 16:18:39
Родился
Зарегистрирован: Ср мар 16, 2016 07:37:44 Сообщений: 2
Рейтинг сообщения:0
uk8amk писал(а):
А вообще у stm32 большая внутренняя перепрограммируемая память, зачем использовать медленную внешнюю?
Спасибо за ответ! Тут 2 нюанса, из-за которых выбор сделан в пользу внешней памяти: 1) У STM32 общая Flash память для программы и для данных. Соответственно с ростом программы или данных может возникнуть наложение, что приведет к ошибкам. 2) Есть вероятность, что данные могут писаться часто. Однако ограниченность циклов перезаписи может привести к порче МК. Однако проще поменять внешнюю память, чем МК. Конечно, можно использовать SD-карту, но объем данных невелик (1-2 кБ), и вероятность частой записи, как говорилось, небольшая. Ещё есть опасения по поводу файловой системы. Там тоже при частом обращении к SD возникали проблемы с порчей файлов (изменение атрибут в сторону неконтролируемого увеличения объема файла). То есть подобная проблема, что и с EEPROM. И тоже, скорее всего, связана с задержками (по тестам некоторые карты при записи могут дать случайную задержку до 1 с.)
1)обычно выделяются несколько последних страниц. Как раз размер страниц 1-2 килобайт. Можно подправить скрипт компоновщика и разместить блок данных по фиксированному адресу. Никто ни на кого после этого не залезет. 2)так чтоб совсем без задержек есть FRAM как с параллельным, так и последовательным интерфейсом.
<Удалил сообщение, проблема не исчезла... Бьюсь дальше> Всё. Разобрался. Условия были выбраны не верные = вместо >, из за того, что возврат значений разный. В одном случае 0 - это ASK. А в другом вместо ASK/NASK... это кол-во отправленных байт! И голову придти не могло, что write не отвечает категорией подтверждений, а кол-вом переданных байт. Школьники и системы под их уровень интеллекта подстраивающиеся - зло!
З.Ы. Библиотека Wire в Arduino - просто ужасна и крайне не приятна, после того как работал с полноценной реализацией в софте или железе. Чтение и запись, в 24C16A, заработало.
_________________ Если в голове каша, значит ваш котелок варит!
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 14
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения