Forum: Mikrocontroller und Digitale Elektronik timer problem atmega8


von Wastl F. (rescuetigerchen)


Lesenswert?

Hallo Programmierer,

ich habe folgendes Problem. Es soll aus der main() eine Art 
Atemzugsgenerator aufgerufen werden, dessen Frequenz und Wiederholungen 
einstellbar ist.
Es wird ein Atmega8 mit 3.686400MHz verwendet.
Im nachfolgenden Code findet die Abarbeitung der zeitlichen Reihenfolge 
in der ISR statt, bis zu 27 Atemzüge pro Minute klappt das auch 
hervorragend. Aber ab dieser Frequenz leuchtet die LED entweder 
dauerhaft oder gar nicht.
Ich denke es könnte an der Berechnung liegen (klar, int ist nicht 
ganzzahlig).
Habt ihr einen Tip wonach ich suchen kann, eventuell ist ja auch mit den 
Timersettings etwas falsch.

Vielen Dank schon mal,
WastlB
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <avr\io.h>
4
#include <avr\interrupt.h>
5
6
volatile int exsp=0,insp=0,act=0,state=0,max=0;
7
volatile int timer;
8
9
ISR(TIMER1_OVF_vect)
10
{              
11
timer++;
12
  
13
    if(state==1)
14
    {
15
      if(timer<<insp)
16
      {
17
      PORTC |= (1<<0);
18
      }
19
      if((timer<<exsp) && (timer>=insp))
20
      {
21
      PORTC &= ~(1<<0);
22
      }
23
      if(timer==exsp)
24
      {
25
      act++;
26
      timer=0;
27
        if(act==max)
28
        {
29
        state=2;
30
        }  
31
      }
32
    }
33
}
34
35
void init_timer()
36
  {
37
    TCCR1A |= (0 << WGM11) | (1 << WGM10);
38
    TCCR1B |= (1 << WGM13) | (0 << WGM12);
39
    TCCR1B |= (1 << CS12)  | (0 << CS11)  | (1 << CS10);
40
    TIMSK |= (1<<TOIE1);
41
  OCR1A = 1;
42
  }
43
44
void init_front()
45
  {
46
  DDRC |= (1<<0)|(1<<1);
47
  PORTC |= (0<<0)|(0<<1);
48
  DDRB |= (0<<0)|(0<<1)|(0<<2);
49
  }
50
51
void calc_vent(int cyc,int ventf)
52
{
53
max=cyc;
54
exsp = (60000/ventf);
55
insp = exsp/3;    
56
57
}
58
59
int main(void)
60
{
61
  init_timer();
62
  init_front();
63
  sei();
64
65
  for(;;)
66
  {
67
      if(state==0)
68
      {
69
      calc_vent(5,27);
70
      state=1;
71
      }
72
  }
73
74
}

von Karl H. (kbuchegg)


Lesenswert?

Bist du sicher, dass das hier

      if(timer<<insp)

tatsächlich ein Links-Schieben sein soll und kein Vergleich auf kleiner?

Persönlich finde ich es immer unklug, wenn man Programmtext so ganz ohne 
Leerzeichen Buchstaben an Buchstaben setzt. Man sieht dann so schlecht 
die kleinen Feinheiten. Dein Lesezentrum im Gehirn wurde seit du 6 Jahre 
alt bist, darauf trainiert, dass zwischen Wörtern ein Leerraum steht und 
wenn du etwas liest, dann sucht das Gehirn erst mal diese Leerräume um 
dort die gedankliche Trennung der Wörter reinzulegen. Kein Mensch käme 
auf die Idee,
deutschenTextkomplettohneLeerzeichenzuschreiben,weildanndasLeseneinfachn 
ur
furchtbarermüdendist.
Nur wenn dieselben Leute dann C Programmieren, dann müssen alle 
Buchstaben knirsch auf knirsch geschrieben werden, weil das ja beim 
Schreiben so wahsinnig viel Zeit spart.


   if( timer << insp )

Schon sticht das << heraus und es ist weit schwieriger so etwas beim 
Korrekturlesen des Codes irrtümlich als < zu lesen. Gerade in einer 
Sprache wie C, in der jedes falsche Zeichen über Sieg oder Niederlage 
entscheiden kann, ist es umso wichtiger, dass man seinen Code so 
gestaltet, dass er gut lesbar ist. Dazu gehören neben optischen Hilfen 
wie Leerzeichen auch korrekte Einrückungen.

