kramann.info
© Guido Kramann

Login: Passwort:










4.1 LEDs der Licht-Klangkugel ansprechen

4.1 Address the LEDs of the light-sound ball (EN google-translate)

4.1 Zaadresuj diody LED kuli świetlno-dźwiękowej (PL google-translate)

Um eine LED blinken zu lassen, reicht das folgende Programm aus:

To flash an LED, the following program is sufficient:

Aby błyskać diodą LED, wystarczy następujący program:

Hinweis: Die Anode bei PA1 muß auf High-Potential gesetzt werden, die Kathode bei PA0 auf Low-Potential. Das bedeutet, dass PA0 und PA1 mit DDRA als digitale Ausgänge konfiguriert werden müssen. Aber dann wird in Register PORTA das Bit0 (PA0) auf 0 gesetzt und Bit1 (PA1) auf 1.

Note: The anode at PA1 must be set to high potential, the cathode at PA0 must be set to low potential. This means that PA0 and PA1 must be configured with DDRA as digital outputs. But then in register PORTA Bit0 (PA0) is set to 0 and Bit1 (PA1) is set to 1.

Uwaga: Anodę w PA1 należy ustawić na wysoki potencjał, katodę w PA0 należy ustawić na niski potencjał. Oznacza to, że PA0 i PA1 muszą być skonfigurowane z DDRA jako wyjściami cyfrowymi. Ale wtedy w rejestrze PORTA Bit0 (PA0) jest ustawiony na 0, a Bit1 (PA1) na 1.

//Blinken grüne LED

#include <avr/io.h>               
int main(void)                    
{      
   long pause;                    

   DDRA = 0;
   DDRB = 0;
   DDRC = 0;
   DDRD = 0;
                           
   DDRA |= 0b00000011;  //PA0 und PA1 als Ausgang konfigurieren          

   PORTA &= 0b11111100; //PA0 und PA1 auf Masse ziehen.      

   while(1)                       
   {                              
       PORTA |= 0b00000010; //PA1 auf 1 setzen       
       for(pause=0;pause<50000;pause++)
       {   
           DDRD = 0;    
       }
       PORTA &= 0b11111101; //PA1 auf 0 setzen       
       for(pause=0;pause<50000;pause++)   
       {
           DDRD = 0;    
       }
   }                              
}

Code 4.1-1: Quelltext: 001_gruen1_blink.c

Um das Hauptprogramm übersichtlicher gestalten, werden in der folgenden Programmvariante C-Funktionen eingesetzt, um die Blinkfunktion zu realisieren.

In order to make the main program clearer, be in the following Program variant C-functions used to change the flashing function realize.

Aby program główny był bardziej przejrzysty, są poniżej Wariant programu Funkcje C służące do zmiany funkcji migania zrealizować.

//Blinken grüne LED

#include <avr/io.h>  

void einLEDgruen1()
{
    PORTA |= 0b00000010; //PA1 auf 1 setzen       
}

void ausLEDgruen1()
{
    PORTA &= 0b11111101; //PA1 auf 0 setzen       
}

void pause(long dauer)
{
    while(dauer>0)
    {
        DDRC=0;
        dauer--;
    }
}
             
int main(void)                    
{      
   DDRA = 0;
   DDRB = 0;
   DDRC = 0;
   DDRD = 0;
                           
   DDRA |= 0b00000011;  //PA0 und PA1 als Ausgang konfigurieren          

   PORTA &= 0b11111100; //PA0 und PA1 auf Masse ziehen.      

   while(1)                       
   {                              
       einLEDgruen1();
       pause(50000);
       ausLEDgruen1();
       pause(50000);
   }                              
}

Code 4.1-2: Quelltext: 002_gruen1_blink_funktion.c

Nachteile der beiden vorangegangenen Lösungen sind:

Disadvantages of the two previous solutions are:

