Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

obrazek

Autor artykułu: mgr Jerzy Wałaszek
Konsultacje: Wojciech Grodowski, mgr inż. Janusz Wałaszek

©2024 mgr Jerzy Wałaszek
I LO w Tarnowie

obrazek

Mikrokontrolery

ATtiny25/45/85

Pamięć AVR

obrazek

Educational and Non-Profit Use of Copyrighted Material:

If you use Microchip copyrighted material solely for educational (non-profit) purposes falling under the “fair use” exception of the U.S. Copyright Act of 1976 then you do not need Microchip’s written permission. For example, Microchip’s permission is not required when using copyrighted material in: (1) an academic report, thesis, or dissertation; (2) classroom handouts or textbook; or (3) a presentation or article that is solely educational in nature (e.g., technical article published in a magazine).

https://www.microchip.com/about-us/legal-information/copyright-usage-guidelines

SPIS TREŚCI
Podrozdziały

obrazek

Ten rozdział opisuje różne pamięci w ATtiny25/45/85. Architektura AVR posiada dwie główne przestrzenie pamięciowe: przestrzeń pamięci danych (ang. data memory space) oraz przestrzeń pamięci programu (ang. program memory space). Dodatkowo mikrokontroler ATtiny25/45/85 jest wyposażony w nieulotną pamięć EEPROM (ang. Electrically Erasable and Programmable Read-Only Memory) na przechowywanie danych. Wszystkie przestrzenie pamięciowe są liniowe i regularne.

Reprogramowalna pamięć FLASH dla programu

Mikrokontroler ATtiny25/45/85 zawiera 2/4/8 KB reprogramowalnej w systemie pamięci FLASH do przechowywania programu. Ponieważ wszystkie instrukcje AVR mają długość 16 lub 32 bity, pamięć FLASH jest zorganizowana jako 1024/2048/4096 komórek 16-bitowych.

Trwałość pamięci FLASH wynosi co najmniej 10.000 cykli zapisu/kasowania. Licznik rozkazów (ang. Program Counter, PC) w ATtiny25/45/85 jest 10/11/12-bitowy, co pozwala mu na zaadresowanie 1024/2048/4096 komórek pamięci programu. W rozdziale "Programowanie pamięci" znajdziesz szczegółowy opis szeregowego ładowania programu do pamięci FLASH za pomocą końcówek interfejsu SPI (ang. Serial Programming Interface).

Tablice ze stałymi mogą być umieszczane w całej przestrzeni adresowej pamięci programu (zobacz na opis instrukcji LPM).

Mapa pamięci programu


do podrozdziału  do strony 

Pamięć SRAM dla danych

Powyższy rysunek pokazuje sposób organizacji pamięci SRAM w mikrokontrolerze ATtiny25/45/85.

Dolne 224/352/607 komórek zawiera zestaw rejestrów, pamięć we/wy oraz wewnętrzną pamięć danych SRAM. Pierwsze 32 komórki to zestaw rejestrów ogólnego przeznaczenia, następne 64 komórki to standardowa pamięć we/wy, a ostatnie 128/256/512 komórek odnoszą się do wewnętrznej pamięci danych SRAM.

Pięć różnych trybów adresowania pamięci danych pokrywa: adresowanie bezpośrednie (ang. Direct Addressing Mode), adresowanie pośrednie z przesunięciem (ang. Indirect with Displacement Addressing Mode), adresowanie pośrednie (ang. Indirect Addressing Mode)adresowanie pośrednie z predekrementacją (ang. Indirect with Pre-decrement Addressing Mode) oraz adresowanie pośrednie z  postinkrementacją (ang. Indirect with Post-increment Addresing Mode). W zestawie rejestrów rejestry od R26 do R31 pełnią dodatkową funkcję rejestrów wskaźnikowych do pośredniego adresowania pamięci.

Adresowanie bezpośrednie obejmuje całą przestrzeń danych.

Adresowanie pośrednie z przesunięciem obejmuje 63 komórki od adresu bazowego danego w rejestrze Y lub Z.

Gdy jest używane pośrednie adresowanie z automatyczną predekrementacją lub postinkrementacją, rejestry adresowe X, Y lub Z są zwiększane lub zmniejszane.

