Attiny clock & Fuse Bits

Gast #2994450
Lesenswert?

Hey,

ich brauch Hilfe von Profis, ich spiel zurzeit ein wenig mit 
Attiny25-20PU herum und bin total verwirrt von dem Datenblatt und dem 
Verhalten. Mir ist irgendwie nicht klar welche internen Oszillator 
Frequenz dieser besitzt. Ich hab leider kein Oszi und hab deswegen eine 
LED blinken lassen im ca. 1Hz Takt und wenn ich das einmal als grob 
Schätzung annehme müsste der interne Clock 2 MHz sein. Das macht aber 
keinen richtigen Sinn wenn ich das Datenblatt richtig verstehe.

Kann mir jemand sagen was die maximale interne Frequenz ist?
Und wie ich diese mit den Fusebits im AVR-Studio 4 einstelle?

Schon mal vielen Dank,
Matthias
Gast #2994468
Lesenswert?

Warum ist dir die MAXIMALE Frequenz so wichtig?

Da sie nicht exakt reproduzierbar ist, MUSS man bei
Benutzung des internen Oszillators mit seinem
Mittelwert "rechnen". Mit dem FUSE-Bit CKDIV8 stellst du ein,
ob der µC mit den vollen (UNGEFÄHR!) 8 MHz des internen
Oszillators arbeitet, oder mit 1/8 davon (1 MHz). Bei
Auslieferung ist das FUSE-Bit auf 1/8 eingestellt.

Abgleichen kann man die Frequenz des internen Oszillators
mit dem OSCCAL-Register auf etwa 4...16 MHz.
Ohne Änderung des FUSE-Bits bekommt man 0,5...2 MHz.
(Firma: keine) #2994469
Lesenswert?

Beim Attiny25 ist standardmäßig der interne Oszillator mit 8 MHz 
aktiviert, das ist auch gleichzeitig die maximale intern erzeugbare 
Frequenz. Allerdings wird der Attiny auch mit gesetzter CKDIV8-Fuse 
geliefert, d.h. der Oszillator-Takt wird durch acht geteilt, so dass der 
effektive Takt 1 MHz ist. Zusätzlich gibt es dann noch ein Register, 
über welches man andere Prescaler für den Takt einstellen kann, das muss 
aber in der Firmware geschehen.
Gast #2994472
Lesenswert?

Übrigens ist dieser interne Oszillator nach meiner
Erfahrung erstaunlich genau (viel besser, als +/- 10%).

Wenn du "rückwärts gerechnet" auf 2 MHz kommst, würde
ich erst mal auf einen Programmierfehler tippen.
Wahrscheinliche Werte sind 0,9...1,1 MHz ohne Veränderung
des Fuse-Bits, oder 7,2...8,8 MHz mit Änderung.
#2994529
Lesenswert?

Matthias schrieb:

> LED blinken lassen im ca. 1Hz Takt

Zeig mal dein Programm und deine Berechnung.
Ich wette du hast in deiner Berechnung einen Fehler mit Faktor 2 
eingebaut, weil du nicht bedacht hast, dass eine LED die 1 Sekunde hell, 
1 Sekunde dunkel ist, mit einer Frequenz von 0.5Hz blinkt und nicht mit 
1Hz.
Sprich: wenn du in einer Timer ISR den Ausgang toggelst, dann halbierst 
du damit die Aufruffrequenz der ISR am Ausgang.
#2994547
Lesenswert?

Bernie schrieb:
> Übrigens ist dieser interne Oszillator nach meiner
> Erfahrung erstaunlich genau (viel besser, als +/- 10%).
>
> Wenn du "rückwärts gerechnet" auf 2 MHz kommst, würde
> ich erst mal auf einen Programmierfehler tippen.
> Wahrscheinliche Werte sind 0,9...1,1 MHz ohne Veränderung
> des Fuse-Bits, oder 7,2...8,8 MHz mit Änderung.



... oder Schwankungen in der Versorungsspannung? Weiß ja nicht wie die 
Schaltung aussieht, aber auf dem Steckbrett kann das schon mal zum 
fehlerhaften Blinken führen (hatte ich gerade erst beim Tiny13).
100nF direkt am µC und auf einmal war das merkwürdige Verhalten weg.
Gast #2994584
Lesenswert?

Hi,

> Zeig mal dein Programm und deine Berechnung.

Das Programm besteht nur aus einer variablen die mit dem Systemtakt 
hochzählt, ist dieser Wert eine Million toggelt die LED. An und Aus 
dauern ca. 1 Sekunde, ist ziemlich ungenau aber es ist definitiv kein 1 
MHz takt und auch kein 8 MHz Takt.

Das Fuse Bit zum achteln der Frequenz ist aus. Außerdem kann man ja die 
CLK source umstellen von "PLL CLK" auf "int. CLK mit 8 MHz", welche 
nimmt man ich habe gerade das erste einsgestellt.

