Overflow oder anderes Problem?

Gast #1916823
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
}
Moderator (Firma: Titel) Persönliche Seite #1916843
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...
#1916862
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.
Gast #1916875
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...
#1916885
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.
Gast #1917007
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...
#1917012
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren