Forum: Mikrocontroller und Digitale Elektronik Zähler & Interrupt auslösen ATmega32


von Christian Woltz (Gast)


Lesenswert?

Hallo,
ich versuche gerade mit den Zählern zu hantieren. Ich hätte gerne, das
wenn der Zähler 1 'überläuft' ein Interrupt ausgelöst wird.
Dazu habe ich folgedes in mein C Programm eingefügt:

SEI();
TCCR1B=0b00000101; //Prescaler = 1024, normal Mode
TIMSK=0b00000100;  //Bei überlauf von Timer 1 ==> ISR

Die Interrupt Routine lautet:

ISR (TIMER1_OVF_vect)
{
LcdCursorOn();
}

Leider funktioniert das aber nicht so wie ich mir das vorstelle, und
kann keinen Fehler finden... Könnte mir bitte jemand helfen ??

Gruss

Christian

von johnny.m (Gast)


Lesenswert?

Immer diese unpräzisen Fragestellungen... Was genau verleitet Dich zu
der Annahme, dass 'es nicht funktioniert'? Hast Du es im Simulator
oder in der Hardware getestet? Was macht die Funktion 'LcdCursorOn()'
genau? Was für ein µC? Welcher Takt? Wie sieht der Rest vom Code
aus???...

von Rahul (Gast)


Lesenswert?

@Johnny: Da fehlt noch die Frage nach der Taktquelle für den Timer...
Ich vermute ja fast, dass da jemand einen Bug gefunden hat...

von johnny.m (Gast)


Lesenswert?

Sorry, eine vergesse ich immer;-)

von Christian Woltz (Gast)


Lesenswert?

Die Funktion LcdCoursorOn() schaltet lediglich den Coursor beim Display
ein. Da dies nicht funktioniert gehe ich davon aus, das es nicht
funktioniert.
Getestet wurde das in der Hardware,  es handelt sich dabei um einen
ATmega 32 mit internen Takt.

Hier der Code:
int main(int argc, char* argv[] ) {
  int d=0;
  InitWaage();
  LcdInit();
  UartInit();
  sei();



  while(1){

    if ( PIND & (1<<PIND4)){
      TCCR1B=0b00000101;
      TIMSK=0b00000100;
      d=LesenVonWaage(d);
      TCCR1B=0b00000000;
      //TIMSK=0b00000000;

      SETRDY;
      SendenAnSps(d);

    } else{
      ClrBit(PORTD,6);
      LcdWriteStr("Idle");
      DelayS(1);
      LcdClear();
    }

  } //end while


}

ISR (TIMER1_OVF_vect)
{

LcdWriteChar(1);

}

von johnny.m (Gast)


Lesenswert?

Du hältst den Timer ja auch immer wieder an, bevor der irgendwas machen
kann. Die Funktion 'LesenVonWaage()' kenne ich zwar nicht, aber wenn
der Timer mit Prescaler von 1024 läuft und Du ihn alle paar µs startest
und ein paar µs später schon wieder anhältst, kannst Du lange warten,
bis der auch nur einen einzigen Takt hochzählt...

von johnny.m (Gast)


Lesenswert?

Damit es klarer wird: 'Interner Takt' heißt ja wahrscheinlich 1 MHz.
Also bei Prescaler-Einstellung 1024 gibts alle 1024µs einen
Zählerinkrement. Wenn der Timer gestartet wird (TCCR1B=0b00000101;) und
TCNT1 0 ist, wird letzteres nach ungefähr 1 ms auf 1 erhöht. Und das
ganze muss 65536 mal passieren, bis ein Überlauf eintritt (also mehr
als 65 Sekunden unter 'normalen' Bedingungen). Das gilt aber nur
dann, wenn der Timer nicht immer schon nach kurzer Zeit (möglicherweise
schon vor dem ersten Inkrement) wieder angehalten wird. Der Prescaler
wird ja bei jedem Schreibvorgang auch zurückgesetzt, wodurch der Timer
überhaupt nichts macht, wenn das was zwischen TCCR1B=0b00000101; und
TCCR1B=0b00000000; steht weniger als 1024 Taktzyklen dauert (was
zumindest ziemlich wahrscheinlich ist).

