Aktualnie wykorzystując bibliotekę Wire, jest inicjowane połączenie z chipem, wysyłając komendę START(S) i kończone wysyłając komendę STOP. Reszta, czyli zapis, odczyt oraz wybór odpowiednich komórek w pamięci, jest w opracowaniu. Chip który wykorzystuje to Atmel 24C16, jego pojemność wynosi 16Kb (kilobitów), więc nie jest on specjalnie duży.
//Edit
Udało się zaimplementować zapis i odczyt pojedynczych bajtów do komórek. Jak wspomniałem wcześniej wykorzystuję bibliotekę Wire, która ułatwia pracę z magistralą I2C(TWI). Nie muszę się martwić o ręczne wysyłanie zdarzenia START(S), START Repeat(Sr), bądź zdarzenia STOP. Największy problem sprawiało mi utworzenie adresu sprzętowego (nie mylić z identyfikatorem urządzenia), za pomocą którego informujemy EEPROM o adresie komórki, do której chcemy coś zapisać albo coś odczytać. W adresie sprzętowym zawarty unikalny dla czipa adres komórki. W kodzie podaje się go w formacie szesnastkowym. (0xZXC, gdzie ZXC to numer komórki pamięci). Aby go utworzyć należy pobrać identyfikator urządzenia, wykonać logiczne OR z adresem komórki, który przesuwamy o 8 bitów w prawo robiąc logiczne AND z cyfrą 0x07. (wynika to z datasheetu).
Kod:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
byte deviceaddress = 0x50; | |
byte eeaddress = 0x010; | |
byte devaddr = deviceaddress | ((eeaddress >> 8) & 0x07); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Wire.beginTransmission(devaddr); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Wire.write(int(addr)); | |
Wire.write(int(data)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Wire.endTransmission(); |
Sam czip zaś jest zapakowany w obudowę DIP8, dzięki czemu bardzo łatwo się z niego korzysta.
Piny A0, A1, A2 spinamy z GND, wykorzystane będą kiedy podłączone zostanie wiele czipów EEPROM na raz. GND i VCC podpinamy kolejno do pinu GND i 5V w Arduino. WP służy do zabezpieczenia przed zapisem i podpięty jest pod 8 pin. Jeśli stan będzie wysoki to EEPROM zostanie zabezpieczony przed zapisem. Piny SCL i SDA są podpięte pod piny A5 i A4, tam są usytuowane te same piny, tylko w Arduino. Na dodatek musiałem zrobić tzw. pull-up, czyli podłączyć obie linie (SCL i SDA) do źródła napięcia za pomocą rezystorów od 1K do 45K(im mniejsza wartość tym większa prędkość transmisji), ponieważ I2C nie potrafi wywołać stanu wysokiego; potrafi tylko wywołać niski(active drain).
Odczyt z komórki jest prostszy od zapisu (to chyba logiczne), polega on na utworzeniu adresu sprzętowego (tak jak w zapisie), wysłaniu adresu komórki, "poproszeniu" o odczyt z pamięci, odczytu z pamięci, jeśli magistrala jest wolna, tj. nikt z niej nie korzysta, oraz na wyświetleniu odczytanych danych w serial monitorze.
Kod odczytu:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int eeprom_read_byte(byte deviceaddress, unsigned eeaddr) | |
{ | |
byte rdata = 0; | |
// utworzenie adresu sprzętowego | |
byte devaddr = deviceaddress | ((eeaddr >> 8) & 0x07); | |
byte addr = eeaddr; | |
//rozpoczęcie transmisji, ustawienie składowych klasy Wire oraz wysłanie adresu sprzętowego. | |
Wire.beginTransmission(devaddr); | |
//Wysłanie adresu komórki. Tutaj jest wysyłane zdarzenie START(S), potem dane, a na końcu zdarzenie STOP. | |
Wire.write(int(addr)); | |
//zakończenie transmisji | |
Wire.endTransmission(); | |
//proźba o odczyt | |
Wire.requestFrom(int(devaddr), 1); | |
//sprawdzenie czy magistarala jest wolna oraz odczyt danych. | |
if (Wire.available()) { | |
rdata = Wire.read(); | |
} | |
//wyświetlenie na serial monitorze | |
Serial.println(rdata); | |
delay(1000); | |
return rdata; | |
} |
Kod zapisu:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//deviceaddress jest identyfikatorem urządzenia, eeadress - adres komórki w pamięci, data - dane | |
void eepromWrite(byte deviceaddress, int eeaddress, byte data) | |
{ | |
byte devaddr = deviceaddress | ((eeaddress >> 8) & 0x07); //utworzenie adresu sprzętowego | |
byte addr = eeaddress; | |
Wire.beginTransmission(devaddr); // rozpoczynamy transmisję przy pomocy utworzonego adresu sprzętowego | |
Wire.write(int(addr)); // wysłanie adresu komórki | |
Wire.write(int(data)); // wysłanie danych | |
Wire.endTransmission(); // zakończenie zdarzenia | |
delay(100); | |
} |