Wady dwóch poprzednich rozwiązań to:

  1. Beim Einfügen weiterer Programmzeilen ändert sich die eingestellte Pausendauer.
  2. Die zeitliche Pausendauer läßt sich schwer vorherbestimmen.
  3. In der Pausenschleife kann der Mikrocontroller keine weiteren Aufgaben erledigen.

Bei Beschäftigung mit diesem Thema bewet man sich im Bereich "Echtzeitsysteme". Hier geht es u.a. darum, intelligentes Task-Management zu verwirklichen, bei dem die oben genannten Probleme vermieden, oder zumindest veringert werden.

In dealing with this topic one is in the realm of real-time systems. Here it is u.a. to realize intelligent task management, in whi the above problems are avoided, or at least reduced.

W zajmowaniu się tym tematem znajdujemy się w systemach czasu rzeczywistego. Tutaj jest u.a. do realizacji inteligentnego zarządzania zadaniami, w któr powyższe problemy są unikane lub przynajmniej zmniejszane.

Realisierung einer Zeitbasis mit Hilfe eines Timers

Realization of a time base with the help of a timer

Realizacja bazy czasowej za pomocą timera

Das nachfolgende Programm arbeitet grundlegend anders, um die Pause zwischen den geänderten Blinkzuständen zu realisieren, als die vorangehenden beiden:

The following program works fundamentally different to the break between the to realize changed flashing states than the preceding two:

Poniższy program działa zasadniczo inaczej niż przerwa między aby uzyskać zmienione stany migania niż poprzednie dwa:

Im nachfolgenden Programm wird einer der drei verfügbaren Timer, nämlich Timer1, so konfiguriert, dass er kontinuierlich bis zu einer vorgeebenen Grenze aufwärts zählt. In dem eingestellten Zählermodus "CTC - Clear Timer on Compare Match" kann diese Obergrenze in einem der verfügbaren Register gespeichert werden. Duech diesen "Trick" gelingt es leicht, eine Periode des Zählvorgangs (einmal bis zur Obergrenze zählen), sehr flexibel festzulegen. Der Timer wird dadurch zu einer Zeitbasis, eine Art interne Uhr, die im Programm eingesetzt werden kann, um beispielsweise Pausen eine exakte Länge zu geben.

The following program will configure one of the three available timers, Timer1, that he continuously counts up to a pre-defined limit. In the set counter mode CTC Upper limit in one of the available registers. Duech this trick succeeds easily, a period of the counting process (once until Upper limit), very flexible. The timer thus becomes a time base, a kind of internal clock that can be used in the program, for example, breaks a give exact length.

Poniższy program skonfiguruje jeden z trzech dostępnych timerów, Timer1, że ciągle liczy się do wcześniej określonego limitu. W ustawionym trybie licznika CTC Górny limit w jednym z dostępnych rejestrów. Duech ten trik z powodzeniem udaje się, jeden okres procesu liczenia (raz do Górny limit), bardzo elastyczny. Timer staje się zatem podstawą czasu, rodzajem wewnętrznego zegara, który może być użyte w programie, na przykład, łamie a podać dokładną długość.

Die möglichen Zählermodi können im Datenblatt des ATmega32 auf Seite 107 nachgelesen werden. Der hier verwendete Modus ist Modus 4.

The possible counter modes can be found in the data sheet of the ATmega32 on page 107. The mode used here is Mode 4.

Możliwe tryby liczników można znaleźć w arkuszu danych ATmega32 na stronie 107. Zastosowany tutaj tryb to Tryb 4.

Neben der Einstellung des Arbeitsmodus (hier 4), der hier in Register OCR1A speicherbaren Obergrenze des Zählvorgangs muß außerdem noch die Vorteilung bezüglich dem Systemtack (z.B. Quarzfrequenz des externen Quarzes, oder interne System-Clock-Frequenz) festgelegt werden. Diese Möglichkeiten sind über die Bits CS12, CS11 und CS10 des Konfigurationsregisters TCCR1B einstellbar und in einer Tabelle auf Seite 108/109 im Datenblatt beschrieben. In untigem Beispiel ist 101, also die maximal mögliche Vorteilung von 1024 eingestellt.