Wszystkie te tryby adresowania w ATtiny25/45/85 pozwalają na dostęp do każdej lokacji w przestrzeni danych: do zestawu 32 rejestrów ogólnego przeznaczenia, 64 rejestrów we/wy oraz 128/256/512 bajtów wewnętrznej pamięci danych SRAM. Opis zestawu rejestrów znajdziesz w rozdziale "Zestaw rejestrów ogólnego przeznaczenia".

Czasy dostępu do pamięci danych

Dostęp do pamięci SRAM wykonywany jest w dwóch taktach clkCPU, co pokazuje poniższy rysunek:

obrazek

 

do podrozdziału  do strony 

Pamięć EEPROM dla danych

Mikrokontroler ATtiny25/45/85 zawiera 128/256/512 bajtów pamięci danych EEPROM (ang. Electrically Erasable Programmable Read-Only Memory). Jest ona zorganizowana jako oddzielna przestrzeń danych, w której można zapisywać pojedyncze bajty. EEPROM posiada wytrzymałość co najmniej 100.000 cykli zapisu/kasowania. Dostęp mikroprocesora do danych zapisanych w pamięci EEPROM dokonywany jest poprzez rejestr adresu EEPROM, rejestr danych EEPROM oraz rejestr sterowania EEPROM. Istnieje również możliwość zapisu/odczytu zawartości EEPROM poprzez interfejs SPI.

Zapis/Odczyt EEPROM

Rejestry dostępu do EEPROM znajdują się w przestrzeni we/wy.

Czasy dostępu dla EEPROM są podane przy opisie rejestru sterującego pamięcią EEPROMEECR (ang. EEPROM Control Register). Jednakże funkcja odmierzająca samoczynnie czas pozwala wykryć oprogramowaniu użytkownika, kiedy można zapisać następny bajt. Jeśli kod użytkownika zawiera instrukcje, które zapisują pamięć EEPROM, należy podjąć pewne środki ostrożności. W mocno filtrowanych źródłach zasilania napięcie VCC może wzrastać lub opadać wolno przy włączaniu/wyłączaniu. Powoduje to, iż mikrokontroler przez pewien okres czasu pracuje przy napięciu niższym od określonego jako minimalne dla używanej częstotliwości zegarowej. Zobacz do podrozdziału "Zapobieganie uszkodzeniu danych w EEPROM", gdzie znajdziesz więcej informacji o tym, jak unikać problemów w takich sytuacjach.

Aby zapobiec niezamierzonym zapisom w EEPROM, należy zastosować specjalną procedurę zapisu. Szczegóły znajdziesz w podrozdziałach "Atomowe programowanie bajtu" oraz "Rozdzielone programowanie bajtu".

Gdy odczytywana jest pamięć EEPROM, to mikroprocesor zostaje wstrzymany przez cztery cykle zegarowe przed wykonaniem następnej instrukcji. Gdy zapisywana jest pamięć EEPROM, mikroprocesor jest wstrzymywany przez dwa cykle zegara przed wykonaniem następnej instrukcji.


Atomowe programowanie bajtu

Użycie Atomowego Programowania Bajtu (ang. Atomic Byte Programming) jest najprostszym trybem. Przy zapisie bajtu do EEPROM, użytkownik musi wpisać jego adres do rejestru EEARL oraz dane do rejestru EEDR. Jeśli bity EEPMn mają wartość zero, to zapis bitu EEPE (w ciągu czterech cykli zegara po zapisie bitu EEMPE) rozpocznie operację kasowania/zapisu. Cykle kasowania jak i zapisu są wykonywane razem w jednej operacji, a całkowity czas programowania podany jest w opisie rejestru EECR. Bit EEPE pozostaje w stanie 1 aż zakończą się obie operacje kasowania i zapisu. Gdy pamięć jest zajęta programowaniem, nie można na niej wykonywać żadnych innych operacji.


Rozdzielone programowanie bajtu

Możliwe jest rozdzielenie cyklów kasowania i zapisu na dwie osobne operacje. Może to być przydatne, jeśli system wymaga krótkiego czasu dostępu przez pewien ograniczony okres czasu (typowo, gdy spada napięcie zasilające). Aby skorzystać z tej metody, zapisywane komórki muszą być wcześniej wykasowane. Jednak ponieważ operacje kasowania i zapisu są rozdzielone, możliwe jest wykonanie operacji kasowania, gdy system pozwala na wykonywanie operacji krytycznych czasowo (zwykle po włączeniu zasilania).

