Systemy wbudowane Mikrokontroler 8051 Budowa dr inż. Maciej Piechowiak Wprowadzenie rdzeń CPU z jednostką artymetyczno-logiczną (ALU) do obliczeń na liczbach 8-bitowych, uniwersalne dwukierunkowe porty wejścia/wyjścia (zapis do portu, odczyt z portu) danych cyfrowych; czasami wejścia/wyjścia przetwornika A/C i C/A, programowany dwukierunkowy port transmisji szeregowej UART (wymagany konwerter do standardu RS-232C), dwa (w niektórych modelach trzy) liczniki/timery do dowolnego wykorzystania, układ generowania przerwań systemowych z możliwością generowania przerwań zewnętrznych, wewnętrzny oscylator (wymagany zewn. rezonator kwarcowy). Wprowadzenie pamięć wewnętrzna RAM do przechowywania danych i wyników obliczeń, pamięć wewnętrzna ROM do przechowywania programu, możliwość dołączenia zewnętrznej pamięci RAM i ROM/EPROM/EEPROM, 1
Porty port P1 Porty 10mA / pin, indywidualne ustawianie poziomu logicznego na każdym wyprowadzeniu (rozkazy SETB, CLR), port jako wejście stan wysokiej impedancji, Reset po włączeniu zasilania, na żądanie użytkownika, w sytuacjach awaryjnych poprzez zewnętrzny układ (np. watchdog), 2
Port transmisji szeregowej piny 3.0 (RxD) i 3.1 (TxD) pełnią rolę portu transmisji szeregowej, transmisja synchroniczna P3.0 pełni rolę dwukierunkowej transmisji szeregowej, P3.1 generuje sygnał taktujący, transmisja asynchroniczna (kilka trybów) P3.0 jest odbiornikiem przesyłanych danych, P3.1 nadajnikiem; współpraca z innymi urządzeniami (np. komputer PC, urządzenia wykorzystujące standard transmisji RS-232C), Porty specjalne porty przerwań zewnętrznych P3.2 (INT0) i P3.3 (INT1) ustawienie flagi (znacznik zgłoszenia przerwania) w mikrokontrolerze przy przejściu ze stanu wysokiego na niski, wejścia uniwersalnych programowalnych liczników P3.4 (T0) i P3.5 (T1); liczniki mogą zliczać impulsy zewnętrzne (0...65535) lub wewnętrzne z wewnętrznego generatora, zapis i odczyt z zewnętrznej pamięci danych port P3.6 (WR) i P3.7 (RD). Asembler 3
Asembler LJMP add a,r1 inc a mov r1,a loop: ljmp loop :060000002904F9020003CF :00000001FF Adresowanie wewn. pamięci adresowanie bezpośrednie (dla całego obszaru pamięci wewnętrznej): mov A, 32h (A) (32h) adresowanie natychmiastowe: mov A, #32h (A) 32h adresowanie rejestrowe (dotyczy akumulatora, rejestrów R0-R7 i rejestru DPTR): mov A, R0 (A) (R0) adresowanie rejestrowe pośrednie: mov A, @R0 (A) ((R0)) adresowanie bezpośrednie bitów (C flaga przeniesienia): mov C, ACC.7 clr P1.7 Timery timery dwa 16-bitowe liczniki (T0 i T1), zliczają impulsy z zewnętrznych wejść licznikowych (pin 14 i 15) lub wewnętrzne impulsy z układu taktującego procesor (sygnał f xtal /12), 4
Timery Timery maksymalna liczba zliczonych impulsów 65536, po przepełnieniu generowane jest przerwanie, liczniki są autonomiczne, jednak można je uruchomić i zatrzymać programowo, do licznika można wpisać dowolną wartość początkową, licznik można sterować wejściem INT0 (INT1), liczniki zbudowane są z rejestrów 8-bitowych TL0 i TH0 (T0) oraz TL1 i TH1 (T1), Timery 5
Timery M0=0; M1=0 tryb 0 Tryb pracy 0 jest identyczny dla obu liczników. Liczniki pracują w konfiguracji 13 bitowej. Starszy bajt THn zawiera 8 bardziej znaczących bitów, natomiast 5 pozostałych bitów to najstarsze z TLn (trzy młodsze TLx są ignorowane). Maksymalna wartość (przy kwarcu 12MHz) wynosi około 8,191 ms, po osiągnięciu tego czasu licznik wyzeruje się i zgłosi przerwanie informujące o tym fakcie. M0=0; M1=1 tryb 1 Podobny do trybu 0 (identyczny dla obu liczników), z tym że do zliczania wykorzystywane są wszystkie 16 bitów licznika. Maksymalny czas to ok. 65 ms. M0=1; M1=0 tryb 2 Identyczny dla obu liczników. Pracuje tylko młodsza połówka licznika (8 bitów). Młodsza połówka zlicza aż do wartości maksymalnej 255, po czym automatycznie zostaje przepisana do niego zawartość starszej połówki. Timery M0=1; M1=1 tryb 3 Tryb ten dotyczy obu liczników T0 i T1 na raz. W tym trybie licznik T1 jest zatrzymany i nie pracuje. Dwa bajty licznika TH0 i TL0 pracują jako dwa niezależne 8 bitowe liczniki, przy czym istnieje pewne ograniczenie co do ich funkcji, a mianowicie: TL0 może liczyć impulsy z wejścia T0 lub pracować jako czasomierz zliczając impulsy wewnętrzne (X tal /12); TH0 może pracować tylko jako czasomierz, czyli zliczać impulsy wewnętrzne. Tryb ten został zaimplementowany po to, aby w wypadkach kiedy licznik T1 używany jest do określenia szybkości transmisji port szeregowego, a programiście niezbędne są dwa dodatkowe liczniki, których role spełniają TH0 i TL0. Timery Timer może generować przerwanie w przypadku przepełnienia licznika: 6
Timery ; Program generatora przebiegu prostokątnego 10Hz (okres = 100msek.) ; Sygnalizacja stanu na linii P2.0 ; Ilość impulsów do zliczenia: N = Tp/Tcykl, (timer pracuje w trybie 1) ; gdzie: Tp - czas ; Tcykl - okres impulsów wzorcowych = 1/(fclk/12) ; Dla 50 msek.: 50msek/(12/11,0592MHz) = 46080 ; Do licznika należy załadować 65536-46080 = 19456 = 4C00h ORG 0 CZAS_HIGH EQU 4CH ; starszy bajt ilości impulsów CZAS_LOW EQU 0 ; młodszy bajt ilości impulsów MOV P2,#0 ; zeruj wszystkie linie portu P2 ; Programowanie trybu pracy timera 0 MOV TMOD,#00000001B ; timer 0 -> tryb 1, timer 1 -> nieużywany, tryb 0 ; Programowanie ilości impulsów MOV TH0,#CZAS_HIGH MOV TL0,#CZAS_LOW SETB TR0 ; uruchomienie licznika PETLA: JNB TF0,$ ; czekaj na zmianę flagi na '1' CLR TF0 ; zeruj flagę przepełnia CPL P2.0 ; neguj bit linii P2.0 ; Ponowne programowanie ilości impulsów MOV TH0,#CZAS_HIGH MOV TL0,#CZAS_LOW SJMP PETLA END Organizacja pamięci programu Organizacja pamięci danych 7
Przerwania Przerwania oddziałują na pracę jednostki centralnej mikrokontrolera poprzez sterownik przerwań wbudowany w mikrokontroler. Na skutek wystąpienia przerwania sterownik przerwań kieruje program do obszaru pamięci programu, w którym znajduje się procedura reakcji na to zdarzenie. Przejście odbywa się poprzez wykonanie instrukcji: CALL wektor_przerwania Efektem wykonania instrukcji jest zapamiętanie adresu następnej instrukcji programu. Po wykonaniu procedury obsługi przerwania program powraca do realizacji programu głównego. Przerwania Zdarzenia, które zgłaszają żądanie obsługi przerwania mogą następować w dowolnej chwili czasowej i w dowolnej kolejności. Wektorem przerwania jest adres w pamięci programu, pod który nastąpi skok po wykryciu przerwania. Pod tym adresem należy umieścić pierwszą instrukcję podprogramu obsługi przerwania. Wektory przerwań są ustawione na sztywno przez producenta danego mikrokontrolera. Podprogram obsługi przerwania musi być zakończony poleceniem RETI, który powoduje powrót do adresu zapamiętanego w momencie wywołania instrukcji CALL. System przerwań 8051 Układ przerwań mikrokontrolera może przyjmować zgłoszenia następujących przerwań: zewnętrzne: z wejść /INT0 i /INT1 (opadające zbocze sygnału lub poziom niski), z portu szeregowego (zakończenie nadawania lub odbioru znaku przez UART), z timera przepełnienie licznika T0 i T1 (z 0xFFFF na 0x0000). Przerwania w mikrokontrolerze można uaktywniać lub blokować z wykorzystaniem rejestru IE, poprzez konfigurację bitów rejestru, np: SETB EX1 SETB EA CLR ET0 MOV IE, #10010010b ;odblokowanie przerwania z /INT1 ;globalne odblokowanie przerwań ;zablokowanie przerwania od T0 ;ustawienie całego rejestru 8
System przerwań 8051 Dwa przerwania nadchodzące w tym samym czasie nie zostaną obsłużone jednocześnie (priorytet) w pierwszej kolejności zostanie obsłużone przerwanie o wyższym priorytecie. Przerwanie o niższym priorytecie oczekuje na zakończenie obsługi przerwania o wyższym priorytecie. Po resecie mikrokontrolera rejestr IE jest wyzerowany wszystkie przerwania i maski są zablokowane. Każde przerwanie posiada swój priorytet (od najwyższego do najniższego): ET2, ES, ET1, EX1, ET0, EX0. Nadchodzi przerwanie z /INT1. W trakcie obsługi tego przerwania nadchodzi sygnał z /INT0. Procedura obsługi przerwania z /INT1 zostaje przerwana, program przechodzi do obsługi przerwania z /INT0. Po zakończeniu wraca do punktu wyjścia z procedury obsługi /INT1. System przerwań 8051 Rejestr IE (ang. Interrupt Enable): System przerwań 8051 Rejestr IP (ang. Interrupt Priority): 9
System przerwań 8051 Ustawienie jednego z bitów rejestru IP powoduje ustawienie danego przerwania na wyższy poziom, wyzerowanie ustawia niższy priorytet. W przypadku wpisania jedynek dla kilku wartości w rejestrze IP jednocześnie o kolejności wykonywania podprogramów obsługi przerwań decyduje ustalona wcześniej kolejność. Podprogram obsługi przerwania o najwyższym priorytecie nie jest przerywany. Po resecie procesora wszystkie pola rejestru IP są zerowane. System przerwań 8051 W przypadku zgłoszenia przerwania mikrokontroler: 1. Sprawdza czy aktualnie nie jest wykonywana procedura obsługi przerwania o wyższym priorytecie lub nie nadeszło zgłoszenie przerwania o wyższym priorytecie z innego źródła. 2. Zeruje znacznik zgłoszenia przyjętego przerwania (nie zeruje Ti i RI w rejestrze SCON obsługującym transmisję szeregową). 3. Zapisuje na stosie wartość 16-bitowego licznika rozkazów (PC). 4. Automatycznie wpisuje do licznika rozkazów adres początku procedury obsługi danego przerwania: 0003h 000Bh 0013h 001Bh 0023h przerwanie z wejścia /INT0 przerwanie od licznika T0 przerwanie z wejścia /INT1 przerwanie od licznika T1 przerwanie z portu szeregowego System przerwań 8051 10
System przerwań 8051 przerwania mogą być zgłaszane opadającym zboczem sygnału na tym wejściu lub poziomem niskim, w pierwszym przypadku procedura zostanie wywołana tylko jeden raz (nawet gdy podprogram obsługi przerwania zakończył się a stan na wejściu /INT0 lub /INT1 jest nadal niski), w drugim przypadku poziom na wejściu powinien się zmienić na wysoki przed zakończeniem procedury obsługi przerwania, w przeciwnym wypadku procedura wykonana zostanie ponownie, procesor w określonych okresach każdego cyklu maszynowego próbkuje stan wejść /INT0 i /INT1 i jeśli w dwóch kolejnych cyklach nastąpi zmiana stanu z 1 na 0 potraktuje to jako zgłoszenie przerwania, nie należy wykorzystywać zbyt dużej liczby rejestrów (przepełnienie stosu) oraz tworzyć długiego kodu procedury obsługi przerwania. System przerwań 8051 System przerwań 8051 WEKTOR_T0 EQU 0BH HIGHLOW EQU 19456 ; 65536 - (50msek/1,08507usek), kwarc: 11,0592MHz ORG 0 LJMP START ORG WEKTOR_T0 MOV TL0,#LOW MOV TH0,#HIGH CPL P1.0 RETI ;odtworzenie zadanego czasu ;neguj stan diody LED ;powrót z przerwania ;******************************** START: MOV P1,#0 ; zerowanie linii P1.7 P1.0 ;inicjacja timera 0 MOV TMOD,#00000001B ;ustawienie trybu 1 MOV TL0,#LOW MOV TH0,#HIGH SETB TR0 ;start timera T0 ;inicjacja przerwania SETB ET0 ;zezwolenie na przerwanie od timera 0 SETB EA ;globalne zezwolenie na przerwanie SJMP $ 11
Odczyt z pamięci programu sygnał PSEN uaktywnienie układu pamięci EPROM: Odczyt z pamięci programu Typowa aplikacja 12
Urządzenia wejścia/wyjścia urządzenia wejścia/wyjścia podłącza się do portów mikrokontrolera, przy kodzie programu zajmującym więcej niż 4kB wymagana jest zewnętrzna pamięć programu (EPROM, EEPROM, FLASH), mikrokontroler 8051 pozwala zaadresować 64kB pamięci programu wymaga zewnętrznej magistrali danych oraz magistrali adresowej, ograniczona liczba portów przy korzystaniu z zewnętrznej pamięci programu i danych (P0 młodsza część adresu / dane, P2 starsza część adresu, P3 sygnały sterujące, P1 wolne), umieszczenie zewnętrznych urządzeń w przestrzeni adresowej pamięci danych wymagany układ kombinacyjny dekoder adresów, Urządzenia wejścia/wyjścia Dekoder adresów jako sygnałów wejściowych dekodera należy użyć wybranych linii adresowych oraz sygnałów sterujących, np. /RD i /WR, zabezpiecza to przed odwrotnym użyciem rozkazu movx podłączenie do magistrali danych urządzenia wysyłającego dane, gdy mikrokontroler również wysyła dane, w zależności od wymaganej wielkości pamięci RAM oraz liczby urządzeń wejścia/wyjścia przestrzeń danych dzieli się na równe bloki wykorzystując najstarsze linie adresowe, wykorzystanie dekodera NKB -> kod 1 z n. 13
Typowa aplikacja Dekoder adresów układ GAL Dekoder adresów: boole (in psen,a15,a14,a13,a12,a11,a10,a9,wr,rd; out lcden,len,ken,ster,oerom,oeram,csram2; io csram1) { oerom =!(!psen &!a15 &!a14 &!a13 &!a12); oerom.oe = 1; csram1 =!(a15 &!a14 a15 &!a13 a15 &!a12 a15 &!a11); csram1.oe = 1; csram2 = a15; csram2.oe = 1; oeram =!(!psen & a15!psen & a14!psen & a13!psen & a12!rd &!csram1!rd &!a15); oeram.oe = 1; ster =!(a15 & a14 & a13 & a12 & a11 & a10 &!a9); ster.oe = 1; len =!(a15 & a14 & a13 & a12 & a11 &!a10 &!a9 &!wr); len.oe = 1; ken =!(a15 & a14 & a13 & a12 & a11 &!a10 &!a9 &!rd); ken.oe =1; lcden = a15 & a14 & a13 & a12 & a11 &!a10 & a9 &!(rd & wr); lcden.oe = 1; putpart("gal16v8","galnew", psen, a15, a14, a13, a12, a11, a10, a9, wr, GND, rd, lcden, len, ken, ster, oerom, oeram, csram1, csram2, VCC); } mov dptr, #0f802h movx a, @dptr Typowa aplikacja 14