In addition to setting the working mode (here 4), The upper limit of the counting process which can be stored here in register OCR1A must also be still the Vorteilung with respect to the system bag (for example, quartz frequency of external crystal, or internal system clock frequency). These possibilities are available via the CS12, CS11 and CS10 bits of the configuration register TCCR1B adjustable and described in a table on page 108/109 in the data sheet. In the example below is 101, so the maximum possible Vorteilung of 1024 set.

Oprócz ustawienia trybu roboczego (tutaj 4), Górny limit procesu zliczania, który można zapisać tutaj w rejestrze OCR1A, musi również być nadal Vorteilung w odniesieniu do worka systemowego (na przykład częstotliwość kwarcu zewnętrzny kryształ lub wewnętrzna częstotliwość zegara systemowego). Te możliwości są dostępne za pośrednictwem bitów CS12, CS11 i CS10 rejestru konfiguracji TCCR1B regulowany i opisany w tabeli na stronie 108/109 w arkuszu danych. W poniższym przykładzie jest 101, więc maksymalny możliwy Vorteilung zestawu 1024.

Somit finden beispielsweise die Zählschritte des Timers bei Taktung mit dem internen RC-Oszilator mit fclock=1MHz mit einer Frequenz von fzähl=fclock/1024 = 976,5625Hz statt. Somit dauert ein Zählschritt dt=0,001024s, also ungefähr eine Millisekunde.

Thus, for example, find the counting steps of the timer when clocking with the internal RC oscillator with fsubclock / sub = 1MHz with a frequency of fsubzähl / sub = fsubclock / sub / 1024 = 976,5625Hz instead. Thus, a counting step dt = 0.001024s, about one millisecond.

Na przykład, znajdź kroki liczenia timera podczas synchronizacji z wewnętrznym Oscylator RC z fsubclock / sub = 1MHz z częstotliwością fsubzähl / sub = fsubclock / sub / 1024 = 976,5625Hz zamiast. Zatem, etap zliczania dt = 0,001024 s, około jednej milisekundy.

Der gesamte Zählvorgang von 0 bis zur Obergrenze, die hier mit OCR1A==97 festgelegt ist, dauert dann 97*dt=0,099328s, also ungefähr eine zehntel Sekunde.

The total count from 0 to the upper limit set here with OCR1A == 97 then takes 97 * dt = 0.099328s, about a tenth of a second.

Łączna liczba od 0 do górnego limitu ustawionego tutaj z OCR1A == 97 następnie przyjmuje 97 * dt = 0,099328 s, około jednej dziesiątej sekundy.

Somit wurde hier eine Zeitbasis von 0,099328s realisiert, wenn man einen Systemtakt von 1MHz voraussetzt.

Thus, a time base of 0.099328s was realized here, assuming a system clock of 1MHz.

Tak więc zrealizowano tutaj podstawę czasową 0,099328 s, przyjmując zegar systemowy 1 MHz.

Die bis hierher betrachteten Programmzeilen sind:

The program lines considered so far are:

Dotychczasowe linie programowe to:

TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (0<<WGM11) | (0<<WGM10);
TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);
OCR1A = 97; //97=> ungefähr im 0,1 Sekunden-Takt wird Interrupt ausgelöst.

Code 4.1-3: Konfiguration von Timer1.

Hinweis: Die Register OCR1A und OCR1B werden im PWM-Modus des Timer1 dazu verwendet, die PWM-Pulsbreite festzulegen. Hier arbeitet der Timer aber nicht im PWM-Modus und so werden die beiden Register nicht zu diesem Zweck gebraucht. So kann hier OCR1A zu einem anderen Zweck benutzt werden, nämlich die obere Zählgrenze festzulegen.

