Forum: Mikrocontroller und Digitale Elektronik [Newbie] AVR Quarztakt falsch?


von Joachim (Gast)


Lesenswert?

Hallo,
ich hab hier nen Arduino von Watterott mit nem 328 und programmier ihn 
in C. Auf dem Schaltplan den ich hab ist jedoch ein Mega8 eingezeichnet. 
Grummel. Gibt's irgendwo nen besseren Plan? Auf dem Plan läuft ein Mega8 
mit 16Mhz. Das Quarz auf meinem Board scheint etwa Baugröße 0804 zu 
sein, jedenfalls ist es so klein, daß ich nichts darauf lesen kann.

Hab versucht, mit meinem Rigol mir den Quarztakt anzuschauen; nichts 
feststellbar, null Pegel. Ist die Eingangskapazität an meinem 
Präzisionsgerät zu groß...?

Punkt 1)
Haben alle Arduinos, also auch der aktuelle Watterott-Arduino, einem 16 
MHz Quarz? Es würde zumindest Sinn machen...


Punkt 2)
Wenn ich eine LED per T1-Interrupt umschalten lasse, stelle ich fest daß 
die Taktfrequenz nicht stimmen kann.

// Arduino Hardware läuft vermutlich mit 16MHz
#define F_CPU 16000000UL
//hab's mit _delay_ms(1000) getestet, damit stimmt's wohl. Verläßlich?

// TCNT1H and TCNT1L – Timer/Counter1
TCNT1 = 0x8000;


// TCCR1B – Timer/Counter1 Control Register B
// CS12 CS11 CS10 untere 3 bits
//   1    0    0   Takt/256
TCCR1B = 0b00000100;


Kurze Rechnung:
xFFFF- x8000= x7FFF
x7FFF/256 = ca 128
128 => 1/128sek Umschaltzeit

Die in der ISR umgeschaltete LED geht jedoch ca 2x/sek an und aus, dh. 
irgendwas ist viiiel zu langsam.

Nach einigem hin und her habe ich todesmutig versucht die Fuses für den 
Osc zu ändern. Ich werde aus meiner Anzeige aber nicht schlau draus. Hab 
hier AVR Studio5, das ist eingestellt:
BODLEVEL = 2V7
RSTDISBL = [ ]
DWEN = [ ]
SPIEN = [X]
WDTON = [ ]
EESAVE = [X]
BOOTSZ = 256W_3F00
BOOTRST = [X]
CKDIV8 = [ ]
CKOUT = [ ]
SUT_CKSEL = EXTFSXTAL_16KCK_14CK_65MS

EXTENDED = 0xFD (valid)
HIGH = 0xD6 (valid)
LOW = 0xF7 (valid)


Und nu?

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


Lesenswert?

Joachim schrieb:
> hab's mit _delay_ms(1000) getestet, damit stimmt's wohl. Verläßlich?
Welche Compileroptimierung?

> Hab hier AVR Studio5, das ist eingestellt:
Ist das auch programmiert?

von Joachim (Gast)


Lesenswert?

Welche Compileroptimierung?

Unter 'Optimisation' finde ich nur:
Optimize for size -Os

Angehakt ist noch:
Pack Structure members together (-fpack-struct)
Allocate only as many bytes as needed by enum types (-fshort-enums)

Wundert mich, daß so wenig Optionen eingetragen sind. Ich hab unter AVR 
Studio 5 unter Properties -> Toolchain -> AVR/GNU C Compiler -> 
Optimisation geschaut. Vielleicht gibt's ja noch anderswo Eintragungen.


>Ist das auch programmiert?
Hmm. Eigentlich schon. Das hier bekomm ich ja angezeigt:

BODLEVEL = 2V7
RSTDISBL = [ ]
DWEN = [ ]
SPIEN = [X]
WDTON = [ ]
EESAVE = [X]
BOOTSZ = 256W_3F00
BOOTRST = [X]
CKDIV8 = [ ]
CKOUT = [ ]
SUT_CKSEL = EXTFSXTAL_16KCK_14CK_65MS

EXTENDED = 0xFD (valid)
HIGH = 0xD6 (valid)
LOW = 0xF7 (valid)


Ich werd wohl noch rausknobeln müssen was die Fuses so sagen.

von Joachim (Gast)


Lesenswert?

Offensichtlich scheint das mit den Fuses zu stimmen. Wenn ich die 
Gegenprobe mache und auf internen Osc umschalte (von 16MHz extern auf 
8MHz intern) blinkt meine LED nur noch mit halber Geschwindigkeit. 
Soweit also ok. Trotzdem ist meiner Ansicht nach die Geschwindigkeit 
mindestens 1000x zu niedrig.


Der relevante Teil in main:


// Timer Interrupt probieren
// T1, 16-bit Timer
 PRR = 0 ; //sicherstellen, daß er eingeschaltet ist

// TCCR1A – Timer/Counter1 Control Register A
TCCR1A = 0b00000000; // untere 4 bits alle 0

// TCCR1B – Timer/Counter1 Control Register B
// CS12 CS11 CS10 untere 3 bits
//   0    0    0   off
//   0    0    1   direkter Takt
//   1    0    0   Takt/256
//   1    0    1   Takt/1024
//   auch andere möglich
TCCR1B = 0b00000100;  // 16MHz/256 = 62,5KHz

// TCCR1C – Timer/Counter1 Control Register C
TCCR1C = 0b00000000;


// TCNT1H and TCNT1L – Timer/Counter1
TCNT1 = 0x8000;


