8051 - zwei Timer benutzen.

Hallo,

Ich habe grad irgendwie ein Problem zwei Timer vernünftig zum Laufen zu bringen.

Also erstmal etwas vorab. Es handelt sich um eine Aufgabe aus einem Praktikum begleitend zur Mikroprozessortechnikvorlesung. Die Aufgabe ist es ein Programm zu schreiben, welches aus einem Array (gefüllt mit Frequenzen und Tondauern) Ein Lied wiedergeben soll. Dafür wird der Pin P1.0 getoggled, welcher an einen Piepser angeschlossen ist. Die Vorgabe war es das Array in der Hauptroutine also in main() und nicht in den Interrupts abzuarbeiten. Das hätte aber meiner Meinung zur Folge, dass man in main() undweigerlich eine Endlosschleife hätte solange die Melodie spielt. Ich möchte aber den IDLE-Modus der CPU benutzen, also muss ich auf Endlosschleifen verzichten. Also habe ich mir ein komplett anderes Konzept überlegt.

Die main() startet nur den Timer0. Danach ist main() zu ende und die CPU kann sich schlafenlegen.

In Timer0 soll jetzt Timer1 gestartet werden, aber genau das gelingt mir jetzt nicht. Timer1 soll also einen Timer-Reload-Wert bekommen, der zur Frequenz des aktuellen Tons passt. Timer0 soll bei einer Pause den Timer1 anhalten und bei einer Tonänderung die Reloadwerte von Timer1 entsprechend dem neuen Ton ändern.

Nur irgendwie bekomme ich den Timer1 nicht vernünftig zum laufen. Ich habe am Ende jetzt mal meinen aktuellen Code angehängt. Das steht zwar auch viel Müll mit drin, aber ich wollte den lieber komplett posten. Man hört momentan ungefähr im Sekundentakt einmal einen Ton und dann eine Sekunde wieder keinen Ton. Die Frequenz des Tons liegt bei ca 140 Hz. Aber ich kann bei den Timer-Reloadwerten einstellen was ich will, der Ton ändert sich gar nicht.

Ich vermute mein Fehler liegt irgendwo bei TMOD.

Ich hab hier für TMOD folgende Inhaltsangabe:

| für Timer 1 | für Timer 0 | |Gate|C/T | M1 | M0 |Gate|C/T | M1 | M0 |

C/T : 1:Counter, 0:Timer

Sieht jemand meinen Fehler? Es würde mir ja schon reichen, wenn beide Timer erstmal nur vernünftig mit den angegebenen Reload-Werten anlaufen.

Der unten mit /XXX eingekesselte Code ist der Code aus einer vorangegangenen Aufgabe, mit der der Timer0 gestartet wurde. Dieser Code funktionierte auch.

#include #include #include "cToolMod.h" #include "cLCDMod.h" #include "Reg552FHMS.h" //#define K 4608 // 5ms //#define TH1_Reloadwert (65536-K) >>8 //#define TL1_Reloadwert (65536-K) & 0x00FF

extern code Melodie;

unsigned int uiFrequenz; unsigned int uiDauer;

unsigned char TH0_Reloadwert = 0; unsigned char TL0_Reloadwert = 0;

void int_T0 (void) interrupt 1 // IR-Routine fr Tondauer { static unsigned char repeat_timer=1;

//unsigned int inhalt,i; //unsigned int code *piMel; // Deklaration Zeiger //piMel=(unsigned int code *)&Melodie; // Startwert

//sizeof(__memt__)

TMOD &= 0xf0; // Timer 1 unverndert lassen TMOD |= 1; // Timer 0 Modus 1

PT1 = 0; // Timer 1 Prioritt niedrig ET1 = 1; // Timer 1 individuelles Freigabeflag

PX1 = 1; // Taste Prioritt niedrig EX1 = 1; // Taste individuelles Freigabeflag

TH1 = 0x5f; TL1 = 0xf0; TR1 = 1; // Timer 1 starten

EA = 1;

TR0 = 0; // Timer 0 beenden

repeat_timer--; if (repeat_timer == 0) { repeat_timer=0; }

}

void int_T1 (void) interrupt 3 // IR-Routine fr Frequenz { //TR1 = 0; // Timer 1 anhalten //TH1 = TH0_Reloadwert; //TL1 = TL0_Reloadwert; //TR1 = 1; // Timer 1 starten

P10 = ~P10; }