Note: Registers OCR1A and OCR1B are used in PWM mode of Timer1 to set the PWM pulse width set. Here, the timer does not work in PWM mode and so the two registe not needed for this purpose. So here OCR1A can be used for another purpose, namely t to set the upper count limit.

Uwaga: Rejestry OCR1A i OCR1B są używane w trybie PWM Timera1 do ustawienia szerokości impulsu PWM ustawione. Tutaj timer nie działa w trybie PWM, a więc w dwóch rejestra nie są potrzebne do tego celu. Więc tutaj OCR1A może być używany do innego celu, a mianowic aby ustawić górny limit liczenia.

Hinweis: Tabellen und Angaben zu den Arbeitsmodi, wie sie hier für den Timer1 aus dem Datenblatt entnommen wurden, existieren dort natürlich für die beiden anderen Timer auch und auch für die ganze restliche interne Peripherie.

Note: Tables and information on the working modes, as they are taken here for Timer1 from the data sheet Of course there are also timers for the two other timers as well as for the whole one remaining internal periphery.

Uwaga: Tabele i informacje na temat trybów pracy, tak jak są tutaj brane za Timer 1 z arkusza danych Oczywiście są też timery dla dwóch innych timerów, a także dla całego pozostałe wewnętrzne obwody.

Dabei lassen sich die in TCC1A und TCC1B zu setzenden Konfigurationsbits COM1A0, COM1B1, WGM13, WGM12 der Tabelle auf Seite 107 im Datenblatt entnehmen.

The configuration bits COM1A0, COM1B1, WGM13, WGM12 can be set in TCC1A and TCC1B see the table on page 107 in the data sheet.

Bity konfiguracji COM1A0, COM1B1, WGM13, WGM12 można ustawić w TCC1A i TCC1B patrz tabela na stronie 107 w arkuszu danych.

Verwendung eines Interupts zur zeitlichen einer internen Uhr

Using an interrupt to time an internal clock

Używanie przerwania do czasu wewnętrznego zegara

Man könnte nun den Zählstand des Timers1 direkt in seinem eigenen Programm benutzen. Das Zählregister des Timers1 TCNT1 und auch das aller anderen (TCNT0 und TCNT2) kann wie eine globale Variable überall im Programm verwendet werden. Es ist sogar möglich im eigenen Programm den Zählerstand zu verändern, z.B. ihn auf Null setzen. Da der Timer1 ein 16-Bit-Zähler ist, ist TCNT1 zwei Byte groß. Dagegen sind die Zählregister der anderen beiden 8-Bit-Timer nur ein Byte groß.

You could now use the count of Timer1 directly in your own program. The counter register of the timer1 TCNT1 and that of all others (TCNT0 and TCNT2) can be used as a global variable anywhere be used in the program. It is even possible to change the meter reading in your own progra e.g. set it to zero the count registers of the other two 8-bit timers are only one byte in size.

Możesz teraz użyć licznika Timer1 bezpośrednio w swoim programie. Rejestr liczników zegara1 TCNT1 i wszystkich innych (TCNT0 i TCNT2) może być używany jako zmienna globalna w dowolnym miejscu być użyte w programie. Można nawet zmienić odczyt licznika w swoim programi na przykład ustaw go na zero rejestry zliczania pozostałych dwóch 8-bitowych timerów mają tylko jeden bajt wielkości.

Die Änderungsgeschwindigkeit des Zählregisters ist aber gegenüber dem Blinkvorgang einer LED viel zu hoch: Einmal hochzählen dauert wie oben beschrieben lediglich eine zehntel Sekunde.

However, the rate of change of the counter register is opposite to the blinking of an LED way too high: counting up once only takes a tenth of a second, as described above.

Jednak szybkość zmiany rejestru licznika jest przeciwna do migania diody LED zdecydowanie za wysoko: odliczanie zajmuje tylko jedną dziesiątą sekundy, jak opisano powyżej.