Vergleich mal deine Variante
1
ISR(TIMER1_OVF_vect)
2
{              
3
timer++;
4
  
5
    if(state==1)
6
    {
7
      if(timer<<insp)
8
      {
9
      PORTC |= (1<<0);
10
      }
11
      if((timer<<exsp) && (timer>=insp))
12
      {
13
      PORTC &= ~(1<<0);
14
      }
15
      if(timer==exsp)
16
      {
17
      act++;
18
      timer=0;
19
        if(act==max)
20
        {
21
        state=2;
22
        }  
23
      }
24
    }
25
}

mit der hier
1
#define ATMEN  1
2
#define OFF    2
3
4
#define LED_PORT  PORTC
5
#define ATEM_LED  0
6
7
ISR(TIMER1_OVF_vect)
8
{              
9
  timer++;
10
  
11
  if( state == ATMEN )
12
  {
13
    if( timer < EinatemZeit )
14
      LED_PORT |= (1 << ATEM_LED);
15
16
    else if( timer < AusatemZeit )
17
      LED_PORT &= ~(1 << ATEM_LED);
18
19
    else {
20
      timer = 0;
21
      ZugNummer++;
22
23
      if( ZugNummer == AnzahlZuege )
24
        state = OFF;
25
    }
26
  }
27
}

Denk dir ein paar Füllwörter dazu und der Programmtext der ISR liest 
sich schon fast wie deutsche Sätze.

   if( timer < EinatemZeit )

Aha. Wenn die Zeitzählung als noch kleiner als die Zeit ist, die fürs 
einatmen vorgesehen ist, dann ....

      LED_PORT |= (1 << ATEM_LED);

... ja, logisch. Dann soll die LED welche einatmen anzeigt eingeschaltet 
werden.
Da brauch ich nur den Programmtext lesen, mir ein paar Wörter dazudenken 
und komm zum Schluss: passt. Die Logik kann stimmen.

von Wastl F. (rescuetigerchen)


Lesenswert?

Gut, abgesehen davon hilft das meinem Problem aber auch nicht weiter.
Es sollte tatsächlich ein Vergleich sein, nur ging ich davon aus, daß es 
sich wie bei dem booleschen Vergleich wie zum Beispiel if (i==0) 
verhält.
Die ISR verhält sich nach wie vor ab einer Frequenz von 27 seltsam.

von Karl H. (kbuchegg)


Lesenswert?

Wastl B. schrieb:
> Gut, abgesehen davon hilft das meinem Problem aber auch nicht weiter.

Inwiefern hilft das deinem Problem nicht weiter, wenn ich dir mitteile, 
dass du an dieser Stelle die völlig falsche Operation machst?

> Es sollte tatsächlich ein Vergleich sein, nur ging ich davon aus, daß es
> sich wie bei dem booleschen Vergleich wie zum Beispiel if (i==0)
> verhält.

Ähm.
Wie wäre es mit C-Grundlagen lernen, ehe man an ein Projekt geht. 
Wenigstens die einfachsten Sachen.

   <      ist kleiner
   <<     ist Links-Schieben

 if( time < zeit )

ist etwas komplett völlig anderes als

 if( time << zeit )

von Wastl F. (rescuetigerchen)


Lesenswert?

Sorry.
Hatte (aus irgendwelchen Gründen) deinen Code nicht angezeigt bekommen. 
Erst beim erneuten Aufrufen der Seite war dein Post komplett.
Ich habe die Operatoren angepasst/korrigiert. Immer noch ist die 
Funktion gestört (ich nehme mal an, daß das Programm sich richtig 
verhält, ich es nur falsch programmiert habe).

von Karl H. (kbuchegg)


Lesenswert?

Und du hast hoffentlich bemerkt, dass du denselben Fehler hier

     if((timer<<exsp) && (timer>=insp))

nocheinmal gemacht hast? Wie gesagt: Optische Hilfsmittel können einen 
wesentlichen Unterschied ausmachen.

von Wastl F. (rescuetigerchen)


Lesenswert?

So, dein Hinweis auf die falschen Operatoren hat zum Ziel geführt.
Unglaublich aber, daß das dann überhaupt funktioniert hat.
Danke sehr, das mit den Operatoren bleibt mir beim nächsten Programm im 
Hinterkopf.

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.