> Abgleichen kann man die Frequenz des internen Oszillators
> mit dem OSCCAL-Register auf etwa 4...16 MHz.
> Ohne Änderung des FUSE-Bits bekommt man 0,5...2 MHz.

Hab dieses Register wie im Datenblatt steht auf 0xFF für 200% Highest 
Frequency gestellt und es verdoppelt auch die Frequenz. Aber ich bin 
immer noch nicht bei 8 MHz geschweige denn bei 16 MHz.

Hab ich irgendwas vergessen oder mache ich was falsch? Wegen der 
Spannungsversorgung ich habe einen IC Sockel der einen 100 nF 
Kondensator integriert hat.

Viele Grüße, Matthias
(Firma: keine) #2994601
Lesenswert?

Wie schon gesagt, zeig mal dein Programm und deinen Aufbau. Wir haben es 
hier oft genug, dass Fragen gestellt werden, weil etwas nicht klappt, 
aber der Code angeblich korrekt wäre. Am Ende ist der Code dann doch 
nicht korrekt und es liegt daran. Mit welcher Optimierung compilierst du 
dein Programm? Und wild an den Clock-Einstellungen rumzuspielen würde 
ich lassen, denn damit kann man sich ganz schnell komplett aussperren, 
und dann wird es kompliziert den AVR wieder ans Laufen zu kriegen.
Gast #2994611
Lesenswert?

also ich hab jetzt einmal meinen Code eingefügt, mit der Variante des 
eigestellten OSCCAL Register auf 200%, jetzt blinkt die LED wieder in 
einem Herz Takt, also an und aus ca. 1 sek. => aktuell eine Frequenz von 
4 MHz (ca.)
1
int main ()
2
{
3
  DDRB |= (1<<DDB1)|(1<<DDB3)|(1<<DDB4);   // LEDs als Ausgang
4

5
  OSCCAL = 0xFF;
6
  CLKPR = 0x00;
7
  while(1)
8
  {
9
    y++;
10
    if (y >= 2000000)
11
    {
12
      PORTB ^= (1<<red);
13
      y = 0;
14
    }
15
  }
16
  return 0;
17
}
Gast #2994623
Lesenswert?

Hi

>>also ich hab jetzt einmal meinen Code eingefügt, mit der Variante des
>eigestellten OSCCAL Register auf 200%, jetzt blinkt die LED wieder in
>einem Herz Takt, also an und aus ca. 1 sek. => aktuell eine Frequenz von
>4 MHz (ca.)

Eine Aussage kannst du nur mit dem Assemblercode machen, der der 
Compiler erstellt. Mit deinem C-Code kann man das nur ahnen.

MfG Spess
#2994629
Lesenswert?

Matthias schrieb:
> Hi,
>
>> Zeig mal dein Programm und deine Berechnung.
>
> Das Programm besteht nur aus einer variablen die mit dem Systemtakt
> hochzählt, ist dieser Wert eine Million toggelt die LED.

Sorry. Aber das ist Blödsinn!

Daraus kannst du überhaupt nichts über das Zeitverhalten ableiten. Je 
nach Optimierungseinstellung deines Compilers kommen da Hausnummern 
raus, gegen die der Wasserstand in der Donau ein Präzissionsinstrument 
ist.

Du musst das schon nach den Regeln machen!


Wenn du ungefähr eine realistische Zeitablesung machen willst, dann geht 
das so
1
// Testprogramm für CPU Takt
2
// Hier die vermeintliche Taktrate des µC eintragen
3
// Im Beispiel hier: 1Mhz
4
 
5
#define F_CPU 1000000
6
 
7
#include <avr/io.h>
8
#include <util/delay.h>
9
 
10
// Hier die tatsächlich verwendeten Parameter angeben
11
 
12
#define LED_PORT    PORTB
13
#define LED_DDR     DDRB
14
#define LED_PIN     PB1
15
 
16
int main()
17
{
18
   LED_DDR |= 1 << LED_PIN;
19
 
20
   while (1)
21
   {
22
      LED_PORT ^= 1 << LED_PIN;
23
      _delay_ms(1000);
24
   }
25
 
26
   return 0;
27
}

Wenn dein µC mit 1 Mhz läuft, dann ist die LED 1 Sekunde ein und 1 
Sekunde aus. Läuft der µC mit 8Mhz dann ist das enstprechend nur 1/8 
Sekunde, es sei denn du trägst bei F_CPU die 8000000 ein. Dann ist es 
wieder 1 Sekunde.

Das ganze beruht darauf, dass dir der Compiler nur dann die notwendigen 
Werte für _delay_ms korrekt errechnen kann, wenn der F_CPU Wert mit der 
Realität des tatsächlichen Taktes übereinstimmt. Nur dann benötigt ein 
_delay_ms(1000) auch tatsächlich 1000 Millisekunden (also 1 Sekunde).


