Forum: Mikrocontroller und Digitale Elektronik Eine bestimmte Anzahl von Impulsen erzeugen


von Flo S. (tuxianer)


Lesenswert?

Hallo,

Hintergrund ist der Folgende. Ich baue eine Schrittmotorsteuerung mit 
der L297/L298 Kombination. Es wird ein Schritt ausgeführt, wenn der L297 
eine steigende Flanke am Takteingang bekommt.
Die Steuerung soll dann von einem anderen Board via I2C angesteuert 
werden.
Folgendes habe ich mir als Konzept überlegt. Zunächst einmal benötige 
ich eine Art Befehlswarteschlange. Denn wenn nacheinander mehrere 
Anweisung kommen, x-Schritte auszuführen, sollen alle der Reihe nach 
abgearbeitet werden. Wie kann man so etwas geschickt in C realisieren? 
Hier fehlt ja leider die Objektorientierung der Sprache.
Dann zur eigentlichen Impulserzeugung. Ich habe mal schnell diesen Code 
geschrieben, und er scheint auch zu funktionieren. Hier ein relevanter 
Ausschnitt.
LCLK ist der Pin OC2A. Und alle in der ISR verwendetn Varriablen sind 
als volatile definiert.

Hier wird der Befehl angenommen x-Schritte zu machen:
1
lcounter=2*steps;
2
lready=false;
3
LPORT &= ~(1<<LCLK);
4
TCNT2=0;
5
TCCR2A |= (1<<COM2A0);

und hier die ISR:
1
ISR(TIMER2_COMPA_vect) {
2
  if(lready==false){
3
    if(lcounter==1) {
4
      lready=true;
5
      TCCR2A &= ~(1<<COM2A0);
6
    } else {
7
      --lcounter;
8
    }
9
  }
10
}


Der Timer läuft die ganze Zeit im Hintergrund durch, und erzeugt somit 
den Takt. Eventuell setze ich nach erhalten des Befehls ein wenig viel 
zurück. Da bin ich mir nicht genau sicher, ob das nötig ist.
Ansonsten wäre es noch möglich, erst nach erhalten des Befehls den 
Compare Interrupt zu aktivieren, und wenn die Erzeugung der Impulse 
beendet ist, diesen wieder zu deaktivieren?

Viele Grüße

von Karl H. (kbuchegg)


Lesenswert?

Florentin S. schrieb:

> Folgendes habe ich mir als Konzept überlegt. Zunächst einmal benötige
> ich eine Art Befehlswarteschlange. Denn wenn nacheinander mehrere
> Anweisung kommen, x-Schritte auszuführen, sollen alle der Reihe nach
> abgearbeitet werden. Wie kann man so etwas geschickt in C realisieren?
> Hier fehlt ja leider die Objektorientierung der Sprache.

Für eine Schleife und einen Zähler fehlt dir die Objektorientierung?
Mach die Dinge nicht komplizierter als notwendig!

Du machst dir eine Struktur, mit der du 1 Befehl beschreiben kannst. In 
deiner Warteschlange hast du derartige Befehls-'Objekte' der Reihe nach 
gesammelt und wenn das Kommando kommt "5 Befehle abarbeiten", nimmst du 
1 Befehls-"Objekt" nach dem nächsten aus der Warteschlange (solange bis 
die 5 erreicht sind oder keine Befehls-Objekte mehr in der Warteschlange 
sind) und übergibst es einer Funktion, die sich die Objektinternals 
ansieht und den Befehl ausführt.

von Flo S. (tuxianer)


Lesenswert?

Gut. Also das mit der Struktur klingt schon mal nicht schlecht. Ich 
müsste mir nur noch überlegen, wie ich die "codiere". Da ich noch andere 
Befehle habe wie z.B. Drehrichtung festlegen etc. Nur möchte ich nicht 
z.B. 5 Befehle abarbeiten, sondern es soll einfach ein Befehl nach dem 
anderen abgearbeitet werden. Und welche die neu reinkommen, sollen 
gepuffert werden.
Dafür müsste sich doch eigentlich ein Ringpuffer eignen. Da hatte ich 
mal was schönes für den UART.
Ist die eigentliche Impulserzeugung eigentlich ok so, oder könnte man da 
noch etwas verbessern?

von Karl H. (kbuchegg)


Lesenswert?

Florentin S. schrieb:
> Gut. Also das mit der Struktur klingt schon mal nicht schlecht. Ich
> müsste mir nur noch überlegen, wie ich die "codiere". Da ich noch andere
> Befehle habe wie z.B. Drehrichtung festlegen etc. Nur möchte ich nicht
> z.B. 5 Befehle abarbeiten, sondern es soll einfach ein Befehl nach dem
> anderen abgearbeitet werden. Und welche die neu reinkommen, sollen
> gepuffert werden.

OK, dann mach das doch so.

> Dafür müsste sich doch eigentlich ein Ringpuffer eignen.

Recht viel was anderes wirst du auch nicht kriegen :-)

> Ist die eigentliche Impulserzeugung eigentlich ok so, oder könnte man da
> noch etwas verbessern?

Wozu lready?

Lass doch den Counter einfach bis auf 0 runterzählen. Bei 0 stoppt er 
und die 0 sagen dem Rest des Codes, dass die entsprechende Anzahl Pulse 
abgearbeitet wurden. Zudem brauchst du dann auch den Timer nicht dauern 
stoppen und neu starten
1
ISR(TIMER2_COMPA_vect)
2
{
3
  if( lcounter > 0 ) {
4
    if (lcoutner % 2 == 0)
5
      LPORT &= ~(1<<LCLK);   // Pin auf 0
6
    else
7
      LPORT |=  (1<<LCLK);   // Pin auf 1
8
9
    lcoutner--;
10
  }
11
}

Willst du x Pulse generieren lassen.
1
  lcounter = 2 * x;

Willst du wissen ob die Anzahl der Pulse schon erzeugt wurden
1
  if( lcounter > 0 )
2
    // Pulserzeugung ist noch im Gange

von Flo S. (tuxianer)


Lesenswert?

Ok das sieht natürlich übersichtlicher aus. Nur bei dir müsste der Takt
nach der letzten Flanke auf High bleiben. Das dürfte dem L297 eigentlich
egal sein, ich habe aber trotzdem mal die Pegel vertauscht.
Ansonsten werde ich mich als nächstes an die Implementierung des Puffers
machen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.