main() { unsigned int inhalt,i; unsigned int code *piMel; // Deklaration Zeiger piMel=(unsigned int code *)&Melodie; // Startwert

LCDInit();

//for (i=0;i

Reply to
Markus
Loading thread data ...

Warum schlafenlegen, wenn se was zu tun hätte?

Bin leider auf'm Sprung habe das nicht kontrolliert, aber die allgemeine Freigabe ist gesetzt und auch die TF der Timer vorsichtshalber auf Null bei der Initialisierung?

Gruß, Mario

Reply to
Mario F. Duhanic

Hallo Markus,

Was hast Du eigentlich gegen Endlosschleifen? In jedem µC mit normaler Software laufen Endlosschleifen. Auch wenn Du den µC schlafen legst, musst Du eine Endlosschleife programmieren, die während dem Schlafen nur angehalten wird und später weiterläuft.

Warum machst Du Dir es als Anfänger unnötig schwierig? Versuch doch, das ganz auf dem einfachsten Weg zu lösen anstatt gleich alles auf einmal erschlagen zu wollen.

Mit der einfachste Weg ist wohl: Der eine TimerInterrupt toggelt ständig den Lautsprecherpin. In der Hauptschleife (Endlosschleife) guckst Du bei jedem Durchgang im Array, was Du für eine Frequenz ausgeben sollst und konfigurierst den Timer immer entsprechend um. Damit Dein Lied nicht zu schnell abläuft, musst Du bei jedem Hauptschleifendurchgang ne Warteschleife einfügen, z.B. 200ms.

Wenn das dann funktioniert, kannst Du weiter optimieren:

  1. Die Hauptschleife wird von einem 2. Timer angetriggert. Dadurch wird das Zeitraster genauer.
  2. Ein Timer kann einen Port vielleicht auch direkt toggeln, ohne dass ein Interrupt das machen muss (-> weniger Jitter)

Das Schlafenlegen der CPU macht in der Anwendung kaum Sinn. Wenn Sie schläft, kann sie keinen Ton ausgeben.

Michael

Reply to
Michael Rübig

"Michael Rübig"

kann sie keinen Ton ausgeben.

Rechne doch mal.

z.B. Ton 440Hz -> 2,3 ms Ein Timertick ist 1,085 us Also kann die CPU knapp 2000 Takte schlafen minus den paar, die zum Toggeln benötigt werden.

Allerdings muss es erst laufen, bevor ich dir den Unterschied im Stromverbrauch sagen kann =)

MfG,

Markus

Reply to
Markus

Hi,

Markus schrieb:

kann sie keinen Ton ausgeben.

Du brauchst 2 Interrupts pro Periode!

Da Du die Peripherie nicht mit schlafenlegen kannst (der Timer muss ja weiter laufen) wirds nicht so arg viel ausmachen. Statt 20mA dann 5-10mA oder so.

Da braucht Dein Lautsprecher viel mehr und den sollte man nicht schlafen legen.

Sicherlich ist es interessant, da das letzte rauszukitzeln, das ist wie ein Sport, wie damals am 386er das letzte KByte Ram rauszukitzeln.

Aber beschäftige Dich erstmal mit der Grundaufgabe. Die solltest Du mal irgendwie lösen. Wenn das dann funktioniert, dann kannst Du Dein Programm optimieren. Dann schiebst Du die Hauptschleife in einen Timerinterrupt und konfigurierst den entsprechend. Im Hauptprogramm bleibt dann im Wesentlichen while (1); und ein "Geh-Schlafen"-Befehl übrig.

Michael

Reply to
Michael Rübig

Hallo Markus,

Auf die Schnelle: In dem u.a. Programm sprichst Du immer nur die unteren 4 Bits von TMOD an, also Timer 0. Ich sehe nirgends einen Zugriff auf die für Timer1 relevanten Bits 4..7 (TMOD wird immer &0xF0 genommen, damit die Bits 4..7 bleiben).

Tom

Reply to
Thomas Langhammer

"Thomas Langhammer"

Jap. Stimmt. Jetzt funzt es auch. Hab jetzt alles genullt und 17 zugewiesen. Das ist jeweils das Mode-Flag0. Nu läufts endlich. War irgendwie blind und habe und und oder verwechselt.

MfG,

Markus

Reply to
Markus

"Michael Rübig"

schläft, kann sie keinen Ton ausgeben.

Habe ich auch erst gedacht. Ist aber nicht der Fall. Vll liegts an dem Rechteck, dass der Ton so viel höher klingt ;) Zumindest klingts korrect.

laufen) wirds nicht so arg viel ausmachen. Statt

Immerhin etwas ;)

Aber jedes Lied hat Pausen. Naja... ist ja auch egal. Es ist schließlich zum Üben gedacht.

Sport, wie damals am 386er das letzte KByte Ram

irgendwie lösen. Wenn das dann funktioniert, dann kannst

Jop. Jetzt läuft alles. Möchte jetzt nur ungern das Netzkabel zum Nachmesser durchschneiden weil das der FH gehört =)

MfG,

Markus

Reply to
Markus

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.