Redakcja: Dondu
Artykuł jest fragmentem cyklu: Kurs mikrokontrolerów XMega by Leon-Instruments
W mikrokontrolerach ATmega i ATtiny układ dystrybucji sygnałów zegarowych był tak prosty, że wręcz aż prymitywny. W szczególności w procesorach starej generacji, takich jak ATmega8, mogliśmy wybrać źródło sygnału zegarowego przy pomocy fusebitów i podczas pracy procesora w żaden sposób nie można było go zmienić.
Tylko część mikrokontrolerów ATtiny i ATmega ma możliwość prostej zmiany częstotliwości taktowania mikrokontrolera, o czym przeczytasz w artykule: Ustawianie i zmiana częstotliwości taktowania mikrokontrolera w trakcie jego działania
Ponadto, błędne ustawienie fusebitów mogło prowadzić do zablokowania procesora. Najwyższy czas, by porzucić poczciwą ósemkę i przejść na mikrokontrolery nowej generacji!
W XMEGA układ zegarowy jest zdecydowanie bardziej rozbudowany. Mamy do dyspozycji różne źródła sygnału zegarowego, takie jak wbudowany generator szybki 32 MHz, energooszczędny 32 kHz oraz normalny 2 MHz, który uruchamia się zawsze po włączeniu zasilania. Możemy te częstotliwości podzielić preskalerem lub pomnożyć wbudowanym układem PLL. Oprócz tego, możemy oczywiście podłączyć różne kwarce, a w razie uszkodzenia kwarcu, procesor samoczynnie przełączy się na wbudowany generator. Mało tego – podczas pracy możemy zmieniać nie tylko częstotliwość zegara, ale również źródło sygnału. Różne peryferia mogą być taktowane różnymi zegarami, a niektóre z nich mogą pracować nawet z częstotliwością 128 MHz!
Do pobrania: XMega-sygnaly-zegarowe.zip (kopia)
Uproszczony schemat układu dystrybucji sygnałów zegarowych przedstawiono na rysunku poniżej. Po wybraniu jednego z pięciu dostępnych źródeł, mamy do dyspozycji aż trzy preskalery, umożliwiające taktowanie poszczególnych peryferiów mikrokontrolera różnymi zegarami. CLKCPU to zegar dla rdzenia procesora i może mieć maksymalnie 32MHz. CLKPER taktuje większość peryferiów. CLKPER2 i CLKPER4 służą do taktowania peryferiów zdolnych do pracy z zegarem szybszym od CLKCPU. Oprócz tego, mamy jeszcze osobne zegary dla RTC i USB, jeśli mikrokontroler jest wyposażony w te peryferia.
Preskalery |
Sposób wyboru źródła sygnału zegarowego sprowadza się do trzech punktów:
- Konfiguracja i uruchomienie generatora
- Oczekiwanie na stabilizację generatora
- Przełączenie źródła
W tej części kursu napiszemy kilka funkcji, umożliwiających przełączenie źródła sygnału taktującego oraz obserwację efektów tej zmiany przy pomocy migającej diody i wyświetlacza LCD ze sterownikiem HD44780. Wykorzystamy wewnętrzny generator RC 2 MHz, 32 MHz, a także zewnętrzny generator kwarcowy i układ PLL.
Schemat |
Po zmontowaniu na płytce stykowej uzyskamy mniej więcej taki układ:
Zdjęcie układu |
Zacznijmy od przeanalizowania funkcji main().
#define F_CPU 62000000UL #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "hd44780.h" int main(void) { // zmienna uint8_t pll = 4; // diody PORTE.DIR = PIN0_bm; // dioda LED // przyciski PORTA.DIRCLR = PIN0_bm; // przycisk - RC 2MHz PORTA.PIN0CTRL = PORT_OPC_PULLUP_gc; // podciągnięcie do zasilania PORTE.DIRCLR = PIN5_bm; // przycisk FLIP - RC 32MHz PORTE.PIN5CTRL = PORT_OPC_PULLUP_gc; // podciągnięcie do zasilania PORTE.DIRCLR = PIN6_bm; // przycisk - XTAL PORTE.PIN6CTRL = PORT_OPC_PULLUP_gc; // podciągnięcie do zasilania PORTF.DIRCLR = PIN4_bm; // przycisk - PLL PORTF.PIN4CTRL = PORT_OPC_PULLUP_gc; // podciągnięcie do zasilania // wyświetlacz LCD LcdInit(); // komunikat o źródłe sygnału zegarowego LcdClear(); Lcd("RC 2MHz"); // włączenie przerwań sei(); while(1) { PORTE.OUTTGL = PIN0_bm; _delay_ms(50); if(!(PORTA.IN & PIN0_bm)) Osc2MHz(); if(!(PORTE.IN & PIN5_bm)) Osc32MHz(); if(!(PORTE.IN & PIN6_bm)) OscXtal(); if(!(PORTF.IN & PIN4_bm)) { pll++; // zwiększ zmienną pll if(pll > 31) pll = 1; // jeśli pll większe od 31 to ustaw na 1 OscPLL(pll); // funkcja konfigurująca PLL } } }
Zwróćmy uwagę na funkcję opóźniającą _delay_ms(50); Co w niej jest nie tak? Funkcja powoduje, że procesor kręci się w pustej pętli nic nie robiąc, aż upłynie żądany czas. Jednak funkcja _delay_ms() oblicza ilość potrzebnych cykli na podstawie definicji #define F_CPU 62000000UL.
W przypadku kiedy częstotliwość taktowania się zmienia, to pamiętajmy, że standardowe funkcje opóźniające nie uwzględniają aktualnej częstotliwości, w związku z czym odmierzony czas nie będzie prawidłowy. Zaobserwujemy ten problem w naszym programie testowym – dioda podłączona do E0 będzie mrugać z różną częstotliwością, mimo że w pętli głównej jest _delay_ms(50) ze stałym argumentem równym 50.
Ściągnij poniższe pliki źródłowe – będziemy używać biblioteki do obsługi wyświetlacza autorstwa Radosława Kwietnia, którą opisałem w 5 części kursu (wyświetlacz LCD w XMEGA). W kolejnych odcinkach przedstawię, jak działają poszczególne generatory i jak skonfigurować ich rejestry kontrolne.
Dominik Leon Bieczyński
leon-instruments.pl
Jak zwykle bardzo dziękuję za cenne informacje. Dodatkowo nasuwa mi się jedno pytanie: A co z drganiami styków? Nie trzeba się przed nimi zabezpieczać?
OdpowiedzUsuńMam jeszcze jedną prośbę: Czy byłaby możliwość dodawania daty do publikowanych artykułów?