Alles was du mit selbstgebauten Warteschleifen machst, beruht immer auf 
irgendwelchen windigen Annahmen, wie der Compiler deinen Code übersetzt 
und ist daher eine ausgesprochen schlechte Idee.


WICHTIG:
Bei obigem Code muss der Optimizer auf -Os stehen. Nur dann stimmen die 
Zeiten, die _delay_ms wartet!
#2994641
Lesenswert?

Matthias schrieb:
> also ich hab jetzt einmal meinen Code eingefügt, mit der Variante des
> eigestellten OSCCAL Register auf 200%, jetzt blinkt die LED wieder in
> einem Herz Takt, also an und aus ca. 1 sek. => aktuell eine Frequenz von
> 4 MHz (ca.)
>
> int main ()
> {
>   DDRB |= (1<<DDB1)|(1<<DDB3)|(1<<DDB4);   // LEDs als Ausgang
>
>   OSCCAL = 0xFF;
>   CLKPR = 0x00;
>   while(1)
>   {
>     y++;
>     if (y >= 2000000)


Aha. Und diese Operationen macht dein µC in 0-Zeit, oder wie?
Folgt man deiner Argumentation, dann benötigt (laut dir) dein µC für das 
Durcharbeiten eines Schleifendurchlaufs nur 1 Taktzyklus.
Das ist 'ein klein wenig' zu optimistisch :-)
(Firma: keine) #2994647
Lesenswert?

Ich habe mir mal "y" und "red" selbst definiert und das Ganze im 
Simulator laufen lassen. Mit Optimierung -O1 lande ich nach etwa 
12.000.000 Takten in der if-Abfrage. Macht also bei 8 MHz knapp 1,5 
Sekunden.

Eine zuverlässige Zeitmessung macht man auch nicht so, wie du sie 
programmiert hast. Du hast allein schon einen großen Denkfehler. Du 
sagst, du erhöhst pro Takt den Zähler um eins. In Wirklichkeit werden 
hier schon mehrere Takte benötigt, da du, um einen Wert von 2.000.000 
feststellen zu können eine 32 Bit Variable benötigt, der AVR jedoch eine 
8 Bit-Architektur hat und daher jedes Byte einzeln berechnen muss. Zudem 
brauchst du noch einige Takte um zu prüfen, ob der richtige Wert 
erreicht wurde, so dass die schlussendlich vergangene Zeit erheblich 
abweicht.

Nutz für sowas besser einen Timer mit ISR oder die zumindest 
entsprechenden delay-Funktionen.
(Firma: keine) #2994653
Lesenswert?

Noch ein Nachtrag, so wie du es programmiert hast ist die Abweichung 
sogar noch größer, denn wenn du auf 2.000.000 prüft (angenommen pro 
Inkrementierung vergeht ein Takt) müsste die LED bei 8 MHz nur 1/4s an 
bzw. aus sein. Damit ist das Ganze um den Faktor 6 langsamer als 
gewünscht ;)
(Firma: guloshop.de) #2995679
Lesenswert?

Daniel H. schrieb:
> Beim Attiny25 ist standardmäßig der interne Oszillator mit 8 MHz
> aktiviert, das ist auch gleichzeitig die maximale intern erzeugbare
> Frequenz.

Ich entschuldige mich gleich vorab, weil mein Einwurf mit dem 
Thread-Thema wenig zu tun hat, aber trotzdem, zur Ehrenrettung des 
ATtiny25:

Die maximale nutzbare reguläre Frequenz des internen Oszillators ist 16 
MHz.

Die Serie ATtiny25/45/85 besitzt einen Frequenzvervielfacher (8-fach), 
der für den Timer1 genutzt wird. Aus diesem kann die CPU getaktet werden 
(nach einem Teiler durch 4). Dadurch kann die CPU mit der doppelten 
regulären RC-Oszillator-Frequenz laufen.

OSCCAL arbeitet unabhängig davon und kann zusätzlich genutzt werden, um 
die Frequenz weiter zu erhöhen. Allerdings ist bei ca. 21 MHz Schluss, 
weil der Frequenzvervielfacher (PLL) nicht schneller als etwa 85 MHz 
schwingt. Steht jedenfalls im Datenblatt – ausgereizt habe ich das noch 
nicht.
#3108961
Lesenswert?

Das Problem ist hier, dass der Wert des clock prescalers nicht gesetzt 
wird. Man kann den Wert nicht einfach in das Register CLKPR schreiben, 
sondern muss erstmal das höchste Bit setzen und dann in einem weiteren 
Zugriff innerhalb von 4 Taktzyklen des gewünschten Wert einstellen.
Das Problem wird im Beitrag "AVR clock prescaler (CLKPR) und gcc-Codeoptimierung" 
genauer beleuchtet.

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