mikrocontroller.net

Forum: Compiler & IDEs atmega168: Minimale Impulsbreite am Portausgang?


Autor: John Go (johngo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie kurz kann denn der kürzestmögliche Impuls am Ausgang eines Ports 
sein, den ich per Software erzeugen kann?

Mein gemessener Impuls dauert 2 CPU-Takte. Aber, wenn ich das richtig 
verstanden habe, sollte ja eine Impulsdauer von 1 Takt möglich sein, 
weil die SBI und CBI Befehle laut Datenblatt nur 1 cycle brauchen.


Ich mach das so in C:

PORTD |= (1<<PORTD3);
PORTD &= ~(1<<PORTD3);

Im Disassembler schauts dann so aus:
+00000166:   9A5B        SBI     0x0B,3           Set bit in I/O 
register
+00000167:   985B        CBI     0x0B,3           Clear bit in I/O 
register

Am Logikanalysator schauts dann so aus:

Clck: 010101010101010101010101010
Port: 000000000111100000000000000

Also, der Port ist 2 Takte lang auf 1, und nicht nur einen.
Weiß jemand, woran das liegt könnte?

Danke,
Johngo

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß jetzt nicht, in welch komischem Datenblatt Du nachgesehen hast, 
aber in der Befehlssatzdokumentation steht recht eindeutig, dass cbi und 
sbi zwei Taktzyklen benötigen!

EDIT:
In meinem Datenblatt vom ATMega48/88/168 steht ebenfalls zwei 
Taktzyklen...

Autor: John Go (johngo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, genau, alles klar!
Da hab ich wohl in die Spalte vom xmega geschaut!

Danke!
Johngo

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gehts über einen Schreibzugriff auf PINx evtl schneller?

Im Atmega48-Datenblatt unter "12.2.2":

12.2.2 Toggling the Pin
Writing a logic one to PINxn toggles the value of PORTxn, independent on 
the value of DDRxn.
Note that the SBI instruction can be used to toggle one single bit in a 
port.

also
PIND=(1<<PIND3);
PIND=(1<<PIND3);

Mal ausprobieren, ob das schneller ist...

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, geht schneller. cbi/sbi müssen halt Lesen, verodern und 
zurückschreiben.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Benedikt K. wrote:
> Ja, geht schneller.
Wie das? Der Compiler macht sicher aus den beiden Zeilen von Ernst auch 
ein sbi (wie ja schon im Original). Und sbi braucht nunmal je 2 Takte, 
da ändert es auch nichts, wenn man auf PIND statt PORTD zugreift.

Es gibt afaik keine einzige Möglichkeit, per Software an einen Pin etwas 
in weniger als zwei Taktzyklen auszugeben.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Wie das? Der Compiler macht sicher aus den beiden Zeilen von Ernst auch
> ein sbi (wie ja schon im Original). Und sbi braucht nunmal je 2 Takte,
> da ändert es auch nichts, wenn man auf PIND statt PORTD zugreift.

Warum sollte er? Da steht doch kein "|=", sondern "=", und daraus macht 
der Compiler ein OUT, was 1 Takt braucht.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
> Warum sollte er? Da steht doch kein "|=", sondern "=", und daraus macht
> der Compiler ein OUT, was 1 Takt braucht.
Für ein out muss aber erst mal ein Wert in einem Rechenregister 
stehen, und der kommt mit ldi da rein, was der zweite Takt ist... (OK, 
im Prinzip hast Du natürlich Recht: Das ldi muss nur einmal ganz am 
Anfang gemacht werden. Demnach haut es natürlich doch hin...)

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes M. wrote:
> Für ein out muss aber erst mal ein Wert in einem Rechenregister

Das muss man aber nur einmal machen, nicht jedesmal.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler macht aus dem Sourcecode von Ernst:
LDI     R24,0x08
OUT     0x10,R24
OUT     0x10,R24

Und damit hat man einen Puls mit einer Breite von einem Takt.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
> Johannes M. wrote:
>> Für ein out muss aber erst mal ein Wert in einem Rechenregister
>
> Das muss man aber nur einmal machen, nicht jedesmal.
Richtig, siehe oben...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry. Habe ich das überlesen, oder hast du nochmal editiert?

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:
> Sorry. Habe ich das überlesen, oder hast du nochmal editiert?
Sagen wir es so: Ich habe mein Privileg als registrierter User schamlos 
ausgenutzt...

Autor: John Go (johngo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und das funktioniert auch beim Zugriff aufs normale PORTD 
Schreibregister: nur 1 Takt.

portD = PORTD;
hibit = portD | (1 << PORTD3);
lobit = portD & ~(1 << PORTD3);

PORTD = hibit;
PORTD = lobit;

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
John Go wrote:
> Und das funktioniert auch beim Zugriff aufs normale PORTD
> Schreibregister: nur 1 Takt.
>
> portD = PORTD;
> hibit = portD | (1 << PORTD3);
> lobit = portD & ~(1 << PORTD3);
>
> PORTD = hibit;
> PORTD = lobit;
Jo, damit veränderst Du aber jedes Mal auch alle anderen Bits im 
Portregister, wenn PORTD sich in der Zwischenzeit ändert, und musst 
außerdem darauf spekulieren, dass der µC noch genügend Register frei 
hat, um die beiden Konstanten in Rechenregistern zu lassen. Der 
ATMega168 hat extra für solche Sachen die Pin-Toggle-Funktion durch 
Schreibzugriff auf PINx, also warum nutzt Du sie nicht?

Autor: John Go (johngo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau, jetzt hab ich erst die Pin-Toggle Funktion verstanden.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.