Forum: Mikrocontroller und Digitale Elektronik ATmega32U4 Timing Problem


von Martin B. (echterwiener)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen!

Ich hba leider ein Problem bei dem ich nicht weiter weiß...

Ich habe eine Platine erstellt mit einem ATmega32U4. Bin gerade am 
Testen und hab dazu das Standard Blink Beispiel (leicht abgeänderte 
Zeiten) von der Arduino IDE mit einem Programmer aufgespielt. Das hat 
auch funktioniert. Also programmieren sollte kein Problem sein. Blinken 
tut das ganze auch aber leider 8mal langsamer als es sollte. Ich finde 
den Fehler einfach nicht.
Drum die Bitte mir zu helfen.
1
void setup() {
2
  // initialize digital pin 13 as an output.
3
  pinMode(7, OUTPUT);  // Schaltplan Signal T1 (Ausgangsstufe LED)
4
}
5
6
// the loop function runs over and over again forever
7
void loop() {
8
  digitalWrite(7, HIGH);   // turn the LED on (HIGH is the voltage level)
9
  delay(50);              // wait for a second
10
  digitalWrite(7, LOW);    // turn the LED off by making the voltage LOW
11
  delay(50);              // wait for a second
12
}

von Wolfgang (Gast)


Lesenswert?

Martin B. schrieb:
> Ich finde den Fehler einfach nicht.

CHDIV8 steht falsch (Kapitel 6.2.1 im Datenblatt)

von Michael U. (amiga)


Lesenswert?

Hallo,

Fusebits falsch? CDIV8 noch gesetzt?

Gruß aus Berlin
Michael

: Bearbeitet durch User
von guest (Gast)


Lesenswert?

Aua, zwei Versuche und dann beide mit Tippfehlern.
Dann versuch ich es jetzt auch mal:
1
CKDIV8

von Michael U. (amiga)


Lesenswert?

Hallo,

guest schrieb:
> CKDIV8

Danke. :-)

Gruß aus Berlin
Michael

von Karl M. (Gast)


Lesenswert?

Der atmega32u4 hat einen usb bootloader und benötigt zwingend einen 
externen 16MHz quarz.
Mann stellt hier also , im vergl. zu einigen anderen keinen 1/8 Teiler 
aus.

von Michael U. (amiga)


Lesenswert?

Hallo,

Karl M. schrieb:
> Der atmega32u4 hat einen usb bootloader und benötigt zwingend einen
> externen 16MHz quarz.

auch in diesem Fall?

Martin B. schrieb:
> Ich habe eine Platine erstellt mit einem ATmega32U4.

Im Lieferzustand CKDIV8 aktiv, die 48MHz für USB werden ohnehin per 
interner PLL erzeugt. Clock-Fuse stehen auf ext. Low-Frequenz 8MHz laut 
Datenblatt, das dürfte auch mit seinen 16MHz noch klappen und intern 
würde der Core dann mit 2MHz laufen.

Wie die ATmega32U4 aus der ArduinoIDE programmiert werden habe ich jetzt 
nicht nachgeschaut, welchen Bootloader der TO benutzt muß er wissen.

Gruß aus Berlin
Michael

von Martin B. (echterwiener)


Lesenswert?

Danke euch drei für die schnelle Antwort!

Ich hab versucht dieses Bit zu setzen, in dem ich die Bords.txt 
abgeändert hab auf "leonardo.bootloader.low_fuses=0x5e" und dann den 
Bootloader aufgespielt hab.
hatte aber keinen Effect, wenn ich dann wieder das Blink Programm über 
den Programmer aufgespielt habe.

von Georg M. (g_m)


Angehängte Dateien:

Lesenswert?

1
CLKPR = 0x80;  // Prepare Clock Prescaler
2
CLKPR = 0x00;  // Set Clock Prescaler to 1

von Andre R. (ltisystem)


Lesenswert?

Wie unnütz ist das denn, dass delay() nicht auf die eingestellte 
Taktrate achtet? Dann finde ich diese Funktion irgendwie sinnlos...

