mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer Konflikt


Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
bin zwar nicht ganz neu, aber ich hab meine Probleme mit den Timern. Ich 
verwende 3 Timer. Timer 0 wird fuer eine PWM benutzt. Timer 1 wird fuer 
Tastenabfrage und Uhrzeit benutzt. Und jetzt moechte ich gerne Timer 2 
benutzen fuer eine Soft PWM. Hab mir hier auch einiges durchgelesen, 
auch die Tutorials, aber es entsteht immer das gleiche Problem. Und zwar 
blinkt die LED am Ausgang PB1 immer dann wenn mein Timer 1 eine Sekunde 
hochzaehlt. Ansonsten dimmt die LED so wie ich es will. Nur alle Sekunde 
geht sie aus und wieder an. Es kommt mir vor, als ob der Timeroverflow 
und der Timercompare sich ueberschneiden.
Bitte helft mir, da ich echt nicht weiter weiss. Und bitte nicht nur auf 
die Tutorials verweisen, denn die hab ich schon durchgearbeitet;-). Ich 
hab sicherlich ein Verstaendnissproblem, dass ich leider nicht alleine 
loesen kann.

Danke schon mal!!!

Gruss Daniel

ISR(TIMER1_COMPA_vect)
{    update_clock();
   tick_display(); // tick every 0.5 sec
    exe_keypad();
}

ISR(TIMER2_OVF_vect)
{
    if (pwm_cnt < 20  ) PORTB &=~(1<<PB1);
  else PORTB |=(1<<PB1);

    if (pwm_cnt==127)
      pwm_cnt=0;
  else
    pwm_cnt++;

}

int main(void)
{
 SPCR=(1<<MSTR);
 DDRB |= (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3)|(1<<PB5)|(1<<PB6);
   wdt_enable(WDTO_2S);


TCCR0= (1<<WGM00)|(1<<COM01)| (1<<COM00)|(1<<CS01);//|(1<<CS00);
TCCR1B = (1<<WGM12)|(1<<CS10);
TCCR2= (1<<CS20);
OCR1A=37314;

TCNT2=0;

OCR0= 0;
SREG = 0b10000000;
TIFR= (1<<OCF1A);
TIMSK = (1<<OCIE1A)|(1<<TOIE2);  //Interrupt enablen





while(1)
{

 if( get_key_press( 1<<PC0 )){servicekey0();pp=0;PORTD |= (1<<PD6);}
if( get_key_press( 1<<PC1 )){servicekey1();pp=0;PORTD |= (1<<PD6);}
if( get_key_press( 1<<PC2 )){servicekey2();pp=0;PORTD |= (1<<PD6);}
if( get_key_press( 1<<PC3 )){servicekey3();pp=0;PORTD |= (1<<PD6);}


   wdt_reset();
  }

 return 0;

}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was versteckt sich hier dahinter
ISR(TIMER1_COMPA_vect)
{    update_clock();
   tick_display(); // tick every 0.5 sec
    exe_keypad();
}

Kann es sein, dass da längere Berechnungen laufen?

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, dass kann schon sein. obwohl dort nur die Uhr hochgezaehlt wird. 
D.h. eine Variable zaehlt bis 100 und dann ist eine Sekunde vorueber. 
Bei tick_display() blinkt der ":" des LCD Displays. Und exe_keypads wird 
die Tastenabfrage abgefragt. Es koennte schon sein, dass das mehr als 
256 Taktzyklen brauch. Nur wie handhabe ich das dann. Da gibt es doch 
sicherlich eine einfache Loesung.....nur leider faellt die mir nicht ein 
:-)

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

in der Interruptroutine nur ein Flag setzen (Hilfvariable, die auf 1 
gesetzt wird). In main in der Hauptschleife dieses Flag abfragen, wenn 
es 1 ist, Deine Unterprogramme abarbeiten und die Variable wieder auf 0 
setzen.

Dann mag Deine Tastaturabfrage mal 1ms später kommen oder Deine Sekunde 
wird ms später hochgezählt, das stört aber nicht weiter.

Gruß aus Berlin
Michael

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel wrote:

> die Tastenabfrage abgefragt. Es koennte schon sein, dass das mehr als
> 256 Taktzyklen brauch.

Wieviel mehr?

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab leider erst heute die Gelegenheit gehabt, dass nachzuschauen. Es 
sind 273 Taktzyklen.
@ michael Leider hab ich dein Prinzip nicht ganz verstanden, denn die 
Unterprogramme sind ja in den Interruptroutinen und nicht in der main 
Schleife. Vielleicht kannst du mir das anders beschreiben, was du 
meinst.

Danke aber schonmal fuer die Antworten!!!!

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probier mal:

ISR(TIMER1_COMPA_vect, ISR_NOBLOCK)
...


Ist aber sehr mit Bedacht anzuwenden, also nie ohne Grund!


Peter

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider gibt der Compiler mir eine Fehlermeldung. Er sagt mir, dass ich 
nur ein Argument in die ISR eingeben darf.
Ich bin ja wie gesagt erst neu in der Materie und frag mich wie ihr das 
denn immer macht um mehere Interrupts paralell laufen zu lassen. Ich 
koennte ja auch einen anderen Weg gehen. Ich moechte eben nur eine 
Softpwm machen, die eine hoehere Frequenz hat als die restlichen 
Aufrufe. Hab schon gedacht nur einen Interrupt zu nutzen aber wofuer hat 
man denn so viel;-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel wrote:
> @ michael Leider hab ich dein Prinzip nicht ganz verstanden, denn die
> Unterprogramme sind ja in den Interruptroutinen und nicht in der main
> Schleife.

Genau darauf will micheal ja hinaus, mache die Aufrufe nicht in
der ISR, sondern in der main-Schleife

> Vielleicht kannst du mir das anders beschreiben, was du
> meinst.

Simpel:

volatile uint8_t IdleProcessing;

ISR(TIMER1_COMPA_vect)
{
  IdleProcessing = 1;
}

...

int main()
{
  ....

  IdleProcessing = 0;

  ...

  while( 1 )
  {

    if( IdleProcessing )
    {
      IdleProcessing = 0;

      update_clock();
      tick_display(); // tick every 0.5 sec
      exe_keypad();
    }

    ....

  }
}

Der Hintergedanke ist der, dass die ISR nur das absolute Minimum
machen muss, was möglich ist. Daher wird der Clock-Update und
das Abfragen des Keypads in die main-Loop verfrachtet. Die ISR
gibt nur noch Bescheid, wann es wieder mal soweit ist. Ob das
Abfragen des Keypads ein paar Nanosekunden später erfolgt, weil
dein Prozessor die Soft-PWM ISR ausführt oder nicht, spielt
keine große Rolle. Es ist ebenfalls unkritisch, wenn das Programm
beim Updaten das Tick-Displays unterbrochen wird. Wichtig ist nur,
dass der Proz. so schnell wie möglich auf die ISR für die Software-
PWM umschalten kann. Und das Einzige was das verhindern kann ist,
wenn das Programm schon in einer anderen ISR steckt. Ergo: Sorge
dafür, daß diese andere ISR so kurz wie nur irgend möglich und so
schnell wie nur irgend möglich abgearbeitet werden kann.

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Karl Heinz. Jetzt klappt es wunderbar und ich hab das Problem 
erkannt!!
Du bist echt ne riesen Hilfe in diesem Forum!!!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.