Kasowanie

Aby skasować bajt, jego adres musi zostać wpisany do rejestru EEARL. Jeśli bity EEPMn mają stan 0b01, zapis bitu EEPE (w ciągu czterech cykli zegara po zapisie bitu EEMPE) rozpocznie tylko operację kasowania (czas programowania podany jest w opisie rejestru EECR). Bit EEPE pozostaje w stanie 1 aż zakończy się operacja kasowania. Gdy pamięć jest zajęta programowaniem, nie można na niej wykonywać żadnych innych operacji.

Zapis

Aby zapisać dane do wybranej komórki pamięci EEPROM, użytkownik musi wpisać jej adres do rejestru EEARL oraz dane do rejestru EEDR.. Jeśli bity EEPMn mają stan 0b10, to zapis bitu EEPE (w ciągu czterech cykli zegara po zapisie bitu EEMPE) rozpocznie tylko operację zapisu (czas programowania podany jest w opisie rejestru EECR). Bit EEPE pozostaje w stanie 1 aż zakończy się operacja zapisu. Jeśli zapisywana komórka nie została wcześniej wykasowana, to zapisywane dane należy potraktować jako utracone. Gdy pamięć EEPROM jest zajęta programowaniem, nie można na niej wykonywać żadnych innych operacji.

Do odmierzania czasów dostępów do EEPROM używany jest kalibrowany oscylator. Upewnij się, iż częstotliwość tego oscylatora spełnia wymagania podane przy opisie rejestru OSCCAL.

Poniższe przykłady kodów pokazują po jednej funkcji w asemblerze i w języku C dla kasowania, zapisu lub atomowego zapisu EEPROM. Przykłady zakładają globalne wyłączenie przerwań (wyzerowany bit I w rejestrze stanu SREG), aby żadne z przerwań nie wystąpiło podczas wykonywania tych funkcji.
Przykład w kodzie maszynowym
EEPROM_write:
  ; Zaczekaj na dokończenie poprzedniego zapisu
  sbic EECR,EEPE
  rjmp EEPROM_write
  ; Ustaw tryb Programowanie
  ldi r16, (0<<EEPM1)|(0<<EEPM0)
  out EECR, r16
  ; Ustaw adres (r18:r17) w rejestrze adresowym
  out EEARH, r18
  out EEARL, r17
  ; Zapisz dane (r19) do rejestru danych
  out EEDR,r19
  ; Wpisz logiczną jedynkę do bitu EEMPE
  sbi EECR,EEMPE
  ; Rozpocznij zapis w EEPROM przez ustawienie bitu EEPE
  sbi EECR,EEPE
  ret
Przykład w języku C
void EEPROM_write(unsigned int ucAddress, unsigned char ucData)
{
  /* Zaczekaj na dokończenie poprzedniego zapisu */
  while(EECR & (1<<EEPE));
  /* Ustaw tryb Programowanie */
  EECR = (0<<EEPM1)|(0>>EEPM0)
  /* Ustaw rejestry adresu i danych */
  EEAR = ucAddress;
  EEDR = ucData;
  /* Wpisz logiczną jedynkę do bitu EEMPE */
  EECR |= (1<<EEMPE);
  /* Rozpocznij zapis w EEPROM przez ustawienie bitu EEPE */
  EECR |= (1<<EEPE);
}

Następne przykłady kodu pokazują funkcje w asemblerze i w języku C dla odczytu EEPROM. Przykłady zakładają globalne wyłączenie przerwań podczas wykonywania tych funkcji..
Przykład w kodzie maszynowym
EEPROM_read:
  ; Zaczekaj na dokończenie poprzedniego zapisu
  sbic EECR,EEPE
  rjmp EEPROM_read
  ; Ustaw adres (r18:r17) w rejestrze adresowym
  out EEARH, r18
  out EEARL, r17
  ; Rozpocznij odczyt EEPROM przez zapis EERE
  sbi EECR,EERE
  ; Odczytaj dane z rejestru danych
  in r16,EEDR