Auch wenn dich das nicht mit deinem Problem weiter bringt interessiert 
mich, warum du PIN PE6 genommen hast? Im Datenblatt steht dazu, dass der 
PIN der Eingang vom Comperator oder für externe Interrupts ist...

: Bearbeitet durch User
von Martin B. (echterwiener)


Lesenswert?

Georg M. schrieb:
>
1
> CLKPR = 0x80;  // Prepare Clock Prescaler
2
> CLKPR = 0x00;  // Set Clock Prescaler to 1
3
>

Das hat geholfen! jetzt stimmen die Zeiten und nicht nur das Blink 
Programm ist korrekt sondern auch LCD und Max31855 gibt Daten her.


Andre R. schrieb:
> Wie unnütz ist das denn, dass delay() nicht auf die eingestellte
> Taktrate achtet? Dann finde ich diese Funktion irgendwie sinnlos...
>
> Auch wenn dich das nicht mit deinem Problem weiter bringt interessiert
> mich, warum du PIN PE6 genommen hast? Im Datenblatt steht dazu, dass der
> PIN der Eingang vom Comperator oder für externe Interrupts ist...

Ja ich finde das auch sehr unnütz! aber im Normalfall ist die Funktion 
auch sehr praktisch wenns um keine kritischen Anwendungen geht...

Ich kann dir die Frage leider nicht beantworten, ich hab die Schaltung 
zu großen Teilen übernommen aus einem Projekt aus den Internet und dann 
Komponenten getauscht die ich bekommen kann.


@all: Danke für eure Hilfe allein wäre ich nicht auf den "Fehler" 
gekommen!

von Wolfgang (Gast)


Lesenswert?

Andre R. schrieb:
> Wie unnütz ist das denn, dass delay() nicht auf die eingestellte
> Taktrate achtet? Dann finde ich diese Funktion irgendwie sinnlos...

Du Schlaumeier, dann verrate mal, wie delay() die Taktrate bestimmen 
soll?

Solange das Zielsystem nicht über entspechende Software und eine 
(richtig laufende) RTC verfügt, ist der Compiler beim Übersetzten von 
delay() auf die im Programm vorhandenen Angaben (in Form von FCPU o.ä.) 
angewiesen.

von Andre R. (ltisystem)


Lesenswert?

Wolfgang schrieb:
> Du Schlaumeier, dann verrate mal, wie delay() die Taktrate bestimmen
> soll?

Indem es die gesetzten Fuses ausliest? Oder geht das nicht?

Ansonsten muss eigentlich bei der delay Funktion stehen, dass diese nur 
mit der und der Taktrate richtig zu benutzen ist und diese Bemerkung hab 
ich bis jetzt noch nicht bewusst wahrgenommen.

: Bearbeitet durch User
von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Andre R. schrieb:
> Ansonsten muss eigentlich bei der delay Funktion stehen, dass diese nur
> mit der und der Taktrate richtig zu benutzen ist und diese Bemerkung hab
> ich bis jetzt noch nicht bewusst wahrgenommen.

Nein, muss es nicht, die Funktion wertet die zur Compilezeit gesetzte 
Definition von F_CPU aus.

Wenn die nicht zu dem passt, was beim µC eingestellt ist, ist's halt 
einfach nur falsch, aber leicht zu beheben.

von Andre R. (ltisystem)


Lesenswert?

Rufus Τ. F. schrieb:
> Nein, muss es nicht, die Funktion wertet die zur Compilezeit gesetzte
> Definition von F_CPU aus.

Entschuldige, falls das eine dumem Frage ist: die Funktione wertet die 
gesetzte Definition der F_CPU aus, die sich wo befindet? Also wo steht 
die Definition? F_CPU ist die nackte Taktrate oohne irgendwelche Teiler, 
auch wenn welche eingestellt sind?

von Wolfgang (Gast)


Lesenswert?

Andre R. schrieb:
> die Funktione wertet die
> gesetzte Definition der F_CPU aus, die sich wo befindet?

Nein, nicht die Funktion wertet F_CPU aus, sondern der Compiler, mit dem 
du den Code für den µC generierst.
Der Wert wird entweder über die IDE festgelegt oder ist im Quellcode 
definiert.

