Hallo zusammen!
Auf einem ATmega644P habe ich zu Testzwecken eine Dauerschleife laufen
lassen, die nur PD6 umschaltet, sonst nichts.
Es ist ein 16 Mhz Quarz angeschlossen und die Fuses entsprechend
programmiert:
LFUSE: 0x0F7 (0xFF ändert nichts)
HFUSE: 0xD9
EFUSE: 0xFF
Mit dem Oszi habe ich an PD6 gemessen (gelb) und gleichzeitig den
Systemtakt an XTAL2 (blau).
Wie am Zeitcursor erkennbar, wird der Pin nach rund 125 ns umgeschaltet,
was einer Freuquenz von 8 MHz entspricht.
Nun frage ich mich, warum der Controller für so eine leichte Aufgabe
zwei Takte benötigt und nicht bloß einen.
Ist es möglich, dass er aus irgendwelchen Gründen nur mit 8 MHz taktet
oder braucht er wirklich zwei Takte dafür?
Grüße,
Vinc
Moment mal. Du schreibst:
PORTD &= ~(1 << PD6);
Ich vermute mal, daß das nicht einfach dem Komplementär-Befehl
entspricht.
Bei den PICs gibts da ein:
PORTDbits.PD7 ^= 1;
Vieleicht bietet er gcc etwas ähnliches an.
SBI und CBI brauchen auf dem ATMega 2 Takte (im Gegensatz zum ATTiny und
XMega):
http://www.atmel.com/images/doc0856.pdf
Seite 14 und Fußnote 5 auf Seite 15
Die OUT instruction braucht dagegen auch auf dem ATMega nur 1 Takt,
allerdings müssen vorher die Bits für den kompletten Port in einem
Register liegen.
Folgender asm-code müsste also 4 MHz auf PD6 ausgeben (mit Verzögerungen
für den rjmp nach jeweils 5 Perioden):
1
ldi r16, (1<<PD6)
2
ldi r17, 0
3
loop:
4
out PORTD, r16
5
out PORTD, r17
6
out PORTD, r16
7
out PORTD, r17
8
out PORTD, r16
9
out PORTD, r17
10
out PORTD, r16
11
out PORTD, r17
12
out PORTD, r16
13
out PORTD, r17
14
rjmp loop
Auf dem Mega644 müsste auch das Toggeln über schreiben ins PIN-Register
funktionieren:
Joachim ... schrieb:> Moment mal. Du schreibst:> PORTD &= ~(1 << PD6);> Ich vermute mal, daß das nicht einfach dem Komplementär-Befehl> entspricht.>> Bei den PICs gibts da ein:> PORTDbits.PD7 ^= 1;> Vieleicht bietet er gcc etwas ähnliches an.
Das ist nicht PIC. Das ist C.
PORTD ^= 1; führt beim AVR und beim PIC wahrscheinlch auch, aber zu
einem Read-Modify-Write, was wesentlich länger dauert als der eine
sbi/cbi.
Also das:
PORTD |= (1 << PD6);
PORTD &= ~(1 << PD6);
ist effektiver.
Beim AVR gibt es aber noch PINx |= 1; Da wird wieder der sbi eingesetzt.
Damit ist Toggle-Toggle zeitlich das gleiche wie Setzen-Löschen.
mfg.
RTFM schrieb:> SBI und CBI brauchen auf dem ATMega 2 Takte (im Gegensatz zum ATTiny und> XMega):
Das verstehst du falsch, jedenfalls was die ATtinys betrifft. Da steht:
"reduced core tinyAVR". Das sind nur die ganz, ganz kleinen (4,5,9,10).
Ab Tiny11 aufwärts kostet SBI/CBI 2 Takte.
Thomas Eckmann schrieb:> PORTD ^= 1; führt beim AVR und beim PIC wahrscheinlch auch, aber zu> einem Read-Modify-Write, was wesentlich länger dauert als der eine> sbi/cbi.PICs können XOR zum Port hin. Das ist also 1 Befehl, wenn die Maske
schon im Akku ist.
A. K. schrieb:> Thomas Eckmann schrieb:>> PORTD ^= 1; führt beim AVR und beim PIC wahrscheinlch auch, aber zu>> einem Read-Modify-Write, was wesentlich länger dauert als der eine>> sbi/cbi.>> Nope. PICs können XOR zum Port hin.
Nicht schlecht.
mfg.
A. K. schrieb:> Thomas Eckmann schrieb:>> PORTD ^= 1; führt beim AVR und beim PIC wahrscheinlch auch, aber zu>> einem Read-Modify-Write, was wesentlich länger dauert als der eine>> sbi/cbi.>> PICs können XOR zum Port hin. Das ist also 1 Befehl, wenn die Maske> schon im Akku ist.
Wieso im Akku?
XORLW ist doch mit immediate.
mfg.
A. K. schrieb:> Thomas Eckmann schrieb:>> XORLW ist doch mit immediate.>> Du willst nicht das Bit im Akku (W) toggeln, sondern im Port (f). Und> dafür brauchst du XORWF, nicht XORLW:> http://www.sprut.de/electronic/pic/assemble/befehle.html#xorwf
Kann ja keiner ahnen, daß W der Akku ist.
> Daumenregel: In einen PIC Befehl fester Länge passt entweder eine> Konstante oder eine Adresse. Aber i.d.R. nicht beides.
Ja. Ist logisch.
mfg.
Thomas Eckmann schrieb:> A. K. schrieb:>> Nope. PICs können XOR zum Port hin.> Nicht schlecht.
Das bringt mich auf die Frage, warum Vinc nicht einfach die
Port-Toggle-Funktion verwendet:
1
PIND|=1<<PD6
Hab jetzt nicht speziell im Datenblatt des ATmega644P geschaut, aber der
sollte das eigentlich auch können.
>> Hab jetzt nicht speziell im Datenblatt des ATmega644P geschaut, aber der> sollte das eigentlich auch können.
Kann er auch. Aber zeitlich bringt das nichts.
Um das gleiche zu erreichen, muss
Markus Weber schrieb:> Das bringt mich auf die Frage, warum Vinc nicht einfach die> Port-Toggle-Funktion verwendet:
Soweit ich das verstanden habe, ging es ihm nicht darum, ein 8MHz Signal
zu produzieren. Sondern um eine Erklärung für die 4MHz. Und die hat er.
Fall abgeschlossen.
>>Das ist nicht PIC. Das ist C.>PORTD ^= 1; führt beim AVR und beim PIC wahrscheinlch auch, aber zu
einem Read-Modify-Write, was wesentlich länger dauert als der eine
sbi/cbi.
Hmmmm...also ich bekomme auf einem 18F458 mit C18 das hier:
112: LEDPin ^= 1;
28AC 7E8C BTG LATD, 7, ACCESS
BTG ist:
BTG f, d, a Bit Toggle f 1 0111 bbba ffff ffff
Und er braucht dazu einen Takt.
>>>> Hab jetzt nicht speziell im Datenblatt des ATmega644P geschaut, aber der>> sollte das eigentlich auch können.>> Kann er auch. Aber zeitlich bringt das nichts.> Um das gleiche zu erreichen, muss>
1
PIND|=1<<PD6
> ja zweimal ausgeführt werden.
Sorry, Tippfehler von mir, ich meinte:
Joachim ... schrieb:> Hmmmm...also ich bekomme auf einem 18F458 mit C18 das hier:
Oder so, gibts aber erst im PIC18.
> Und er braucht dazu einen Takt.
Sagen wir mal einen Befehlszyklus. Was 4 Takte sind.
.include "m8def.inc" ; durch passendes config-file ersetzen
2
3
ldi r16, 0x01
4
out DDRD, r16
5
6
loop:
7
clr PORTD
8
ser PORTD
9
10
rjmp loop
eine taktmessung (einfach nur einen pin togglen) würde ich eher in ASM
schreiben - und clr/ser brauchen laut meinem instructionset-ausdruck nur
jeweils 1 takt. alternativ könnte man ein clr nach die initialisierung
packen und in der schleife nur mehr com ausführen.
hier sinds 3 takte pro schleifendurchlauf, der overhead kann durch
mehrfaches clr/ser einfach reduziert werden...
ok, ich habs auswendig geschrieben und mangels eines 644 auch nicht
getestet, aber das prinzip sollte klar sein ;-)
Ich meine, clr geht nur für r0 bis r31, nicht aber für I/O-Register.
Thomas Eckmann:
Du hast natürlich Recht, ich hatte den Beitrag von RTFM nicht bis zum
Ende gelesen.
Wow, das geht ja schnell hier :)
Wie es scheint, ist mit den zwei Takten pro Befehl in diesem Fall ja
alles in Ordnung.
Ich wollte auch keinen Taktgenerator bauen, sondern einfach nur checken,
ob der Controller mit dem richtigen Takt läuft.
Danke für die kompetenten Antworten!