//TIFR1 – Timer/Counter1 Interrupt Flag Register
//Bit 0 – TOV1: Timer/Counter1, Overflow Flag



//TIMSK1 – Timer/Counter1 Interrupt Mask Register
TIMSK1 = 0b00000001; //erlauben



// Interrupts aktivieren
    sei();

// Langeweile-Schleife in main:
  while (1) {
      PORTD ^= (1<<PD5); // LED grün
      _delay_ms(1000);
  }






Die ISR-Routine:

ISR(TIMER1_OVF_vect)  {
cli();
PORTB ^= (1<<PB0);      // blinkt ca 2x pro Sekunde, sollte aber vieeel 
mehr sein

    static uint8_t i = 0;
    TCNT1 = 0x8000;
/*
    i++;
    if (i == 100) {
    PORTB ^= (1<<PB0);
    i=0;
    };
*/
    sei();
  }


Ist irgendwo noch ein Vorteiler versteckt?

von spess53 (Gast)


Lesenswert?

Hi

>// blinkt ca 2x pro Sekunde, sollte aber vieeel mehr sein

Nein. Passt.

16MHz/256 = 62,5 kHz

62,5kHz/$8000 = 0,524 Hz

MfG Spess

von Joachim (Gast)


Lesenswert?

Blamabel...

von Joachim (Gast)


Lesenswert?

Ich werde den Rest des Tages mit Schämen verbringen.

Danke an euch.

von spess53 (Gast)


Lesenswert?

Hi

Ich schrieb:

>62,5kHz/$8000 = 0,524 Hz

Ist natürlich Mist

-> 62,5kHz/$8000 = 1,9Hz

MfG Spess

von Joachim (Gast)


Lesenswert?

Tja. Wir sind noch nicht fertig...


1. Ich kann machen was ich will, eine Änderung des Wertes
TCNT1 = 0x8000;
bewirkt genau gar nichts. Wie ist das möglich?

ISR(TIMER1_OVF_vect)  {
    cli();
    PORTB ^= (1<<PB0);      // blinkt ca 1x alle 2 sek
          TCNT1 = 0x1000;
    sei();
}

Es scheint als ob der Zähler immer wieder bei x0000 losläuft um bei 
xFFFF einen Interrupt auszulösen. Es gibt noch die Register TOP und MAX, 
die werde ich aber bei einem simplen LED-blinken mittels Timer ja wohl 
nicht brauchen - hoffe ich.

Jetzt kommt's aber noch dicker:
sei();
hat keinen Einfluß.
in einem alten Thread habe ich gelesen, daß der GCC je nach Einstellung 
den Code "optimiert". Ein Bug? Wie kann ich einstellen daß so etwas 
nicht passiert ohne 20 Seiten Dok zu lesen?



Mein Senf:
Also man kann über MPLAB und PICs ja sagen was man will... aber so ein 
Mist ist mir mit dem Compiler C18 in 5 Jahren in der default-Einstellung 
nicht einmal passiert...

von spess53 (Gast)


Lesenswert?

Hi

>1. Ich kann machen was ich will, eine Änderung des Wertes
>TCNT1 = 0x8000;
>bewirkt genau gar nichts. Wie ist das möglich?

Falsches Programm geflasht?

>Jetzt kommt's aber noch dicker: sei(); hat keinen Einfluß.

cli und sei haben in einer Interruptroutine eh nichts zu suchen. Das 
passiert automatisch. Das Auslösen eines Interrupts bewirkt ein cli und 
das reti am Ende ein sei.

MfG Spess

von Joachim (Gast)


Lesenswert?

>Das Auslösen eines Interrupts bewirkt ein cli und
>das reti am Ende ein sei.

Das hab ich zuerst auch geglaubt.
Der Gegenbeweis lieferte das Abschalten des Int-Freigabebits in TIMSK1.
Dann blieb er auch tatsächlich stehen, andernfalls nicht. Irgendwie 
passt das alles gar nicht zusammen.
Siehe auch hier:
Beitrag "Schwerer Bug in AVR-GCC 4.1.1"

von (prx) A. K. (prx)


Lesenswert?

Joachim schrieb:

> Hab versucht, mit meinem Rigol mir den Quarztakt anzuschauen; nichts
> feststellbar, null Pegel. Ist die Eingangskapazität an meinem
> Präzisionsgerät zu groß...?

Mit 1:1 Tastkopf darfst du keinem Quarz zu Leibe rücken, mit 10:1 sollte 
aber was zu sehen sein. Wobei der Low-Power-Oszillator empfindlicher ist 
als der Full-Swing-Oszillator. Wäre natürlich besser, am Ausgang des 
internen Inverters zu messen als am Eingang.

Die Eingangskapazität der üblichen passiven kapazitiven 10:1 Tastköpfe 
ist ziemlich unabhängig davon, ob auf dem DSO nun Rigol oder Agilent 
draufsteht.

von spess53 (Gast)


Lesenswert?

Hi

>Das hab ich zuerst auch geglaubt.
>...
>Siehe auch hier:
>Beitrag "Schwerer Bug in AVR-GCC 4.1.1"

Berührt mich eigentlich wirklich, da ich Assembler benutze. Und da 
klappt das wunderbar.

MfG Spess

von Joachim (Gast)


Lesenswert?

In die falsche Richtung gedacht. Da der Zähler ja aufwärts bis 0x0000 
zählt bewirkt ein kleinerer Wert eine größere Zeit. Uff.

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.