von Florian (Gast)


Lesenswert?

Karl M. schrieb:
> Der atmega32u4 hat einen usb bootloader und benötigt zwingend einen
> externen 16MHz quarz.

Erzähle das mal dem AVR mit einem 8MHz Quarz!
Die können beide!

von Michael U. (amiga)


Lesenswert?

Hallo,

Andre R. schrieb:
> Entschuldige, falls das eine dumem Frage ist: die Funktione wertet die
> gesetzte Definition der F_CPU aus, die sich wo befindet? Also wo steht
> die Definition? F_CPU ist die nackte Taktrate oohne irgendwelche Teiler,
> auch wenn welche eingestellt sind?

Nein. F_CPU muß die tatsächliche Taktfrequenz bekommen, mit der der Core 
läuft. Der Compiler liest keine Fuase-Bits aus, er schaut auch nicht 
nach, welchen Quarz mit welcher Frequenz Du außen angebaut hast usw.
Für all das bist Du zuständig.

Hätte der TO z.B. F_CPU mit 2 MHz angeben (16MHz Quarz und CKDIV8 
programmiert) hätten die delay-Werte gestimmt.

Gruß aus Berlin
Michael

von Jim M. (turboj)


Lesenswert?

Andre R. schrieb:
> Wie unnütz ist das denn, dass delay() nicht auf die eingestellte
> Taktrate achtet? Dann finde ich diese Funktion irgendwie sinnlos...

Viele Leute benutzen lange delay_ms() um nachzuschauen ob F_CPU richtig 
gesetzt wurde. Einfach Blinkfrequenz messen. ;-)


Für nicht-triviale Programme sind delays im ms Bereich verpönt - dort 
nimmt man besser Interrupts und Statemachines. Bei Delays im us Bereich 
würde die Berechnung jedesmal zu lange dauern. Beim Macro macht das 
schon der Compiler.

von Andre R. (ltisystem)


Lesenswert?

Ja, dass delays für zeitkritischebn Geschichten murks sind hab ich schon 
gelernt und kann ich bestätigen :D

Michael U. schrieb:
> Nein. F_CPU muß die tatsächliche Taktfrequenz bekommen, mit der der Core
> läuft. Der Compiler liest keine Fuase-Bits aus, er schaut auch nicht
> nach, welchen Quarz mit welcher Frequenz Du außen angebaut hast usw.
> Für all das bist Du zuständig.

Das heißt, wenn ich nicht selber im Quellcode F_CPU modifiziere geht der 
Compiler von einer Taktfrequenz der Werkseinstellung aus, egal welche 
Fuses ich gesetzt habe oder nicht. Demzufolge wird ein delay(100) bei 
F_CPU = 8MHz ein anderes Ergebnis liefern als F_CPU = 2 MHz? Unabhängig 
davon, ob ich die Fuses nun gesetzt habe oder nicht?

von Cyblord -. (cyblord)


Lesenswert?

Andre R. schrieb:
> Das heißt, wenn ich nicht selber im Quellcode F_CPU modifiziere geht der
> Compiler von einer Taktfrequenz der Werkseinstellung aus, egal welche
> Fuses ich gesetzt habe oder nicht. Demzufolge wird ein delay(100) bei
> F_CPU = 8MHz ein anderes Ergebnis liefern als F_CPU = 2 MHz? Unabhängig
> davon, ob ich die Fuses nun gesetzt habe oder nicht?

Ja. Schau dir doch die delay_ms Funktion einfach mal an. Für normale 
Menschen ist das aber keine Einschränkung weil die F_CPU von vornherein 
auf den korrenten Wert gesetzt haben. Nur Spongos die das nicht haben, 
müssen hier eine Welle wegen _delay_ms machen.

Aber F_CPU gehört nicht in den Quellcode sondern in die Linker-Parameter 
des Projekts.

