Запись от 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. |
Добавлено: 4730 дн 5 час 17 мин 28 сек назад | Внесений правок: 0 | Последняя правка: нет данных |