Timer (Assembler)

Einführung

Ein Timer löst ein „internes Ereignis“ aus, welches zu einem Interrupt führt und dem Programmierer somit die Möglichkeit gibt, zu einem bestimmten Zeitpunkt das Hauptprogramm zu unterbrechen, um ein Unterprogramm, die Interrupt Service Routine, auszuführen.

Bitte ließ dir zuerst den Beitrag über die Interrupts durch, da dort wichtige grundlegende Informationen erläutert werden!

Unser Mikrocontroller besitzt 2 Timer:

  1. Timer
    • Bezeichnung: T0
    • Port: 3.4
    • Einsprungadresse: 000Bh
  2. Timer
    • Bezeichnung: T1
    • Port: 3.5
    • Einsprungadresse: 001Bh

 

Anwendung

Timerstartwert errechnen

Im Normalfall wird man dazu aufgefordert, den Timerstartwert selbst zu berechnen. Dazu benötigt man lediglich die Frequenz des Mikrocontrollers und die gewünschte Zeit, nach der ein Interrupt ausgelöst werden soll.

In diesem Fall hat der Mikrocontroller einen Systemtakt von 1 MHz (1*106 Hz) und es soll alle 50 ms ein Interrupt ausgelöst werden.

  1. Zeit errechnen, die ein Takt benötigt

→ 1 Takt benötigt 1µs!

2. Wie viele Takte notwendig?

3. Startwert errechnen

Bei einem 16-Bit-Timer sind 216-1 (= 65.535) Takte notwendig bis zum Überlauf. Mit dem Überlauf sind es somit 216 (= 65.536) Takte. Da wir nur 50.000 Takte brauchen, ist kein Multiplikator notwendig.

→ 65.536 Takte – 50.000 Takte = 15.536 Takte

Stackpointer setzen

Dem Stackpointer wird die Adresse 0x80 zugewiesen:

mov SP,#0x80

Timerstartwert setzen

Nun muss man dem Timer den gerade errechneten Startwert zuweisen.

  1. Dazu wandelt man den Startwert zuerst einmal in eine Hexadezimal-Zahl um:

15.53610 = 3CB016

2. Nun teilt man die Werte und weißt dem Timer ein „Timer High-Byte“ und ein „Timer Low-Byte“ zu.

TH0 enthält das „Timer High-Byte“ und TL0 das „Timer Low-Byte“ des Timers 0.

Die 2 linken Hexadezimal-Zahlen unseres Wertes weisen wir TH0 zu:

mov TH0,#0x3C

Die 2 rechten Hexadezimal-Zahlen unseres Wertes weisen wir TL0 zu:

mov TL0,#0xB0

Timermodus setzen

Unser Mikrocontroller besitzt 4 verschiedene Modi:

M1 M0
0 0 Modus 0
0 1 Modus 1 16-Bit Timer ohne nachladen
1 0 Modus 2 8-Bit-Timer mit Auto-Reload
1 1 Modus 3 2 Stück 8-Bit-Timer

Wir verwenden Modus 1, damit wir 50.000 Takte ohne nachladen realisieren können.

mov TMOD,#0x01

Timer freigeben

Als nächstes gibt man den Timer 0 frei:

setb ET0

Zuletzt gibt man „generell“ alle Interrupts frei:

setb EA

Timer starten

Zum starten des Timer 0, setzt man ein Bit bei TR0. Um ihn zu stoppen entfernt man es.

setb TR0   //Timer starten
clr TR0    //Timer stoppen

ISR erstellen

Damit der Timer nun auch etwas bewirkt, benötigt man noch eine Interrupt Service Routine (ISR).

cseg at 0x000B        //cseg auf die Einsprungsadresse setzen 
isr:                  //Label setzen 
                      //Irgendwelche Befehle 
   reti               //ISR beendet

Nun kann der Timer T0 verwendet werden!

 

Zusammenfassung

  1. Timerstartwert errechnen
  2. Stackpointer setzen
  3. Timerstartwert setzen
  4. Timermodus setzen
  5. Timer freigeben
  6. Timer starten

 

Quelltext-Beispiel

Das folgende (kommentierte) Quelltext-Beispiel löst alle 50 ms einen Interrupt durch Timer 0 aus und komplementiert das Bit bei P2.0:

$NOMOD51                //Vordefinitionen vergessen
#include <at89c5131.h>  //Neue Definitionen einbinden
 
cseg at 0x0000
jmp main                //zu Sprungmarke main springen
cseg at 0x000B          //vordefinierte Einsprungadresse (siehe Einfuehrung)
jmp isr                 //zu Sprungmarke isr springen

main:                   //Sprungmarke main
   mov SP,#0x80         //Stackpointer auf 0x80 setzen
   mov TH0,#0x3C        //TH0-Startwert setzen
   mov TL0,#0xB0        //TL0-Startwert setzen
   mov TMOD,#0x01       //Modus setzen
   setb ET0             //T0 freischalten
   setb EA              //Alle Interrupts generell freischalten
   setb TR0             //T0 starten
 
loop:                   //Endlosschleife
   nop
   jmp loop

isr:                    //Sprungmarke isr
   clr TR0              //Timer stoppen
   mov TH0,#0x3C        //TH0 zuruecksetzen
   mov TL0,#0xB0        //TL0 zuruecksetzen
   setb TR0             //Timer starten 
   cpl P2.0             //Bit bei P2.0 komplementieren 
   reti                 //ISR beendet - zuruekspringen

end

Merken

Merken