18+ Некоторые материалы сайта могут содержать информацию, запрещенную для детей.

Запись от AZM на субдомене electronics-and-mechanics
Все записи на субдомене: Электроника и механика (записки от AZM)

Работа с I2C памятью 24cXXX, например 24c512 используя TWI микроконтроллера AVR ATmega88 на Си (CodeVisionAVR C Compiler)
Встала ребром задача работы с 24c512 на ATmega88, после тщетных поисков вменяемой библиотеки для работы с памятью используя TWI контроллера, было решено написать собственные функции.

Запись байта в память
// ST --------------------------------- Записать байт в 24Cxxx
// Значения возврата:
// 0 успешно
// 1 пробуйте ещё раз
// 2 не сформирован сигнал "старт"
// 4 ошибка работы с устройством
unsigned char eto_eeWrite(unsigned char chipaddr, unsigned int adr, unsigned char inf){
TWCR=0b10100100; // ВКЛ+СТАРТ TWINT|TWSTA|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x08){return 2;}
TWDR=chipaddr; // SLA+W
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) != 0x18){if ((TWSR & 0xF8) == 0x38){return 1;}else{return 4;}}
TWDR=adr>>8;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWDR=adr&0b0000000011111111;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWDR=inf;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWCR=0b10010100; // СТОП TWINT|TWSTO|TWEN
return 0;
}
// EN --------------------------------- Записать байт в 24Cxxx
Чтение байта из памяти
// ST --------------------------------- Прочитать байт из 24Cxxx
// Значения возврата:
// 0 успешно
// 1 пробуйте ещё раз
// 2 не сформирован сигнал "старт"
// 4 ошибка работы с устройством
unsigned char eto_eeRead(unsigned char chipaddr, unsigned int adr, unsigned char* inf){
TWCR=0b10100100; // ВКЛ+СТАРТ TWINT|TWSTA|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x08){return 2;}
TWDR=chipaddr; // SLA+W
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) != 0x18){if ((TWSR & 0xF8) != 0x38){return 1;}else{return 4;}}
TWDR=adr>>8;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWDR=adr&0b0000000011111111;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWCR=0b10100100; // ВКЛ+СТАРТ TWINT|TWSTA|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x10){return 2;}
TWDR=chipaddr|1; // SLA+R
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x40){return 4;}
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
*inf=TWDR;
TWCR=0b10010100; // СТОП TWINT|TWSTO|TWEN
return 0;
}
// EN --------------------------------- Прочитать байт из 24Cxxx
Если вдруг кому то нужно выключать TWI после того как байт записан или прочитан, то после строки:
TWCR=0b10010100; // СТОП TWINT|TWSTO|TWEN
перед строкой
return 0;
Добавляется код:
while ((TWCR & 0b00010000) != 0);
TWCR=0b00000000; // ВЫКЛ TWI
Для желающих пойти дальше и писать не по одному байту, ниже приведена процедура пакетной записи двух байт (signed int):
// ST --------------------------------- Записать байт в 24Cxxx
// Значения возврата:
// 0 успешно
// 1 пробуйте ещё раз
// 2 не сформирован сигнал "старт"
// 4 ошибка работы с устройством
unsigned char eto_eeWriteSignedByte(unsigned char chipaddr, unsigned int adr, signed int inf){
TWCR=0b10100100; // ВКЛ+СТАРТ TWINT|TWSTA|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x08){return 2;}
TWDR=chipaddr; // SLA+W
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) != 0x18){if ((TWSR & 0xF8) == 0x38){return 1;}else{return 4;}}
TWDR=adr>>8;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWDR=adr&0b0000000011111111;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWDR=inf&0b0000000011111111;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWDR=inf>>8;
TWCR=0b10000100; // Передать TWINT|TWEN
while ((TWCR & 0b10000000) == 0);
if ((TWSR & 0xF8) !=0x28){return 4;}
TWCR=0b10010100; // СТОП TWINT|TWSTO|TWEN
return 0;
}
// EN --------------------------------- Записать байт в 24Cxxx
Для пакетного чтения используется та же методика, а именно:
1) передача адреса ячейки откуда начать читать;
2) Чтение байта;
3) Чтение следующего байта;
... ...

Обращаем внимание на то, что процедуры не используют прерывания TWI и создают задержки используя пустые циклы для того, что бы дождаться ответов TWI, соответственно эти процедуры уместно применять там, где не требуется выжимать максимум производительности из контроллера. Впрочем, не так велики задержки обмена информацией с данными микросхемами памяти.

Ещё немного важной информации:
Прежде чем работать с TWI нужно установить скорость обмена информацией в регистре TWBR, хотя в простейшем случае (максимальная скорость) никакие регистры можно не трогать, то есть будет вот так:
// 2 Wire Bus initialization
// Generate Acknowledge Pulse: Off
// 2 Wire Bus Slave Address: 0h
// General Call Recognition: Off
// Bit Rate: 62,500 kHz
TWSR=0x00;
TWBR=0x00;
TWAR=0x00;
TWCR=0x00;
По процедурам:
chipaddr - адрес микросхемы памяти (задаётся тем какие ножки микросхемы куда повешены, если обе на земле то адрес будет 0xA0).
adr - адрес ячейки микросхемы памяти откуда будем читать/куда будем писать.

Возвращаемое значение:
// 1 пробуйте ещё раз
означает, что некое другое устройство перехватило контроль на шиной и в данный момент времени невозможно работать с шиной в режиме ведущего.

Как использовать
Копируете отсюда, вставляете в свой исходник, выше, чем собираетесь вызывать код нужных функций. Вызываете из, например так:
if (eto_eeWrite(0xA0, 10, 144)){
// успешно записали 144 в ячейку 10
}else{
// имеется некая ошибка
}
Как видим, всё решено топорно "тупо в лоб". Надесь поможет, либо послужит подспорьем для разработки своих функций работы с I2C.

Добавлено: 4688 дн 22 час 1 мин 46 сек назад | Внесений правок: 0 | Последняя правка: нет данных



Электроника и механика (записки от AZM)