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?
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?
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.
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?
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...
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
>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"
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.
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