Statt dessen wird in dem nachfolgenden Programm ein interner Interrupt eingesetzt, um eine zyklisch zählende "interne Uhr" zu erhalten. Die Funktion SIGNAL(..) ist eine Interruptfunktion. Als Bedingung, wann diese aufgerufen wird, findet sich der Übergabewert SIG_OUTPUT_COMPARE1A.

Instead, an internal interrupt is used in the subsequent program to create a cyclically counting internal The function SIGNAL (..) is an interrupt function. As a condition, when this is calle there is the transfer value SIG_OUTPUT_COMPARE1A.

Zamiast tego wewnętrzne przerwanie jest używane w kolejnym programie do utworzenia cyklicznie licząc wewnętrzny Funkcja SIGNAL (..) jest funkcją przerwania. Jako warunek, gdy jest to wywoływan jest wartość transferu SIG_OUTPUT_COMPARE1A.

Hinweis: Tatsächlich ist SIGNAL(..) ein Makro, wird also beim Kompilieren durch etwas anderes ersetzt. Deshalb findet sich hier scheinbar keine korrekte C-Syntax (fehlender Datentyp beim Übergabeparameter).

Note: In fact, SIGNAL (..) is a macro, so it is replaced by something else when compiled. Therefore, there is apparently no correct C syntax (missing data type for the transfer parameter).

Uwaga: W rzeczywistości SYGNAŁ (..) jest makro, więc jest zamieniany na coś innego podczas kompilacji. Dlatego najwyraźniej nie ma poprawnej składni C (brakujący typ danych dla parametru transferu).

Mit SIG_OUTPUT_COMPARE1A wird der Interrupt so konfiguriert, dass er immer dann aufgerufen wird, wenn das Zählregister TCNT1 von Timer1 den in OCR1A gespeicherten Vergleichswert erreicht, sprich, wenn ein Flag gesetzt wird und das dieses anzeigt und der Timer daraufhin wieder automatisch auf Null zurückgesetzt wird.

With SIG_OUTPUT_COMPARE1A, the interrupt is configured to be called whenever if the counting register TCNT1 of Timer1 reaches the comparison value stored in OCR1A, say if a flag is set and this indicates and the timer is then automatically reset to zero.

Przy SIG_OUTPUT_COMPARE1A przerwanie jest skonfigurowane tak, aby było wywoływane za każdym razem gdy rejestr liczący TCNT1 Timera1 osiągnie wartość porównania przechowywaną w OCR1A, to znaczy, gdy flaga jest ustawiona i to oznacza, a zegar jest automatycznie resetowany do zera.

Es sind ganz unterschiedliche Ursachen anwählbar für die Ausführung der Interrupt-Funktion SIGNAL. SIG_OUTPUT_COMPARE1A ist nur eine davon. Eine Liste der Optionen findet sich im Datenblatt auf Seite 42. Die genauen Bezeichnungen der Interrupt-Optionen für C finden sich jedoch in der Dokumentation avr_libc144.pdf von Atmel.

There are very different reasons selectable for the execution of the Interrupt function SIGNAL. SIG_OUTPUT_COMPARE1A is just one of the A list of options can be found in the datasheet on page 42. However, the exact names of the interrupt options for C can be found in the Documentation avr_libc144.pdf from Atmel.

Istnieją bardzo różne powody wyboru do wykonania Funkcja przerwania SIGNAL. SIG_OUTPUT_COMPARE1A to tylko jeden z nic Listę opcji można znaleźć w arkuszu danych na stronie 42. Jednak dokładne nazwy opcji przerwań dla C można znaleźć w Dokumentacja avr_libc144.pdf firmy Atmel.

SIGNAL(SIG_OUTPUT_COMPARE1A)
{
    ZEIT++;
    ZEIT%=10000;    
}

Code 4.1-4: Interruptfunktion aus 003_gruen1_blink_timer2pause.c

