Moin,
ich habe einen ATmega16 mit einem 16 Mhz quarz (2x22pF). Nach langen
rumprobieren läuft er jetzt auch. Ich habe eine LED zu Testen
angeschlossen und sie blinken lassen. Nach meinem Oszi sind es 4,3xxx
Mhz.
Ich kann leider den den takt nicht direkt an XTAL2 messen da er dann
aus geht (nicht mehr schwingt).
Meine Vermutung ist, das es am Programm liegt. Sieht wie volgt aus:
1
ISR(TIMER0_OVF_vect)
2
{
3
TCNT0=245;// 10 Takte warten
4
if(PORTD==231)
5
{
6
PORTD=247;
7
}
8
else
9
{
10
PORTD=231;
11
}
12
}
Ist nur die Interrupt routine die die LED ein bzw aus schaltet.
(Prescaler ist aus)
Wandelt WINAVR das evtl so "scheisse" um das es er für die If anweisung
die restlichen Zeit benötigt?? (Gibt es einen eine Möglichkeit in C das
Komplement des Port Pins direkt zu bilden).
Oder liegt es am Quarz bzw. bzw an der Verdrahtung Masse nicht gleich
masse usw. (Er liegt allerding direckt an XTALx). Ich kenne mich zwar
nicht mit quarzen aus aber ich denke mal das das nicht möglich ist das
der Oszillator dann nur mit 4 Mhz Schwingt.
MFG
Was glaubst Du, wie lange es von dem Moment, in dem das Interrupt Flag
gesetzt wird, dauert, bis der Code im Interrupt-Handler ausgeführt wird?
Das ist im Vergleich zu den 10 Takten, die Du haben willst, ne halbe
Ewigkeit...
BTW:
Die CPU braucht 4 Takte, um den Programmzähler auf dem Stack zu sichern,
das I-Bit zu löschen und in den Vektor zu springen. Der Sprung aus dem
Vektor zum eigentlichen Interrupt-Handler braucht (bei AVRs mit mehr als
8 KiB Flash, also auch beim Mega16) 3 Takte. Dort angekommen, sichert
der Compiler erst mal das SREG (in und push, macht noch mal 2 Takte),
einige wichtige Rechenregister (mindestens 3-4 Takte, eher mehr). Jetzt
kannste ja mal nachzählen... Selbst in Assembler geht das nicht!
Also liegt es einizg und allein an der Interrupt routine ?!?
Hab mich noch nicht sehr lange mit den Timern beschäftigt allerdings
meine ich im Datenblatt gelesen zu haben das mann eine PWM bzw
einen Funktionsgenerator aufbauen kann.(Läuft dann meine ich auch mit
Interrupts)
Aber läuft dann wahrscheinlich nur mit geringeren Frequenzen als mit
nahezu 16Mhz.
Der link geht leider nicht :(
MFG
Wenn Du nur einen Pin toggeln willst, dann geht das mit den Frequenzen
nur hardwaremäßig (Timer im CTC-Modus, OC0 als Ausgang)! Mit Interrupts
kannste das komplett vergessen. Und nen Timer-Preload macht man beim AVR
überhaupt nicht! Dafür gibts schließlich die Compare-Einheiten.
Und noch was:
Gewöhne Dir AUF JEDEN FALL wieder ab, Bitmasken für Ports als
Dezimalwerte zu schreiben! Das kann keine Sau lesen. Muss man immer erst
rechnen. Entweder hexadezimal oder (falls Dir das lieber ist) binär.
Wusste leider nicht wie ich dem Kompiler das Binärformat beibringe.
Also 0x.. oder bx0101 das ist mein Problem.
Ich werde das mal mit dem Timer1 testen ich glaube das ist der einzige
bei dem diese geht melde mich dann nochmal :)
MFG
elvis wrote:
> Ich möchte eigendlich nur wissen wie schnell der Quarz schwing, ob> errichtig funktioniert.> Gibt es da ne möglichkeit das zu messen.
Wenn 16 MHz draufstehen und Du mit dem obigen Programm auf das oben
beschriebene Verhalten kommst, dann scheint der µC immerhin mit den 16
MHz zu laufen.
Also ein Zustand (0,1) hält ca. 2,3us Sekunden an. Ein "Takt"
(Periodendauer sind 62.5 ns. Macht also 36,8 Takte. Also minus meiner 10
noch 26,8 bearbeitungstakte. Könnte ja hinkommen.
MFG
> Ich möchte eigendlich nur wissen wie schnell der Quarz schwing, ob> errichtig funktioniert. Gibt es da ne möglichkeit das zu messen.
Mit was misst Du denn? Eigentlich sollte der nicht aufhoeren zu
schwingen... zumindest nicht wenn Du mit einem Oszi misst - OK die
Tastkoepfe haben eine Kapazitaet allerdings meine ich dass das kein
gutes Zeichen ist. Wie hast Du denn den Quarz in Deinem Layout
platziert? Wo sind die Lastkondenstatoren?
Gruesse,
Michael
elvis wrote:
> Ich möchte eigendlich nur wissen wie schnell der Quarz schwing, ob> errichtig funktioniert.> Gibt es da ne möglichkeit das zu messen.
Und warum machst du dir dann das Leben so dermassen schwer?
Nimm den 16 Bit Timer her und lass den komplett durchzählen.
16000000 / 65536 = 244 Hz
Ist noch ein bischen zu hoch, also in der Overflow ISR nochmal
durch 122 teilen und eine LED in diesem Takt umschalten.
uint8_t Counter;
ISR( TIMER1_OVF_vect)
{
Counter++;
if( Counter == 122 ) {
Counter = 0;
PORTD ^= ( 1 << PD4 );
}
}
Wenn dein Quarz jetzt exakt mit 16 Mhz schwingt, dann leuchtet
deine LED exakt im Sekundentakt auf. Das kann man auch mit
friem Auge sehen.
So ich habe jetzt nochmal ein bischen rumgelötet um mein Board mit dem
STK500 über ISP programmieren zu können.
Ich lasse jetzt den Timer 255 Schritte machen dann kommt der overflow
Interrupt. Rechnerisch ergibt sich eine Zeit von 15,95xxxx us und mein
Oszi zeigt genau das an. Also der Quarz läuft mit 16Mhz.
Das die ISR jetzt noch 20 oder mehr Takte benötigt um den Port Pin zu
ändern ist egal da das ja immer die Gleiche Zeit in anspruchnehmen
sollte.
Zum Layout: Der Quarz sitzt direkt an den XTALx pins sowie die die C's.
Die Masse habe ich zum Massepins des ATmega gezogen damit seine masse
auch die der Kondensatoren ist.
Danke nochmal für die hilfe.
MFG
elvis
Kleiner Tipp: Im AVRStudio simulieren! Solche Timing-Aspekte kann man so
nämlich ganz nett und sehr genau beobachten. Notfalls kannst du dir
sogar den erzeugten Assemblercode ansehen.
> Die CPU braucht 4 Takte, um den Programmzähler auf dem Stack zu> sichern, das I-Bit zu löschen und in den Vektor zu springen.
Vorher muß er den aktuell ausgeführten Befehl noch fertigmachen.
> Der Sprung aus dem Vektor zum eigentlichen Interrupt-Handler braucht> (bei AVRs mit mehr als 8 KiB Flash, also auch beim Mega16) 3 Takte.> Dort angekommen, sichert der Compiler erst mal das SREG (in und push,> macht noch mal 2 Takte),
Um das SREG in ein Register lesen zu können, muß er das vorher erstmal
sichern. Außerdem macht ein Push alleine schon zwei Takte. Somit sind
wir hier insgesamt nicht bei 2, sondern bei 5 Takten.
> einige wichtige Rechenregister (mindestens 3-4 Takte, eher mehr).
Zwei pro Register.
>Ich möchte eigendlich nur wissen wie schnell der Quarz schwing, ob>errichtig funktioniert.>Gibt es da ne möglichkeit das zu messen.
Klar. Die einfachste Möglichkeit wäre, Deinen Controller dieses
Assemblerprogramm ausführen zu lassen:
1
_Loop:
2
ldi r16, 0
3
out PORTB, r16
4
5
nop
6
nop
7
nop
8
9
ldi r16, 1
10
out PORTB, r16
11
12
nop
13
rjmp _Loop
Wie Du direkt nachzählen kannst, benötigt es vom ersten "out" bis zum
zweiten genau fünf Taktzyklen, und vom zweiten bis zum ersten ebenfalls
fünf ("rjmp" nimmt zwei Zyklen in Anspruch, alle anderen Instruktionen
einen). Somit toggelt Pin 0 von Port B mit genau *** 1/10 *** der
Quarzfrequenz. Frequenzzähler anschließen, ablesen - fertig.