Hallo,
ich habe ein Problem:
und zwar habe ich eine Frequenz über den Timer1 generiert. diese möchte
ich jedoch nicht unbegrenzt ausgeben lassen, sondern nach einer
bestimmten Zeit beenden, so dass am Ausgang 0V anliegen.
Ich wollte mit einer for-schleife einfach hochzählen und dann nach einer
bestimmten Zeit stoppen. Wie jedoch stoppe ich diesen timer bzw. gibt es
eine andere Möglichkeit um die Frequenzausgabe zu beenden?
Danke schon mal :)
Dankeschön, ich habs ausprobiert und in einer for- schleife geschrieben.
nur hört er nicht vollständig auf, sondern fängt dann iwann wieder an:(
verstehs ehrlichgesagt nicht, weil ich ja TR1=0 setze und dadurch der
timer ja gestoppt wird. warum startet er dann trotzdem wieder?
habs einmal versucht in die main zu schreiben und einmal in die funktion
für den timer aber beides funktioniert nicht.
hmm, iwie funktioniert das wirklich nicht.
glaube habe insgesamt ein Problem mit dem Verständnis für die Timer
/interrupts.
Habe mal den Quelltext angefügt.
Mit TR0=0; bzw. TR1=0; erreiche ich absolut keine Wirkung.
Wäre wirklich nett, wenn mir jemand auf die Sprünge helfen könnte.
Verzweifel gerade ein wenig.
Dankeschön :)
>glaube habe insgesamt ein Problem mit dem Verständnis für die Timer
Stimmt
Um eine saubere Frequenz auszugeben, kommst Du um eine ISR für den Timer
nicht drum rum. Mit Deinem Progamm dürfte das nichts werden.
Also: Timer-ISR programmieren, die zyklisch entsprechend der geforderten
Frequenz aufgerufen wird. Darin kannst Du dann ein Port-Pin toggeln.
so z.B. für f=11.0592MHz:
1
// Testprogramm TIMER
2
// Beispiel: LED blinkt im o.5s Takt
3
4
#include"reg51.h" // Register des 8051MCs
5
#define LED P0_7
6
7
// Timer 0 - Zeitbasis
8
// Timer0: Reload Wert für T0 T=1/(fosz/12)*(65536-(TH0*256+TL0))
hey, das hat top funktioniert:) bekomm jetzt ein schönes rechtecksignal,
sieht wesentlich besser aus als bei mir.
jetzt steh ich aber noch immer vor dem problem, dass ich den timer
irgendwie stoppen möchte:
hab das Programm wie unten abgeändert.
Dachte dass ich zu Anfang nun über eine Zählschleife die Dauer des
Zählers beschränken kann (was ja später durch einen weiteren Zähler
verbessert werden könnte).
Jedoch stoppt mein Timer absolut nicht.
Wie du siehst, bin ich noch nicht wirklich in dem Thema drin :(.
void initzaehler (void) {
// Timer 0 initialisieren
TMOD = 0x01; // 0000 0001B Timer 0: Mode 1 (16-Bit Zähler)
TH0 = TH0Reload; // Reloadwert Timer 0
TL0 = TL0Reload;
TR0 = 1; // Timer 0 starten
// Interruptsystem
ET0 = 1; // Timer 0, Interruptfreigabe
EA = 1; // generelle Interruptfreigabe
}
// ********************************************************************
void init0 (void)
{
TMOD = 0x01; // 0000 0001B Timer 0: Mode 1 (16-Bit Zähler)
TH0 = 0; // Reloadwert Timer 0
TL0 = 0;
TR0 = 0; // Timer 0 stoppen
// Interruptsystem
ET0 = 0; // Timer 0, Interruptsperren
EA = 0;
}
// ********************************************************************
// Hauptprogramm
// ********************************************************************
void main (void) {
init();
for(i=1; i<5;i++)
{
initzaehler();
while(1);
}
init0();
}
Durch das while(1); kommst Du nie wieder aus der Schleife raus und die
init0(); wird nie aufgreufen! TR0 = 0; würde auch schon reichen, den
Timer anzuhalten. Das i<5 wird auch bei richtiger Funktion nur sehr kurz
die Frequenz ausgeben! Den Timer brauchst Du auch nur einmal am Anfang
zu initialisieren.
hab das jetzt so ergänzt: mit einer wait funktion von 5ms (habs auch mit
einer höheren Zahl versucht)
aber der Timer stoppt einf nicht. iwo ist wohl noch ein denkfehler
vorhanden
void wait5ms(void)
{
TMOD = 0x11;
TR0=0; //Timer stoppen
TH0 = 0xE8; // TH0 wird auf 15 gesetzt, so dass
zusammen mit TL0 die Zahl 0x159F /5000 entsteht, welche die 0,5ms
ausmacht.
TL0 = 0x8E;
TR0 = 1;
while (TF0 == 0); //zählt so lange, bis TF0 == 0
TF0 = 0;
}
// ********************************************************************
void pwm(void)
{
TR0=0;
for (i=0; i<2000; i++)
wait5ms();
TR0=1;
for (i=2000; i<100; i++)
wait5ms();
}
// ********************************************************************
// Hauptprogramm
// ********************************************************************
void main (void) {
init();
initzaehler();
pwm();
}
Das ist jetzt aber was ganz anderes. Du sprachst im ersten Beitrag von
einer Frequenzausgabe und nun von einer PWM. Dafür ist eine andere
Herangehensweise erforderlich, da bei konstanter Frequenz nun das
Tastverhältnis geändert werden muss.
Der XC886 (noch nicht damit gearbeiet) hat nach querlesen des Datasheets
eine spezielle Capture/Compare-Unit dafür. Du solltest diese benutzen.
Mit Standard-Timer geht es auch bedingt zu machen, ist aber aufwendiger.
Es wird damit nur eine geringe PWM-Grundfrequenz zu realisieren sein.
Was willst Du eigentlich machen?
muss das denn unbedingt mit pwm gemacht werden. hab den obigen namen
einf. nur mal so gewählt muss aber nicht heißen, dass es damit gemacht
weren sollte.
ich möchte mit dem Programm vier Schrittmotoren ansteuern und somit
brauche ich für jeden Schrittmotor unter anderem eine andere FReqeuenz.
Da der Schrittmotor nach einer bestimmten Strecke anhalten soll, muss ja
die Frequenz stoppen.
Müsste ja eigentl auch mit dem von dir genannten Timer gehen, den man
dann einfach nach einer Bestimmten Zeit (wait-Timer) stoppen würde. oder
sehe ich das falsch?
Wenn Du 4 Schrittmotoren direkt selber steuern willst, werden so wie Du
es vor hast sicher die Timer knapp. Lass besser einen Timer mit
konstanter Wiederholrate (ms-Bereich) frei laufen (ohne ihn jemals
wieder anzuhalten!) und programmiere darin dann das entsprechende Timing
für jeden Motor. Ist nicht besonderes kompliziert. Einfacher wird es
beim Einsatz entprechender Schrittmotortreiber als Hardware.
Du solltest Dir zunächst grundlegende Kenntnisse der 8051er Familie
aneignen. Dazu gibt es jede Menge guter Literatur. Die XC8.. Serie ist
für den Einstieg nicht unbedingt geeignet. Besser sind überschaubare MC,
z.B. Atmel AT89C51ED2 oder AT89S8253.
habe bisher immer mit xc8... gearbeitet, deswegen will ich mich da auch
nicht großartig umlernen.
mein problem an sich ist einfach, dass meine Frequenz nicht stoppen will
auch mit TR0=0 nicht.
hättest du da nicht evtl ein beispielprogramm wie das funktioniert,
damit ich überhaupt mal sehe wie ich eine Frequenz ausgebe und diese
nach einer bestimmten zeit null ist.
weil mit dem oben von dir genannten tip, welcher nicht schlecht ist muss
ja trotzdem der ms timer iwann gestoppt werden bzw in den ms timer etwas
hineingeschrieben werden. iwie ist mir das einfach nicht ganz klar.
Danke dir, tine
eigentl dachte ich ich könnte einfach nur sagen:
TR0=1 bzw. TR0=0
und damit meinen timer ein bzw ausschalten.
aber angenommen ich schreibe mein programm so:
TR0=1;
wait(); // dann warte ich ein weilchen
TR0=0;
na ja dann passiert niente...
oder wenn ichs so schreib, dann geht halt meine frequenz "an" aber nie
mehr wieder aus :(
for(i=0; i<100; i++)
{TR0=1;}
warte();
for(i=100; i>100; i++)
{
LED=0;
TR0=0;
warte();
}
Im Hauptprogramm setzt Du nur motorX auf 1 ode 0 und damit steuerst Du
die einzelnen Motoren. In den jeweiligen IF-Zweig kommen die Funktionen
für die Schrittmotorsteuerung. Die ISR läuft dann immer.
oki, damit hat sich mein Problem aber noch immer nicht gelöst. Zum einen
stoppt die Frequenz nicht, egal was ich für Befehle eingebe. Zum anderen
kann ich nach deinem oben genannten Programm die beiden Motoren nicht
ablaufen lassen. Ich muss ja beide gleichzeitig auf 1 setzen jedoch
läuft immer nur einer der beiden und zwar motor2 ab.
fetchy schrieb:
> und was kann ich dagegen machen?
// ********************************************************************
// Hauptprogramm
// ********************************************************************
void main (void) {
init();
initzaehler();
pwm();
}
Was soll denn deiner meinung nach passieren, wenn die pwm() funktion
zurueckkommt? Wie gehts dann weiter?
so wie es jetzt geschrieben ist geht es unendlich weiter.
wollte ja eigentl nur, dass die Frequenz dann iwann beendet wird, aber
die "warte" zeiten wurden einfach übergangen. und wenn ich danach
schreibe TR0=0; ändert das an der Situation absolut nichts.
Habs schon versucht mit dem Beispiel von Matthias aber das ist iwie auch
nicht das wahre weil Motor1 und motor2 nicht gleichzeitig laufen können
und nicht einfahc mit motor1=1; motor1=0 angesprochen werden können.
Ich kapiers einfach nicht :(
oki jetzt bekomm ich dadurch eine frequenz. so weit war ich schon.
mein Ziel ist eine Frequenz zu erhalten die dann aber nach einer
bestimmten Zeit komplett aufhört und die Ausgangsspannung einfach
konstant 0 ist.
Dachte das geht in dem ich den Zähler einfach stoppe und die den
jeweiligen Port auf 0 setze, aber wohl offensichtlich nicht, weil die
main funktion immer wieder abgelaufen wird?
abgesehen davon hätte ich noch eine weitere frage: wie kann ich zwei
unterschiedlich frequenzen gleichzeitig ausgeben?
weil bei mir überlagern die sich dann und die frequenz wird nur über
einen Port ausgegeben.