ret
Przykład w języku C
unsigned char EEPROM_read(unsigned int ucAddress)
{
  /* Zaczekaj na dokończenie poprzedniego zapisu */
  while(EECR & (1<<EEPE));
  /* Ustaw rejestr adresowy */
  EEAR = ucAddress;
  /* Rozpocznij odczyt EEPROM przez zapis EERE */
  EECR |= (1<<EERE);
  /* Zwróć dane z rejestru danych */
  return EEDR;
}


Zapobieganie uszkodzeniu danych w EEPROM

Podczas okresów niskiego napięcia zasilającego VCC dane w EEPROM mogą ulec uszkodzeniu przy zapisie, ponieważ napięcie zasilające jest zbyt niskie na poprawne funkcjonowanie mikroprocesora oraz EEPROM. Problem ten jest taki sam jak w systemach z zewnętrznymi pamięciami EEPROM i te same rozwiązania powinny być stosowane.

Uszkodzenie danych w EEPROM może być spowodowane przez dwie sytuacje, gdy napięcie jest zbyt niskie. Po pierwsze normalna sekwencja zapisu do EEPROM wymaga minimalnego napięcia, aby zadziałać prawidłowo. Po drugie sam mikroprocesor może nieprawidłowo wykonywać instrukcje, jeśli napięcie zasilania jest zbyt niskie.

Uszkodzeniu danych w EEPROM można łatwo zapobiec, stosując następujące zalecenia projektowe:

Utrzymuj końcówkę  AVR RESET w stanie aktywnym (niskim 0) podczas okresów niewystarczającego napięcia zasilania. Można to zrobić, przez uaktywnienie wewnętrznego detektora spadku napięcia (ang. Brown-out Detector, BOD). Jeśli poziom wykrywania wewnętrznego detektora BOD nie odpowiada wymaganemu poziomowi wykrywania, to można użyć zewnętrznego układu resetowania przy niskim napięciu VCC. Jeśli reset wystąpi podczas operacji zapisu, operacja ta zostanie dokończona o ile napięcie zasilania jest wystarczające.


do podrozdziału  do strony 

Pamięć wejścia/wyjścia

Definicja przestrzeni we/wy mikrokontrolera ATtiny25/45/85 pokazana jest w rozdziale "Podsumowanie rejestrów".

Wszystkie układy we/wy ATtiny25/45/85 obsługiwane są poprzez rejestry w przestrzeni we/wy. Dostęp do wszystkich rejestrów we/wy wykonywany jest przez instrukcje LD/LDS/LDD i ST/STS/STD, przesyłające dane pomiędzy 32 rejestrami ogólnego przeznaczenia a przestrzenią we/wy. Rejestry we/wy o adresach w zakresie 0x00 – 0x1F są bezpośrednio dostępne bitowo przy pomocy instrukcji SBI i CBI. W rejestrach tych wartość pojedynczych bitów można sprawdzać instrukcjami SBIS i SBIC. Gdy są używane dedykowane instrukcje IN i OUT, należy używać adresów we/wy 0x00 – 0x3F. Gdy rejestry we/wy są adresowane w przestrzeni danych za pomocą instrukcji LD i ST, należy do tych adresów dodać 0x20.

Dla kompatybilności z przyszłymi mikrokontrolerami zarezerwowane bity powinny być zapisywane stanami 0 przy dostępie do rejestrów. Zarezerwowanych adresów w pamięci we/wy nie należy nigdy zapisywać.

Niektóre ze znaczników stanu są zerowane przez zapis w nich stanu 1. Zwróć uwagę, iż w przeciwieństwie do większości innych mikrokontrolerów AVR instrukcje CBI i SBI działają tylko na określonym bicie i można je z tego powodu używać na rejestrach zawierających takie znaczniki stanu. Instrukcje CBI i SBI pracują jedynie na rejestrach od 0x00 do 0x1F.


do podrozdziału  do strony 

Opis rejestrów

EEARH – EEPROM Address Register – Rejestr adresowy EEPROM

Bit 7 6 5 4 3 2 1 0  
0x1F EEAR8 EEARH
Zapis/Odczyt O O O O O O O Z/O  
Wartość początkowa 0 0 0 0 0 0 0 X/0  

Bity 7:1 – Zarezerwowane

Te bity są zarezerwowane do przyszłego użytku i przy odczycie dają zawsze wartość 0.

