Forum: Mikrocontroller und Digitale Elektronik Overflow oder anderes Problem?


von Raven (Gast)


Lesenswert?

Hallo, ich habe folgenen C Code für einen Atmega 8535

Eine LED soll ihre Frequenz ändern und dann jeweils kurz aufblitzen 
(also ein Stroboscope). Über ein Poti wird die Blinkfrequenz 
eingestellt.

Allerdings scheint es für mich so, als ob der µC ab und zu neu startet, 
da das Licht ganz kurz mal aus ist, oder ca eine halbe Sekunde an ist.

Woran könnte das liegen, ich habe schon 4 verschiedene 8535 getestet:

hier der Code:
1
#include <stdlib.h>
2
#include <avr/pgmspace.h>
3
#include <lcd.h>
4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include <stdint.h>
7
#include <avr/interrupt.h>
8
9
10
11
12
volatile unsigned int Startwert;
13
volatile unsigned int Endwert;
14
15
void init_timer(void)
16
{
17
    TCCR1B |= (1<<CS12) | (1<<CS10);
18
19
20
    TCNT1 = 0;
21
22
}
23
24
25
uint16_t Kanal(uint8_t mux)
26
{
27
  uint8_t i;
28
  uint16_t result;
29
  ADMUX = mux;
30
  ADMUX |= (1<<REFS0);  // 5V Referenz
31
32
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
33
  ADCSRA |= (1<<ADSC);
34
  while ( ADCSRA & (1<<ADSC) ) {
35
     ;
36
  }
37
  result = ADCW;
38
  result = 0;
39
  for( i=0; i<3; i++ )  //3 Messungen
40
  {
41
    ADCSRA |= (1<<ADSC);
42
    while ( ADCSRA & (1<<ADSC) ) {
43
      ;
44
    }
45
    result += ADCW;     //Aufsummieren
46
  }
47
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren
48
49
  result /= 3;                     // Summe durch 3 für Mittelwert
50
51
  return result;
52
}
53
54
55
int main(void)
56
{
57
58
59
60
    uint8_t ErsteFlanke = 1;
61
    uint16_t Timerwert;
62
    DDRB |= (1<<0);
63
    init_timer();
64
65
    while(1)
66
    {
67
        if (ErsteFlanke)
68
        {
69
            Timerwert = 200 + Kanal(0) ;
70
            Startwert = TCNT1;
71
            ErsteFlanke = 0;
72
73
74
        }
75
        else
76
        {
77
            Endwert = TCNT1;
78
            if ( (Endwert - Startwert ) >= (Timerwert)  )
79
            {
80
81
                ErsteFlanke = 1;
82
                PORTB |= (1<<0);
83
                while ((Endwert - Startwert ) < (Timerwert + 10 ) )
84
                {
85
                    Endwert = TCNT1;
86
                }
87
                PORTB &= ~(1<<0);
88
            }
89
90
        }
91
92
93
94
95
96
    }
97
98
    return 0;
99
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Raven schrieb:
> ich habe schon 4 verschiedene 8535 getestet:
Dann ist der Fehler woanders...

Ich würde sagen, du bekommst Probleme, wenn dein Timer mal überläuft. 
Vorher war er 65535 und jetzt ist er 0. Und dann geht das natürlich 
schief:

> if ( (Endwert - Startwert ) >= (Timerwert)  )
Und das auch:
>  while ((Endwert - Startwert ) < (Timerwert + 10 ) )
Endwert - Startwert wäre dann 0 - 65535 = 0xffff = -1 !!!
Und zusammen mit dem vorzeichenbehafteten
>   uint16_t Timerwert;
muß das dann ja schiefgehen... :-/

Aber der Compiler sollte da schon ein paar Warnungen ausspucken...

von M2K (Gast)


Lesenswert?

Ah, natürlich! Ich sollte vorher einer unsigned Variable den Wert 
zuweisen, damit es noch vom Betrag stimmt.

von Karl H. (kbuchegg)


Lesenswert?

Lothar Miller schrieb:

> Ich würde sagen, du bekommst Probleme, wenn dein Timer mal überläuft.

Würde ich auch sagen.
Aber ich finde das Problem nicht :-)

> Vorher war er 65535 und jetzt ist er 0. Und dann geht das natürlich
> schief:
>
>> if ( (Endwert - Startwert ) >= (Timerwert)  )
> Und das auch:
>>  while ((Endwert - Startwert ) < (Timerwert + 10 ) )
> Endwert - Startwert wäre dann 0 - 65535 = 0xffff = -1 !!!

Das stimmt nicht. Sowohl Startwert als auch Endwert sind schon unsigned. 
Die Subtraktion gibt in diesem Fall das richtige Ergebnis

     0x0000 - 0xFFFF = 0x0001