Oben ist die Interrupt-Funktion aus 003_gruen1_blink_timer2pause.c gezeigt. Mit jedem Erreichen des Zählerregisters TCNT1 von 97 (Register-Belegung von OCR1A) wird die globale Variable ZEIT inkrementiert. Durch die nachfolgende Modulo-Division mit 10000 wird erreicht, dass ZEIT zyklisch in Schritten von ca. 0,1s bis 9999 zählt und dann wieder bei 0 beginnt. Somit kann ein Gesamtzyklus von 1000 Sekunden zur Programmsteuerung benutzt werden.

Above the interrupt function is shown from 003_gruen1_blink_timer2pause.c. Each time the counter register TCNT1 of 97 (register occupancy of OCR1A) is reached the global variable TIME is incremented. By the subsequent modulo division wi 10000 it is achieved that TIME counts cyclically in steps of approx. 0.1s to 9999 and then again starts at 0. Thus, a total cycle of 1000 seconds can be used for program contro

Powyżej funkcji przerwania jest wyświetlany od 003_gruen1_blink_timer2pause.c. Za każdym razem, gdy zostanie osiągnięty rejestr licznika TCNT1 z 97 (rejestracja obecności OCR1A) zmienna globalna TIME jest inkrementowana. Przez kolejny podział modulo 10000 uzyskuje się to, że TIME zlicza się cyklicznie w krokach od około 0,1 s do 9999, a następnie ponownie zaczyna się od 0. Zatem całkowity cykl 1000 sekund może być użyty do sterowania programe

Die Aktivierung der Interrupts erfolgt mit der Bibliotheksfunktion sei(), die Deaktivierung kann mit cli() erfolgen. Um den Mikrocontroller so zu konfigurieren, dass bei "Compare-Match" zwischen TCNT1 und OCR1A auch ein Interrupt ausgelöst wird, wird ein entsprechendes Konfigurationsbit (Flag) gesetzt: Bit OCIE1A im Register TIMSK. Das Register TIMSK wird im Datenblatt im Kapitel zu Timer0 beschrieben (Seite 80).

The interrupts are activated with the library function sei (), the deactivation can be done with cli (). To configure the microcontroller so that between Compare TCNT1 and OCR1A If an interrupt is also triggered, a corresponding configuration bit (flag) is set: Bit OCIE1A im Register TIMSK. The register TIMSK is described in the data sheet in the chapter on Timer0 (page 80).

Przerwania są aktywowane funkcją biblioteczną sei (), dezaktywację można wykonać za pomocą cli (). Aby skonfigurować mikrokontroler tak, aby między Porównaj TCNT1 i OCR1A Jeśli zostanie również wywołane przerwanie, ustawiany jest odpowiedni bit konfiguracji (flaga): Bit OCIE1A im Zarejestruj TIMSK. Rejestr TIMSK został opisany w arkuszu danych w rozdziale Timer0 (strona 80).

Um die Interruptfunktion zu konfigurieren und zu aktivieren, dienen also die folgenden Befehle in dem nachfolgenden Programm:

Thus, to configure and enable the interrupt function, the following commands are used in the following program:

Tak więc, aby skonfigurować i włączyć funkcję przerwania, następujące polecenia są używane w następujący program:

    TIMSK |= (1<<OCIE1A); //Interrupt-Flag-Register, hier wird 
	                  //Timer/Counter1, Output Compare A Match Interrupt Enable gesetzt.
    sei();                //Interrupts allgemein erlauben.

Code 4.1-5: Konfiguration und Aktivierung der Interrupt-Funktion.

Nach diesen ganzen Konfigurationen, dient nun der folgende Code-Abschnitt dazu, die LED mit 1Hz blinken zu lassen:

After all these configurations, the following code section now serves as the LED to blink at 1Hz:

Po wszystkich tych konfiguracjach następująca sekcja kodu służy teraz jako dioda LED migać przy 1 Hz:

       if(ZEIT%10==0)                 
           einLEDgruen1();
       
       if(ZEIT%10==5)                 
           ausLEDgruen1();

