Forum: Mikrocontroller und Digitale Elektronik Timer Konflikt


von Daniel (Gast)


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;

}

von Karl H. (kbuchegg)


Lesenswert?

Was versteckt sich hier dahinter
1
ISR(TIMER1_COMPA_vect)
2
{    update_clock();
3
   tick_display(); // tick every 0.5 sec
4
    exe_keypad();
5
}

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

von Daniel (Gast)


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 
:-)

von Michael U. (amiga)


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

von Karl H. (kbuchegg)


Lesenswert?

Daniel wrote:

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

Wieviel mehr?

von Daniel (Gast)


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!!!!

von Peter D. (peda)


Lesenswert?

Probier mal:
1
ISR(TIMER1_COMPA_vect, ISR_NOBLOCK)
2
...

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


Peter

von Daniel (Gast)


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;-)

von Karl H. (kbuchegg)


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:
1
volatile uint8_t IdleProcessing;
2
3
ISR(TIMER1_COMPA_vect)
4
{
5
  IdleProcessing = 1;
6
}
7
8
...
9
10
int main()
11
{
12
  ....
13
14
  IdleProcessing = 0;
15
16
  ...
17
18
  while( 1 )
19
  {
20
21
    if( IdleProcessing )
22
    {
23
      IdleProcessing = 0;
24
25
      update_clock();
26
      tick_display(); // tick every 0.5 sec
27
      exe_keypad();
28
    }
29
30
    ....
31
32
  }
33
}

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.

von Daniel (Gast)


Lesenswert?

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

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.