Mit der ISR des Timers kann ein kontinuierliches Rechtecksignal an einem Portpin erzeugt werden. Die minimale bzw. maximale Frequenz hängt von der Betriebsart des Timers ab. Die Taktfrequenz des Timers errechnet sich wie folgt:
PCLK = CCLK/2 = OSCCLK/(DIVM *4)
Mit der Betriebsart 2 des Timers kann eine maximale Frequenz von 200 kHz, mit Betriebsart 1 des Timers kann eine minimale Frequenz von 28 Hz bei Verwendung des RC-Oscillator erreicht werden.
Erstellen sie eine Rechteckspannung von ti/T = 0.5 und einer Frequenz von 1 kHz. Der Reloadwert für den Timer beträgt somit 0.5 ms/PCLK = 0.5 ms/0.2712 µs = 1843. Dieser Wert kann nur mit den Betriebsarten 1 und 2 verarbeitet werden. Verwenden sie für dieses Beispiel die Betriebsart 2. In der ISR des Timers soll der Zustand des Portpins P2.0 invertiert werden. Der Reloadwert ist in der Variablen „uiTime“ abgespeichert (siehe Listing 47, ). Die Initialisierung des Timers und das Setzen der ersten Timerwerte werden in der Funktion „v_ InitTimer0()“ vorgenommen (siehe ‚, ƒ). Der Reloadwert für den Timer 0 wird am Anfang der ISR durchgeführt (siehe „). Das Toggeln des Ausgangssignals wird erst danach durchgeführt (siehe …).
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
Test_TimRec |
Test_TimerRectangle |
Test_Timer0Rectangle.c |
|
|
..\Library |
PortConfig.c |
Tabelle 53 Projekt Test_TimRec
|
‚
ƒ ƒ
„
…
|
#include <REG932.H> #include <PortConfig.H>
sbit btClk = P2^0; unsigned int uiTime = 0xF8CC;
void v_InitTimer0(void) { TMOD = 0x01;
TH0 = uiTime/256; TL0 = (unsigned char) uiTime; TF0 = 0; ET0 = 1; }
void main(void) { v_PortConfig(Port2, Pin0 | Pin1 | Pin2, PushPull); v_InitTimer0(); TR0 = 1; EA = 1; while(1); }
void v_Timer0Int(void) interrupt 1 { TH0 = uiTime/256; TL0 = (unsigned char) uiTime; btClk = !btClk; } |
Listing 47 Inhalt von Test_Timer0Rectangle.c
Abbildung 46 enthält das Signal vom Portpin btClk (P2.0). Die geringfügige Abweichung von der 1 kHz-Frequenz ergibt sich aus der Toleranz des RC-Oscillators.
|
|
Abbildung 46 Timer 0, Betriebsart 1, 1kHz
Erstellen sie ein Projekt, bei dem mit Hilfe des Inkrementalgebers die Frequenz einstellbar ist.
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
Test_TrimFreq |
Test_TrimFreq |
Test_TrimFreq.c |
|
|
..\Library |
PortConfig.c, Encoder_Lib.c |
Tabelle 54 Projekt Test_TrimFreq
|
‚
ƒ ƒ
„
…
|
#include <REG932.H> #include <Encoder_Lib.h> #include <PortConfig.H>
sbit btClk = P2^2; unsigned int uiTime = 0xF8D2; // 1 kHz beim RC-Oscillator void v_InitTimer0(void) { TMOD = 0x01; TH0 = uiTime/256; TL0 = (unsigned char) uiTime; TF0 = 0; ET0 = 1; }
void main(void) { v_InitEncoder(); v_PortConfig(Port2, Pin0 | Pin1 | Pin2, PushPull); v_InitTimer0(); TR0 = 1; EA = 1; while(1) { while (cValue == 0); // Warten bis Encoder gedreht wurde if (cValue > 0 & uiTime < 0xFFFF) uiTime++; else if (uiTime > 0) uiTime--; cValue = 0; } }
void v_Timer0Int(void) interrupt 1 { TH0 = uiTime/256; TL0 = (unsigned char) uiTime; btClk = !btClk; } |
Listing 48 Inhalt von Test_Timer0Rectangle.c
Erweitern sie das Projekt so, dass der Reloadwert für den Timer 1 auf der 7-Segment-Anzeige ausgegeben wird. Um die Ausgabe zu realisieren, müssen die Sourcemodule „I2C_Lib.c“ und „SAA1064_Lib.c“ mit in das Projekt aufgenommen werden (siehe Tabelle 55, Abschnitt „Verwendete Sourcemodule“). Um die Funktionen im Sourcemodul „Test_TrimFreq.c“ bekannt zu machen, müssen die H-Files inkludiert werden (siehe Listing 49, und ‚). Die Initialisierung des I²C-Busses erfolgt in der Funktion „v_InitI2C()“ (siehe ƒ). Um den SAA1064 zu initialisieren, muss zuerst die allgemeine Interruptsperre aufgehoben werden (siehe „). Die Umrechnung des Reloadwertes und die Ausgabe erfolgt am Anfang der while-Schleife (siehe …).
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
Test_TrimFreq |
Test_TrimFreq |
Test_TrimFreq.c |
|
|
..\Library |
PortConfig.c, Encoder_Lib.c, I2C_Lib.c, SAA1064_Lib.c |
Tabelle 55 Projekt Test_TrimFreq (erweitert)
|
‚
ƒ
„
…
|
#include <REG932.H> #include <Encoder_Lib.h> #include <I2C_LIB.H> #include <SAA1064_LIB.h> #include <PortConfig.H>
sbit btClk = P2^2; unsigned int uiTime = 0xF8D2; // 1 kHz beim RC-Oscillator void v_InitTimer0(void) { TMOD = 0x01; TH0 = uiTime/256; TL0 = (unsigned char) uiTime; TF0 = 0; ET0 = 1; }
void main(void) { v_InitI2C(); v_InitEncoder(); v_PortConfig(Port2, Pin0 | Pin1 | Pin2, PushPull); v_InitTimer0(); TR0 = 1; EA = 1; v_InitSAA1064(DYNAMIC_MODE); while(1) { Slave.DataLen = 0; Slave.Adr = 0x70; // Adresse SAA1064 v_SetNextI2CVal(1); // Subadresse auf 1 (Daten-Byte) v_ConvVal(uiTime/0x1000); // Umrechung des Reloadwertes (MSB) v_ConvVal((uiTime & 0xF00)/0x100); v_ConvVal((uiTime & 0xF0)/0x10); v_ConvVal(uiTime & 0x0F); // Umrechung des Reloadwertes (LSB) v_StartI2CandWait(); while (cValue == 0); // Warten bis Encoder gedreht wurde if (cValue > 0 & uiTime < 0xFFFF) uiTime++; else if (uiTime > 0) uiTime--; cValue = 0; } }
void v_Timer0Int(void) interrupt 1 { TH0 = uiTime/256; TL0 = (unsigned char) uiTime; btClk = !btClk; } |
Listing 49 Inhalt von Test_TrimFreq.c
Da die beiden Timer 0 und 1 über die SFR TMOD und TAMOD konfiguriert werden, ist es sinnvoll, diese mit Hilfe von Funktionen zu initialisieren. Die Funktionen übernehmen das nötige Ausmaskieren und Setzen der jeweiligen Bits in den SFR. Damit der Übergabewert an die Initialisierungsfunktion nicht in einem HEX-Wert geschrieben werden muss, sind für die einzelnen Betriebsarten des Timers enum-Aufzählungstypen im H-File definiert (siehe Listing 50, und ‚). Für jeden der beiden Timer ist eine eigene Funktion zur Initialisierung des Timers erstellt worden (siehe ƒ, „). Die Definitionen in den enum-Aufzählungstypen sind so gelegt worden, dass alle zulässigen Kombinationen in einem Byte abgespeichert werden können. Dadurch ist der Programmcode klein.
|
‚
ƒ „ |
enum enTimerMode {MODE0 =0, MODE1, MODE2, MODE3, MODE6 = 0x12}; enum enTimerFunc {TIMER = 0, COUNTER = 4, GATE_OFF = 0, GATE_ON = 8, PWM_OFF = 0, PWM_ON = 0x20};
// Funktionsdeklaration void v_InitTimer0(unsigned char ucMode); void v_InitTimer1(unsigned char ucMode); |
Listing 50 Inhalt von TestTimerLib.h
Am Anfang der Initialisierung des Timers werden zuerst alle Bits in den SFR TMOD und AUXR1 auf „0“ gesetzt (siehe Listing 51, ). Als nächstes wird überprüft, ob der Timer in der Betriebsart 6 (Mode 6) arbeiten soll (siehe ‚). Ist dies der Fall, wird das jeweilige Bit im SFR TAMOD gesetzt (siehe ƒ). In dieser Programmverzweigung wird auch überprüft, ob das PWM-Signal aktiviert werden soll (siehe „). Ist dies der Fall wird das jeweilige Bit im SFR AUXR1 gesetzt. Trifft die Betriebsart 6 nicht zu, wird das jeweilige Bit im SFR TAMOD gelöscht (siehe …). In der letzten Zeile (siehe †) wird die Betriebsart in das TMOD-Register geschrieben.
|
‚
ƒ„
… †
‚ ƒ „
… †
|
#include <REG932.H> #include <TimerLibrary.h>
void v_InitTimer0(unsigned char ucMode) { // Einstellung der Betriebsart TMOD = TMOD & 0xF0; AUXR1 = AUXR1 & 0xEF; // Externen PWM-Ausgang abschalten if ((ucMode & MODE6) == MODE6) // Ueberpruefung auf Betriebsart { // 6 (PWM) TAMOD = TAMOD | 0x01; if ((ucMode & PWM_ON) == PWM_ON) AUXR1 = AUXR1 | 0x10; ucMode = ucMode & 0x0F; // MODE6-Codierung und PWM-Info ausb. } else TAMOD = TAMOD & 0xFE; TMOD = TMOD | ucMode; }
void v_InitTimer1(unsigned char ucMode) { // Einstellung der Betriebsart TMOD = TMOD & 0x0F; AUXR1 = AUXR1 & 0xDF; // Externen PWM-Ausgang abschalten if ((ucMode & MODE6) == MODE6) // Ueberpruefung auf Betriebsart { // 6 (PWM) TAMOD = TAMOD | 0x10; if ((ucMode & PWM_ON) == PWM_ON) AUXR1 = AUXR1 | 0x20; ucMode = ucMode & 0x0F; // MODE6-Codierung und PWM-Info ausb. } else TAMOD = TAMOD & 0xEF; TMOD = TMOD | (ucMode * 16); } |
Listing 51 Inhalt von TestTimerLib.c
Erstellen sie nun das Projekt aus Tabelle 56, das die Funktionen „v_InitTimer0()“ und „v_InitTimer1()“ austestet. Timer 0 soll in der Betriebsart 2 als Counter (siehe Listing 52, ) und Timer 2 in Betriebsart 6 als Timer mit aktiver PWM laufen (siehe ‚). Um die Aufzählungstypen MODE2, MODE6, ... verwenden zu können, muss das H-File Timerlibrary.h über die #include-Anweisung eingebunden werden (siehe ƒ).
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
Test_TimerLib |
Test_TimerLib |
Test_TimerLib.c |
|
|
..\Library |
PortConfig.c, TimerLibrary.c |
Tabelle 56 Projekt Test_TimerLib
|
ƒ
‚
|
#include <REG932.H> #include <TimerLibrary.h> #include <PortConfig.H>
void main(void) { v_InitTimer0(MODE2 | COUNTER); v_InitTimer1(MODE6 | TIMER | PWM_ON); v_PortConfig(Port0, Pin7, PushPull); TH1 = 0xF0; P0 = 0xFF; TR1 = 1; while(1); } |
Listing 52 Inhalt von TestTimerLib.c