Code 4.1-6: Blinke mit 1Hz.

Hinweis: Das für die Variable verwendete Schlüsselwort "volatile" kann für globale Variablen eingesetzt werden und weist den Kompiler an, die entsprechende Variable für einen schnellen Zugriff im gesamten Programm verfügbar zu machen. Wird "volatile" nicht gesetzt, kann es vorkommen, dass Änderungen bei globalen Variablen gar keine Wirkung zeigen.

Note: The volatile keyword used for the variable can be global Variables are used and instructs the compiler, the corresponding variable for quick access throughout the program. If volatile is not set, changes to global variables may occur show no effect at all.

Uwaga: zmienne słowo kluczowe użyte dla zmiennej może mieć charakter globalny Zmienne są używane i instruuje kompilator, odpowiednią zmienną dla szybkiego dostępu przez cały program. Jeśli lot nie jest ustawiony, mogą wystąpić zmiany zmiennych globalnych nie wykazują żadnego efektu.

..und hier folgt der besprochene Quelltext:

..and here follows the discussed source text:

..i tutaj następuje omówiony tekst źródłowy:

//Blinken grüne LED

#include <avr/io.h>  
#include<avr/interrupt.h>

volatile unsigned int ZEIT = 0;

SIGNAL(SIG_OUTPUT_COMPARE1A)
{
    ZEIT++;
    ZEIT%=10000;    
}


void init()
{
   DDRA = 0;
   DDRB = 0;
   DDRC = 0;
   DDRD = 0;
                           
   DDRA |= 0b00000011;  //PA0 und PA1 als Ausgang konfigurieren          

   PORTA &= 0b11111100; //PA0 und PA1 auf Masse ziehen.      

    //Normaler Zählermode
	//Vorteilung 1024
	//1000000/1024=976,5625Hz

    //Mode 4 (s. Datenblatt S. 107):
    //CTC: Clear Timer on Compare Match
	//Vergleichswert in OCR1A

	//16Bit Zählregister: 0..65535
    TCCR1A = (0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (0<<WGM11) | (0<<WGM10);
    TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);

    TIMSK |= (1<<OCIE1A); //Interrupt-Flag-Register, hier wird 
	                     //Timer/Counter1, Output Compare A Match Interrupt Enable gesetzt.

    OCR1A = 97; //97=> ungefähr im 0,1 Sekunden-Takt wird Interrupt ausgelöst.
                //genauer sind es 10,067654639Hz, also 0,099328Sekunden pro Zählschritt.

    sei();

}

void einLEDgruen1()
{
    PORTA |= 0b00000010; //PA1 auf 1 setzen       
}

void ausLEDgruen1()
{
    PORTA &= 0b11111101; //PA1 auf 0 setzen       
}
             
int main(void)                    
{      
   unsigned int zaehler = 0;

   init();
   while(1)                       
   {             
       if(ZEIT%10==0)                 
           einLEDgruen1();
       
       if(ZEIT%10==5)                 
           ausLEDgruen1();
   }                              
}

Code 4.1-7: Quelltext: 003_gruen1_blink_timer2pause.c

Übung
exercise
ćwiczenie
  • Realisieren Sie ein Blinken der LED mit möglichst exakten 4Hz. Verwenden Sie auch dazu eine Taktung mit dem internen RC-Oszillator von 1MHz.
  • Da OCR1A ein 16-Bit-Register ist, kann darin ein maximaler Wert von 65536 stehen. Nutzen Sie dies aus, um ein exaktes 4Hz-Blinken auch ohne Interrupts zu realisieren.
  • Variieren Sie die vorangehenden beiden Aufgaben, indem Sie Modus 0 anstatt Modus 4 benutzen (vergl. Datenblatt).
musterloesungen.zip - Musterlösungen zu obiger Übung.