> Und zusammen mit dem vorzeichenbehafteten
>>   uint16_t Timerwert;
> muß das dann ja schiefgehen... :-/

ist auch unsigned.


So ganz klar ist mir das Problem noch nicht. Da passiert irgendwo eine 
Implizite Konvertierung nach signed. Aber noch hab ich sie nicht 
gesehen.

von M2K (Gast)


Lesenswert?

Also ich habs mal probiert das ganze vorher in eine unsigned Variable zu 
schreiben, hilft aber auch nix, Grund wurde von Karl Heinz schon 
gegeben.

@Karl Heinz

warum bist du dir so sicher, dass irgendwo ne Konvertierung nach signed 
stattfindet? Kann ja nur bei der Subtraktion des Startwertes und des 
Endwertes passieren, aber dass stimmt doch soweit...

von M2K (Gast)


Lesenswert?

Also, was ich damit sagen wollte, dass der µC nicht wegen dem Abstürzen 
sollte

von Karl H. (kbuchegg)


Lesenswert?

M2K schrieb:

> warum bist du dir so sicher, dass irgendwo ne Konvertierung nach signed
> stattfindet?


Wegen dieser Symptome

> oder ca eine halbe Sekunde an ist.

und dem Programmteil
1
      PORTB |= (1<<0);
2
      while ((Endwert - Startwert ) < (Timerwert + 10 ) )
3
      {
4
        Endwert = TCNT1;
5
      }
6
      PORTB &= ~(1<<0);

die passen nicht zusammen.

Entweder ist es wirklich ein Hardwareproblem und der µC resettet (kann 
aber eigentlich auch nicht sein, denn bei einem Reset würde PORTB 
gelöscht werden und damit die LED ausgehen) oder da wird tatsächlich das 
Ende des Intervalls 'übersehen'. Ich bin mir noch nicht im Klaren 
inwieweit da jetzt die Addition von + 10 in die signed / unsigned 
Prolematik mit hineinspielt. Aber eigentlich müsste das Ergebnis von 
unsigned + signed ein unsigned Wert sein.
Überlaufen kann die Addition auch nicht, denn Timerwert kann maximal 
1224 gross sein.

Schaden kanns nicht, die 10 mal zu 10U zu machen

      while ((Endwert - Startwert ) < (Timerwert + 10U ) )

auch wenn ich da jetzt keine großen Hoffnungen darin setze.

von M2K (Gast)


Lesenswert?

Nein leider immernoch das gleiche Symptom...

Ich finde diesen Fehler einfach nicht... es ist bestimmt wieder nur ne 
winzige kleinigkeit...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Wegen dieser Symptome
>> oder ca eine halbe Sekunde an ist.
Das ist allerdings sehr ominös... :-/

>>>> ich habe schon 4 verschiedene 8535 getestet:
Welche Taktfrequenz/Oszillatorfrquenz hast du?

von M2K (Gast)


Lesenswert?

8 Mhz interner Takt (bei Allen!)

von M2K (Gast)


Lesenswert?

Habe eben mal beim Anlaufen einen Pin Kurz auf High und wieder auf Low 
setzen lassen. Der Logicanalyser hat mir dann verraten, dass der µC in 
unregelmäßigen Abständen neu startet. Das bedeutet wohl, dass es vom 
Timer, bzw vom ADC abhängig gemacht wird, ob es irgendwo zu einem 
Overflow kommt.
Nur ich finde immer noch nichts, habe schon einige Zahlenbeispiele 
durch...

von Karl H. (kbuchegg)


Lesenswert?

M2K schrieb:
> Habe eben mal beim Anlaufen einen Pin Kurz auf High und wieder auf Low
> setzen lassen. Der Logicanalyser hat mir dann verraten, dass der µC in
> unregelmäßigen Abständen neu startet.

Hmmm.

> Das bedeutet wohl, dass es vom
> Timer, bzw vom ADC abhängig gemacht wird, ob es irgendwo zu einem
> Overflow kommt.

IMHO ist das Programm soweit in Ordnung.

Irgendwelche Probleme an der Stromversorgung?
Rundumbeschaltung?

von M2K (Gast)


Lesenswert?

Ja, die Hardware ist auch korrekt

von Rolf Magnus (Gast)


Lesenswert?

Also alle Versorgungspins angeschlossen und mit Abblock-Kondensatoren 
bestückt? Reset-Pin richtig beschaltet?

von eProfi (Gast)


Lesenswert?

Watchdog?
BrownOut?

von M2K (Gast)


Lesenswert?

Keines von denen macht Probleme...
Fehler immernoch nicht gefunden

von M2K (Gast)


Lesenswert?

Der Bürstenmotor in der Schaltung war nicht entstört.

@Rolf
danke für das Wort Kondensator, die Beste Gleichstromquelle bringt nix 
wenn ein unentstörter Bürstenmotor mitläuft...

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.