Różnice w sposobach zapisu wewnętrznych pamięci EEPROM AT89S8252 i T89C51RD2
Czasami zaczyna brakować pamięci na program puchnący wraz z wymaganiami klienta, który już nauczył się, że można od mikrokontrolera oczekiwać czegoś więcej i zaczynamy się rozglądać za mikrokontrolerami alternatywnymi. Czasami również jest konieczne zwiększenie szybkości wykonywania programu. Tak było i w moim wypadku: stanąłem przed obiema tymi kwestiami jednocześnie. Używałem AT89S8252 i kod wynikowy programu przekroczył rozmiar pamięci FLASH. Potrzebowałem mikrokontrolera o większej ilości pamięci lub zewnętrznej pamięci programu. Potrzebowałem również większej szybkości CPU, ponieważ niebezpiecznie rozrosły się funkcje realizowane w obsłudze przerwania jednego z Timer’ów.
Mój wybór padł na P89C51RD2, gdyż wiedziałem od kolegi, że model RD2 ma 2 kB wewnętrznej pamięci EEPROM (której to bardzo potrzebowałem do przechowywania danych), 6-taktową jednostkę CPU oraz 64 kB na program. Niestety, podczas zakupu nie uwzględniłem jednego, oczywistego faktu: kolega mówił o TEMIC’u, a ja kupiłem PHILIPS’a. Przecież RD2 to RD2! Okazało się, że są pomiędzy nimi różnice i że polegają one na przykład na braku pamięci EEPROM w produkcie firmy PHILIPS.
Oba mikrokontrolery mają możliwość zapisu własnej pamięci programu, ale to nie jest to samo. Podstawową różnicą jest liczba cykli zapisu: FLASH przeznaczony na kod programu można zapisać około 1000 razy, a EEPROM 100 tysięcy razy. Jest to istotna różnica, jeśli przechowywane dane często ulegają zmianie. Ponadto, aby zapisać pamięć programu trzeba posługiwać się funkcjami bootlader’a i zapisywać dane blokami. Nie jest to zbyt wygodne przy konstrukcji prostej, małej bazy danych bez bufora i systemu plików.
Dla odmiany przeniesienie programu z AT89S8252 do T89C51RD2 a następnie do AT89C51RD2 (Atmel) odbyło się „bezboleśnie”. Oprócz drobiazgów związanych z nastawami rejestrów konfiguracyjnych, jedyna, najważniejsza różnica, polegała na obsłudze zapisu i odczytu danych w wewnętrznej pamięci EEPROM. RD2 TEMIC’a czy ATMEL’a ma jej tyle samo, co AT89S8252, czyli 2 kB. Funkcje obsługi pamięci EEPROM, wraz z przykładami ich użycia w języku C, prezentują poniższe listingi. Dosyć jest dodać, że sprawują się bez zarzutu.
Jacek Bogusz
j.bogusz@easy-soft.net.pl
Listing 1. Podstawowe funkcje obsługi pamięci EEPROM mikrokontrolera AT89S8252
//*************************************
// AT89S8252, obsługa pamięci EEPROM
//*************************************
pdata char * ee2addr = 0; //wskaźnik do pamięci eeprom
;Odczyt bajtu danych z pamięci EEPROM,16-bitowy adres w ADDRESS
char EE_GetByte(unsigned int ADDRESS)
{
char B;
WMCON |= 0x08; //załączenie trybu odczytu eeprom
B = *(ee2addr+ADDRESS); //odczyt bajtu
WMCON &= 0xE7; //wyłączenie pamięci eeprom
return (B);
}
;Zapamiętanie bajtu danych w pamięci EEPROM,16-bitowy adres w ADDRESS, bajt w X
void EE_StoreByte(char B, unsigned int ADDRESS)
{
WMCON |= 0x18; //włączenie trybu zapisu
*(ee2addr + ADDRESS) = B; //zapis bajtu
while (WMCON & 0x02); //testowanie stanu zajętości
WMCON &= 0xE7; //wyłączenie eeprom
}
Listing 2. Podstawowe funkcje obsługi pamięci EEPROM w T/AT89C51RD2
//*************************************
// T89C51RD2, obsługa pamięci EEPROM
//*************************************
//odczyt bajtu z eeprom; adres bajtu w eeprom zawiera parametr ADDRESS
char EE_GetByte(unsigned int ADDRESS)
{
char B;
EECON = 0x02; //załączenie trybu odczytu eeprom
B = *(e2addr+ADDRESS);
EECON = EECON & 0xFD;
return (B);
}
//zapis bajtu do eeprom, bajt przekazywany w parametrze B, adres w ADDRESS
void EE_StoreByte(char B, WORD ADDRESS)
{
EETIM = 0xDC; //ustawienie czasu programowania (Vss=5V)
EECON = 0x02; //załączenie eeprom
*(e2addr+ADDRESS) = B; //zapis bajtu do bufora
EECON = 0x50; //zapis bajtu do eeprom
EECON = 0xA0;
while (EECON & 0x01); //testowanie flagi zajętości
}
Listing 3. Przykłady użycia funkcji zapisu / odczytu pamięci EEPROM
//odczyt statusu rekordu w eeprom; wartość "1" oznacza, że pozycja jest zajęta
bit EE_PosActive(unsigned int ADDRESS)
{
return (EE_GetByte(ADDRESS) != 0xFF);
}
//zapis COUNT bajtów obszaru pamięci RAM pod adres wskazywany przez argument
//ADDRESS w eeprom
void EE_SaveBUF(unsigned int ADDRESS, char COUNT)
{
data char *ptrb = (data char*)(&BUF);
char i;
for (i=0; i < COUNT; i++) EE_StoreByte(*ptrb++, ADDRESS++);
}
//przepisanie COUNT bajtów z pamięci EEPROM do RAM spod adresu ADDRESS
void EE_ReadBUF(WORD ADDRESS, char COUNT)
{
data char *ptrb = (data char*)(&BUF);
char i;
for (i=0; i < COUNT; i++) *ptrb++ = EE_GetByte(ADDRESS++);
}
Dodaj nowy komentarz