von Christian Woltz (Gast)


Lesenswert?

Das ganze ist als 'Schutz' gedacht falls die Waage nicht bereit ist
und nicht auf die Anforderung reagiert. Deswegen halte ich den ja auch
wieder an ...
Aber selbst wenn ich 5 min warte und die Waage ausgeschaltet ist, also
nicht reagiert springt er mir nicht in die ISR rein.

von johnny.m (Gast)


Lesenswert?

Damit wären wir wieder bei der Sache mit dem Code: Solange Du nicht
mitteilst, was die Funktion LesenVonWaage(d) genau macht, siehts da
ziemlich finster aus...

von Rick Dangerus (Gast)


Lesenswert?

Schau Dir als "Schutz" mal den WatchDog an.
(Datenblatt Seite 39)

Rick

von Christian Woltz (Gast)


Angehängte Dateien:

Lesenswert?

Soll kein Geheimnis sein ...

Das Problem ist, wenn jemand die Waage nicht einschaltet und trotzdem
versucht über die SPS den Waagen Wert einzulsesen bleibt mein Programm
stehen, da er nach dem senden vom W auf eine Antwort der Waage
wartet....

von Peter D. (peda)


Lesenswert?

Wenn Du Probleme mit dem Timer vermutest, dann schmeiß den ganzen
Schrunz raus, der damit nichts zu tun hat und laß ihn endlich mal frei
atmen (laufen).

Einen Fehler muß man systematisch einkreisen und nicht planlos
rumprobieren.


Ein LCD zum Debuggen ist mit Vorsicht zu genießen, es braucht ne Weile,
ehe was angezeigt wird, und da kann es schon längst wieder überschrieben
worden sein.

Nimm lieber eine LED, die sieht man im Dunkeln selbst noch 1µs
leuchten.


Peter

von Christian Woltz (Gast)


Lesenswert?

Wtd bringt mir hier leider nichts, da er ja einen Reset macht, und ich
würde aber lieber in der ISR einen Fehlercode ausgeben....

von Christian Woltz (Gast)


Lesenswert?

Das habe ich auch schon probiert mit einem Oszilloscop....

von Karl heinz B. (kbucheg)


Lesenswert?

Peter hat trotzdem recht.
Wenn du Probleme mit dem Timer hast, dann
fang ein 2-tes Testprojekt an, das sich nur
mit dem Timer besdchäftigt und mit sonst nichts
anderem.
Dadurch konzentrierst du deine Gedanken auf diesen
Problemkreis und hast nicht noch 20 andere Dinge
die in dem Programm schief gehen können.
An diesem Testprogramm kannst du dann nach
Herzenslust rumprobieren und auch das Programm
nach Lust und Laune umbauen um zu sehen wie
die Dinge wirklich funnktionieren.

Auf die Art lernst du schon fast spielerisch, wie
man mit einem Timer (oder was anderem) umgeht und
kannst das Gelernte dann viel schneller in deinem
eigentlichem Program umsetzen.

von Christian Woltz (Gast)


Lesenswert?

;-) Ihr habt ja recht, werde es gleich mal testen....

von Christian Woltz (Gast)


Angehängte Dateien:

Lesenswert?

So,
also in meinem 'Extra' Projekt geht es ...
Nur nicht wenn ich es in mein eiegntliches Projekt einbinde gehts
nicht. Könnte es sein, da ich ja die serielle Übetragung absichern
möchte, das dort Interupts deaktiviert werden. Würde zwar keinen Sinn
ergeben aber....

Zur erinnerung:
Ich fordere einen Wert von der Waage an und warte auf diesen. Damit der
Microcontroller nicht bis in alle ewigkeit wartet wollte ich durch einen
Timer Überlauf erreichen, das eine Fehlermeldung ausgegeben wird.

Anbei mal noch die Funktion für Senden/Empfangen ...

von Karl heinz B. (kbucheg)


Lesenswert?

Nein.
Wenn du nicht explizit einen cli() machst, laufen
die Interrupts weiter wie gehabt.

Bist du absolut, 100% sicher, dass die ISR nicht
aufgerufen wird?

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.