www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Overflow oder anderes Problem?


Autor: Raven (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <lcd.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>




volatile unsigned int Startwert;
volatile unsigned int Endwert;

void init_timer(void)
{
    TCCR1B |= (1<<CS12) | (1<<CS10);


    TCNT1 = 0;

}


uint16_t Kanal(uint8_t mux)
{
  uint8_t i;
  uint16_t result;
  ADMUX = mux;
  ADMUX |= (1<<REFS0);  // 5V Referenz

  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);
  ADCSRA |= (1<<ADSC);
  while ( ADCSRA & (1<<ADSC) ) {
     ;
  }
  result = ADCW;
  result = 0;
  for( i=0; i<3; i++ )  //3 Messungen
  {
    ADCSRA |= (1<<ADSC);
    while ( ADCSRA & (1<<ADSC) ) {
      ;
    }
    result += ADCW;     //Aufsummieren
  }
  ADCSRA &= ~(1<<ADEN);             // ADC deaktivieren

  result /= 3;                     // Summe durch 3 für Mittelwert

  return result;
}


int main(void)
{



    uint8_t ErsteFlanke = 1;
    uint16_t Timerwert;
    DDRB |= (1<<0);
    init_timer();

    while(1)
    {
        if (ErsteFlanke)
        {
            Timerwert = 200 + Kanal(0) ;
            Startwert = TCNT1;
            ErsteFlanke = 0;


        }
        else
        {
            Endwert = TCNT1;
            if ( (Endwert - Startwert ) >= (Timerwert)  )
            {

                ErsteFlanke = 1;
                PORTB |= (1<<0);
                while ((Endwert - Startwert ) < (Timerwert + 10 ) )
                {
                    Endwert = TCNT1;
                }
                PORTB &= ~(1<<0);
            }

        }





    }

    return 0;
}



Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: M2K (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: M2K (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: M2K (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
      PORTB |= (1<<0);
      while ((Endwert - Startwert ) < (Timerwert + 10 ) )
      {
        Endwert = TCNT1;
      }
      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.

Autor: M2K (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein leider immernoch das gleiche Symptom...

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: M2K (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
8 Mhz interner Takt (bei Allen!)

Autor: M2K (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: M2K (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, die Hardware ist auch korrekt

Autor: Rolf Magnus (Gast)
Datum:

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

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Watchdog?
BrownOut?

Autor: M2K (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keines von denen macht Probleme...
Fehler immernoch nicht gefunden

Autor: M2K (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.