Bit 0 – EEAR8: EEPROM Address – Adres EEPROM

Jest to najbardziej znaczący bit adresu EEPROM dla mikrokontrolera ATtiny85. W mikrokontrolerach z mniejszą pamięcią EEPROM, tj. w ATtiny25/45, bit ten jest zarezerwowany i przy odczycie zawsze daje zero. Początkowy adres w rejestrze EEAR jest niezdefiniowany i właściwa wartość musi być zapisana do niego przed dostępem do EEPROM.


EEARL – EEPROM Address Register – Rejestr adresowy EEPROM

Bit 7 6 5 4 3 2 1 0  
0x1E EEAR7 EEAR6 EEAR5 EEAR4 EEAR3 EEAR2 EEAR1 EEAR0 EEARL
Zapis/Odczyt Z/O Z/O Z/O Z/O Z/O Z/O Z/O Z/O  
Wartość początkowa X/0 X X X X X X X  

Bit 7 – EEAR7: EEPROM Address – Adres EEPROM

Jest to najbardziej znaczący bit adresu EEPROM dla mikrokontrolera ATtiny45. W mikrokontrolerach z mniejszą pamięcią EEPROM, tj. w ATtiny25, bit ten jest zarezerwowany i przy odczycie zawsze daje zero. Początkowy adres w rejestrze EEAR jest niezdefiniowany i właściwa wartość musi być zapisana do niego przed dostępem do EEPROM.

Bity 6:0 – EEAR[5:0]: EEPROM Address – Adres EEPROM

To jest 6 młodszych bitów adresu EEPROM. Dane w EEPROM są adresowane liniowo w zakresie od 0 do 127/255/511. Początkowa zawartość rejestru EEARL jest niezdefiniowana. Przed dostępem do  EEPROM należy wpisać poprawny adres.


EEDR – EEPROM Data Register – Rejestr danych EEPROM

Bit 7 6 5 4 3 2 1 0  
0x1D EEDR7 EEDR6 EEDR5 EEDR4 EEDR3 EEDR2 EEDR1 EEDR0 EEDR
Zapis/Odczyt Z/O Z/O Z/O Z/O Z/O Z/O Z/O Z/O  
Wartość początkowa X X X X X X X X  

Bity 7:0 – EEDR7:0: EEPROM Data – Dane EEPROM

Dla operacji zapisu w EEPROM rejestr EEDR zawiera dane do zapisania pod adresem podanym przez rejestr EEARL. Dla operacji odczytu z EEPROM rejestr EEDR zawiera dane odczytane z komórki EEPROM o adresie podanym w rejestrze EEARL.


EECR – EEPROM Control Register – Rejestr sterujący EEPROM

Bit 7 6 5 4 3 2 1 0  
0x1C - - EEPM1 EEPM0 EERIE EEMPE EEPE EERE EECR
Zapis/Odczyt O O Z/O Z/O Z/O Z/O Z/O Z/O  
Wartość początkowa 0 0 X X X X X 0  

Bit 7 – Zarezerwowany

Ten bit został zarezerwowany do użytku w przyszłości i na ATtiny25/45/85 daje przy odczycie wartość 0. Dla kompatybilności z przyszłymi mikrokontrolerami AVR zawsze zapisuj ten bit stanem 0. Po odczycie wymaskuj ten bit z wyniku.

Bit 6 – Zarezerwowany

Ten bit jest zarezerwowany w ATtiny25/45/85 i daje przy odczycie zawsze wartość zero.

Bity 5:4 – EEPM[1:0]: EEPROM Programming Mode Bits – Bity trybu programowania EEPROM

Bity te ustalają rodzaj programowania, które zostanie wyzwolone przy zapisie do bitu EEPE. Możliwe jest programowanie danych w jednej operacji atomowej (skasowanie starej zawartości i zaprogramowanie nowej) lub rozdzielenie operacji kasowania i zapisu na dwie osobne operacje. Czasy programowania pokazane są w poniższej tabeli.  Gdy bit EEPE jest ustawiony, każdy zapis do bitów EEPMn zostanie zignorowany. Podczas resetu bity EEPMn zostaną ustawione na 0b00, chyba że pamięć EEPROM jest zajęta programowaniem.

Bity trybu programowania EEPROM

EEPM1 EEPM0 Czas
programowania
Operacja
0 0 3,4 ms Kasowanie i zapis w jednej operacji (operacja atomowa)
0 1 1,8 ms Tylko kasowanie
1 0 1,8 ms Tylko zapis
1 1 Zarezerwowane na przyszłość

Bit 3 – EERIE: EEPROM Ready Interrupt Enable – Włączenie przerwań przy gotowości EEPROM

Ustawienie bitu EERIE na 1 uaktywnia przerwania przy gotowości EEPROM, jeśli bit I w SREG jest ustawiony. Wyzerowanie bitu EERIE wyłącza to przerwanie. Przerwanie to jest generowane ciągle, gdy pamięć nieulotna jest gotowa na programowanie.

Bit 2 – EEMPE: EEPROM Master Program Enable – Główne uaktywnienie programowania EEPROM

Bit EEMPE określa, czy zapis jedynki do bitu EEPE odniesie jakiś skutek, czy też nie. Gdy bit EEMPE zostanie ustawiony, to ustawienie EEPE w ciągu czterech cykli zegarowych spowoduje zaprogramowanie komórki EEPROM pod wybranym adresem. Jeśli EEMPE ma wartość zero, to ustawienie EEPE nie będzie miało żadnego skutku. Gdy do bitu EEMPE program wpisał 1, to bit ten zostanie wyzerowany sprzętowo po czterech cyklach zegarowych.

Bit 1 – EEPE: EEPROM Program Enable – Programowanie EEPROM

Sygnał EEPE jest sygnałem wyzwalającym programowanie EEPROM. Gdy bit EEPE zostanie zapisany, pamięć EEPROM będzie zapisana zgodnie z ustawieniem bitów EEPMn. Przed zapisem logicznej jedynki do bitu EEPE bit EEMPE musi zostać ustawiony na 1, inaczej zapis do EEPROM nie odbędzie się. Gdy upłynie czas zapisu bit EEPE zostanie wyzerowany sprzętowo. Gdy bit EEPE zostanie ustawiony, mikroprocesor jest wstrzymywany na dwa cykle zegarowe przed wykonaniem następnej instrukcji.

Bit 0 – EERE: EEPROM Read Enable – Odczyt EEPROM

Sygnał EERE jest strobem odczytu dla EEPROM. Gdy poprawny adres zostanie ustawiony w rejestrze EEARL, bit EERE musi być zapisany stanem 1, aby wyzwolić odczyt z EEPROM. Dostęp odczytu z EEPROM zajmuje jedną instrukcję, a zażądane dane są dostępne natychmiast. Gdy pamięć EEPROM jest odczytywana, mikroprocesor zostaje wstrzymany na cztery cykle zegarowe przed wykonaniem następnej instrukcji. Użytkownik powinien sprawdzać stan bitu EEPE przed rozpoczęciem operacji odczytu. Jeśli trwa operacja zapisu, nie jest możliwy odczyt EEPROM, ani zmiana rejestru EEARL


GPIOR2 – General Purpose I/O Register 2 – Rejestr we/wy ogólnego przeznaczenia nr 2

Bit 7 6 5 4 3 2 1 0  
0x13 MSB             LSB GPIOR2
Zapis/Odczyt Z/O Z/O Z/O Z/O Z/O Z/O Z/O Z/O  
Wartość początkowa 0 0 0 0 0 0 0 0  

GPIOR1 – General Purpose I/O Register 1 – Rejestr we/wy ogólnego przeznaczenia nr 1

Bit 7 6 5 4 3 2 1 0  
0x12 MSB             LSB GPIOR1
Zapis/Odczyt Z/O Z/O Z/O Z/O Z/O Z/O Z/O Z/O  
Wartość początkowa 0 0 0 0 0 0 0 0  

GPIOR0 – General Purpose I/O Register 0 – Rejestr we/wy ogólnego przeznaczenia nr 0

Bit 7 6 5 4 3 2 1 0  
0x11 MSB             LSB GPIOR0
Zapis/Odczyt Z/O Z/O Z/O Z/O Z/O Z/O Z/O Z/O  
Wartość początkowa 0 0 0 0 0 0 0 0  

do podrozdziału  do strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2024 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.