Und btw: Niemand hält dich ab eine entsprechende Delay Funktion zu 
schreiben welche die Frequenz anhand der Fuses bestimmt.
Nun gut, geht bei ext. Quarzen usw. natürlich auch wieder nicht und 
somit muss man wieder F_CPU bemühen aber hey, irgendwas ja immer und es 
würde dich ein wenig beschäftigen und du wärst weg von der Straße und 
vom Forum....

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

Andre R. schrieb:
> Das heißt, wenn ich nicht selber im Quellcode F_CPU modifiziere geht der
> Compiler von einer Taktfrequenz der Werkseinstellung aus, egal welche
> Fuses ich gesetzt habe oder nicht. Demzufolge wird ein delay(100) bei
> F_CPU = 8MHz ein anderes Ergebnis liefern als F_CPU = 2 MHz? Unabhängig
> davon, ob ich die Fuses nun gesetzt habe oder nicht?

der Compiler geht von garkeiner konkreten Taktfrequenz aus, dem ist 
völlig egal wie schnell das Programm hinterher abgearbeiet wird.
Funktionen, die Zeitabhängigkeit fordern wie z.B. _delay() warnen 
einfach, wenn F_CPU nicht gesetzt wurde. Wenn Du z.B. einen timer 
programmierst muß Du die nötigen Register und Teilerwerte selber 
bestimmen.

Die ArduinoIDE als Beispiel geht von einem Arduino aus, den Du in der 
Boardauswahl eingestellt hast. Der kommt im Lieferzustand auch mit 
Bootloader, passendem Quarz und passend gesetzten Fuses.
Nur deshalb gehen da die internen Rechnereien von feststehenden Werte 
aus.
Baust Du selber was, mußt Du entweder alle Randbedingungen (Quarz, Fuses 
usw) des "Arduinos" einhalten oder dir einen passenden boards.txt 
Eintrag für Deinen "Arduino" anlegen.

Gruß aus Berlin
Michael

von Wolfgang (Gast)


Lesenswert?

Andre R. schrieb:
> Das heißt, wenn ich nicht selber im Quellcode F_CPU modifiziere geht der
> Compiler von einer Taktfrequenz der Werkseinstellung aus, egal welche
> Fuses ich gesetzt habe oder nicht. Demzufolge wird ein delay(100) bei
> F_CPU = 8MHz ein anderes Ergebnis liefern als F_CPU = 2 MHz?

Nein, der Compiler kann alleine schon deshalb nicht von irgendeiner 
Werkseinstellung ausgehen, weil kein Compiler dieser Welt weiss, was du 
auf deinem Board für einen Taktgeber aufgelötet hast. Der Compiler 
verwendet den in der IDE festgelegten Wert oder meckert (hoffenlich), 
dass der Wert gar nicht definiert ist.
Für die Arduino Board steht der Wert, den die Arduino IDE benutzt z.B. 
in der Board-Datei.

von guest (Gast)


Lesenswert?

Cyblord -. schrieb:
> Aber F_CPU gehört nicht in den Quellcode sondern in die Linker-Parameter
> des Projekts.

Das ist Blödsinn, der Linker kann mit dem Wert absulut nichts anfangen.
Der einzige, der ihn benutzt ist der Präprozessor. Und ob der ihn im 
Quellcode findet oder in seinen Parametern ist im Endeffekt auch egal.

Wolfgang schrieb:
> Nein, der Compiler kann alleine schon deshalb nicht von irgendeiner
> Werkseinstellung ausgehen, weil kein Compiler dieser Welt weiss, was du
> auf deinem Board für einen Taktgeber aufgelötet hast. Der Compiler
> verwendet den in der IDE festgelegten Wert oder meckert (hoffenlich),
> dass der Wert gar nicht definiert ist.

Der Compiler nicht direkt, aber die Entwickler der avr-libc (gekürzt):
1
#ifndef F_CPU
2
# warning "F_CPU not defined for <util/delay.h>"
3
# define F_CPU 1000000UL
4
#endif
Die gehen halt von dem wohldefinierten Zustand aus, in dem die Dinger 
von Atmel/Microchip produziert werden. Sie schreiben in der Doku aber 
auch dazu:
1
The value 1 MHz here is only provided as a "vanilla" fallback if no such user-provided definition could be found.

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.