Forum: Compiler & IDEs Programm funktioniert nur kurze Zeit lang, AVR Atmega 8


von MarkusG (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe ein C-Programm für Atmega 8 geschrieben, womit ich eine Art Uhr 
am LCD-Display Zeile 1 darstellen kann und Zeile 2 wechselweise den 
Zählerstatus eines Taster oder den Wert eines ADC anzeige.
(Programm siehe Anhang, includiertes ADC.C als Kommentar im Programm 
unten angehängt)
Leider habe ich mit diesem Programm ein Problem:
es läuft nur kurz (mal 10sec, mal 1min und ein paar sec), aber nie 
länger.
Weiß nicht warum und würde dazu eure Hilfe benötigen.
Die Case sind drin, weil ich hier das Programm noch um verschiedene 
Funktionen erweitern will.
Über eure Hilfe wäre ich wirklich sehr dankbar.

Grüße
Markus
PS:
Das AVR-GCC-Tutorial ist super

von Stefan E. (sternst)


Lesenswert?

Argh, immer diese "ausführlichen" Fehlerbeschreibungen.
Wie äußert sich denn das "läuft nur kurz"? Was passiert dann?

von MarkusG (Gast)


Lesenswert?

es bleibt einfach stehen, es passiert nix mehr. Dehr Inhalt des 
LCD-Displays ändert sich nicht mehr.
Im Programm ist auch ein Blinklicht drinn. Auch diese hört dann auf zu 
blinken.

von Falk B. (falk)


Lesenswert?

@ MarkusG (Gast)

>es bleibt einfach stehen, es passiert nix mehr. Dehr Inhalt des
>LCD-Displays ändert sich nicht mehr.

>Im Programm ist auch ein Blinklicht drinn. Auch diese hört dann auf zu
>blinken.

Tjaaa, da sind einige Schnitzer drin.

>  while(1)
>  {
>    if (TIFR == (1<<TOV0))

Ganz gefährlich. Denn sobald EIN EINZIGES Bit in dem Register zusätlich 
gesetzt ist, wird die Bedingung nie wieder erfüllt. Du willst eher sowas 
machen

    if (TIFR & (1<<TOV0))

Siehe auch Bitmanipulation

In alle Zweige teiler++ reinzuschreiben ist sinnfrei, zumal es damit 
teilweise doppelt ausgeführt wird. Das ist vermutlich auch der Grund, 
warum dein Programm komisch reagiert. Der Switch wird unsinigerweise 
rasend schnell und oft abgearbeitet. Der muss mit in die if() Abfrage 
des Timers!

MFG
Falk

von MarkusG (Gast)


Lesenswert?

Hallo Falk Brunner,

viele Dank für deinen Hinweis mit der Bitmanupulation. Nachdem ich dies 
geändert habe, funktioniert das Programm tatsächlich wie gewünscht.
Das ich in jedem case
teiler ++;
break;
habe ist absicht, damit dieser nur jeweils einmal pro sec. ausgeführt 
wird.

von Falk B. (falk)


Lesenswert?

@ MarkusG (Gast)

>habe ist absicht, damit dieser nur jeweils einmal pro sec. ausgeführt
>wird.

Wird er auch so, wenn mans richtig macht. Und dein Programm ist noch 
falsch. Eher so.
1
  while(1)
2
  {
3
    if (TIFR & (1<<TOV0))
4
    {
5
      // diese Routine wird alle 16384us aufgerufen
6
      // dies ergibt sich aus: 16Mhz=0.0625us
7
      // 8Bit-Timer: 0.0625us*8=16us
8
      // 1024 Prescaler: 16us*1024=16384us
9
10
      TIFR |= (1<<TOV0);
11
      teiler ++;
12
      
13
      // zaehlen Impulse PC1
14
      if (PINC & ( 1 << PC1))
15
      {
16
        if (!bin.hold)
17
        {
18
          bin.hold = 1;
19
          zaehler_1 ++;
20
        }
21
      }
22
      else
23
      {
24
        bin.hold = 0;
25
      }
26
      switch (teiler)
27
      {
28
        case 11:      // Aufruf 1* pro sec
29
          // wechseln des Zusandes PORTD.6
30
          PORTD ^= (1<<6);
31
          break;
32
        
33
        case 22: // Aufruf 1* pro sec
34
          // lesen Analog Channel 0 (10Bit)
35
          adcval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0  -> PC0*/
36
          break;
37
    
38
        case 33: // Aufruf 1* pro sec
39
          if ( sec % 2 ) // sek�nliche Abwechslung der Ausgabe
40
          {
41
            //   Ausgabe des ADC-Messwertes auf dem Display
42
            utoa( 4.8876 * adcval, buf, 10); // Messbereichsendwert: 5000mVolt, Aufl�sung 10Bit=1023
43
            set_cursor(0,2);
44
            lcd_string("=>_____mVolt");
45
            set_cursor(0,2);     // Spalte 2, Zeile 2
46
            lcd_string(buf);     // write ADC-mV to display
47
          }
48
          else
49
          {
50
            // Ausgabe des Zaehler PinC.1 auf dem Display
51
            utoa( zaehler_1, buf, 10);
52
            set_cursor(0,2);
53
            lcd_string("=>_____Zaehler1");
54
            set_cursor(0,2);     // Spalte 2, Zeile 2
55
            lcd_string(buf);     // write ADC-mV to display
56
          }
57
          break;     
58
    
59
        case 44: // Aufruf 1* pro sec
60
          // Ausgabe des Timer 0 auf dem Display
61
          set_cursor(0,1);
62
          lcd_string("________________");
63
        
64
          utoa( sec, buf, 10); // convert uint to char
65
          set_cursor(10,1);     // Spalte 8, Zeile 1
66
          lcd_string(buf);     // write ADC-value to display
67
      
68
          utoa( min, buf, 10); // convert uint to char
69
          set_cursor(5,1);     // Spalte 8, Zeile 1
70
          lcd_string(buf);     // write ADC-value to display
71
      
72
          utoa( std, buf, 10); // convert uint to char
73
          set_cursor(0,1);     // Spalte 8, Zeile 1
74
          lcd_string(buf);     // write ADC-value to display
75
      
76
          break;
77
    
78
        case 55: // Aufruf 1* pro sec
79
          // wechseln des Zusandes PORTD.6
80
          PORTD ^= (1<<6);
81
          break;
82
    
83
        case 66: // Aufruf 1* pro sec
84
          // nun ist eine Sekunde vergangen
85
          // erh�he den Sekundenz�hler
86
          teiler = 0;
87
          sec ++;
88
      
89
          if (sec==60) {
90
            min ++;
91
            sec = 0;
92
            if (min==60)
93
            {
94
              std ++;
95
              min = 0;
96
            }
97
         }
98
      }
99
    }
100
  return 0;
101
}

MFG
Falk

von MarkusG (Gast)


Lesenswert?

OK, bin überzeugt.
Vielen Dank für Eure Hilfen.

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.