Forum: Mikrocontroller und Digitale Elektronik PINx zu schnell Kniffelig.


von Karsten K. (karsten42)


Lesenswert?

Moin Moin,

Kniffelig weil folgendes nicht geht und ich frage mich wieso...
1
//wait for MOSI becomes HIGH
2
FL_CS_LOW; // Reset PB0
3
NOP();
4
while(!(PINB & (1<<PINB6)));
5
FL_CS_HIGH; // Set PB0

ABER dies geht:
1
//wait for MOSI becomes HIGH
2
FL_CS_LOW;  // Reset PB0
3
NOP();
4
while(!(PINB & (1<<PINB6)));
5
FL_CS_HIGH;  // Set PB0

Die fallende Flanke vom reset des PB0 lässt das high auf PB6 ebenfalls 
auf LOW fallen. Im oberen code, ist in der while() schleife PB6 noch?? 
HIGH.

Wieso ist das so und kann man das ohne NOP() umgehen??

Beste Grüße
Karsten

P.S. Hier der "klartext" aus dem lss file....
1
  //wait for MOSI becomes HIGH
2
    FL_CS_LOW;
3
     816:  2c 98         cbi  0x05, 4  ; 5
4
    NOP();
5
     818:  00 00         nop
6
    while(!(PINB & (1<<PINB6)));
7
     81a:  1e 9b         sbis  0x03, 6  ; 3
8
     81c:  fe cf         rjmp  .-4        ; 0x81a <write_4K+0x80>
9
    FL_CS_HIGH;
10
     81e:  2c 9a         sbi  0x05, 4  ; 5
11
     820:  22 96         adiw  r28, 0x02  ; 2
12
     822:  ff 24         eor  r15, r15
13
     824:  f3 94         inc  r15

von Possetitjel (Gast)


Lesenswert?

Karsten K. schrieb:

> Kniffelig weil folgendes nicht geht [...]
>
> ABER dies geht: [...]

Wo ist der Unterschied?

von Arduinoquäler (Gast)


Lesenswert?

Karsten K. schrieb:
> FL_CS_LOW;  // Reset PB0
------------^-------
hier ist ein Space mehr dazwischen.

> FL_CS_HIGH;  // Set PB0
-------------^-------
hier ist auch ein Space mehr dazwischen.

von Possetitjel (Gast)


Lesenswert?

Arduinoquäler schrieb:

> Karsten K. schrieb:
>> FL_CS_LOW;  // Reset PB0
> ------------^-------
> hier ist ein Space mehr dazwischen.
>
>> FL_CS_HIGH;  // Set PB0
> -------------^-------
> hier ist auch ein Space mehr dazwischen.

Stimmt. Danke.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Vermutlich fehlt dem TE jedoch einfach nur das Studium des Abschnitts
“Reading the PIN value” im Datenblatt seines AVRs.

von Arduinoquäler (Gast)


Lesenswert?

Possetitjel schrieb:
> Stimmt. Danke.

Das muss den Compiler bzw Präprozessor natürlich verwirren.

von Stefan F. (Gast)


Lesenswert?

Nu hört doch auf, ihn zu veräppeln.

Geht es eventuell darum, dass du den Ausgang PB0 mit dem Eingang PB1 
verbunden hast und erwartest, dass eine Änderung von PB0 sofort danach 
an PB1 sichtbar wird?

Das geht nicht, denn:

1) Nach Absetzen des Befehls, PB0 auf Low zu setzen, dauert ein einige 
Nanosekunden, bis der Ausgang wirklich auf Low geht.

2) Der Eingang braucht auch einige Nanosekunden, bis er das erkennt.

3) Die Eingänge und Ausgänge sind synchron getaktet.

Wenn Du ein AusgangsRegister beschreibst, erscheint der neue Status am 
Ausgangspin erst beim nächsten I/O Takt. Genau in diesem Moment werden 
die Eingänge ins PIN Register geladen.

Deswegen ist ein NOP dazwischen notwendig.

von Stefan F. (Gast)


Lesenswert?

1
PORTB=Wert --> I/O Takt --> Ausgangs-Pin Ändert sich -----+
2
                                                          |
3
                                                       einige ns delay
4
                                                          |
5
PINB lesen <-- I/O Takt <-- Eingangs-Pin Ändert sich <----+

Und nun bedenke, dass die beiden I/O Takte zeitgleich stattfinden, 
sofern zwischen dem Schreiben und Lesen kein NOP befehl steht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan Us schrieb:
> 1) Nach Absetzen des Befehls, PB0 auf Low zu setzen, dauert ein einige
> Nanosekunden, bis der Ausgang wirklich auf Low geht.
>
> 2) Der Eingang braucht auch einige Nanosekunden, bis er das erkennt.

Nein, das sind keine Nanosekunden, also keine Effekte irgendeines
propagation delays, sondern das ist voll synchron.  Selbst, wenn du
den Controller mit 32 kHz taktest, brauchst du den NOP.  Der Grund ist,
dass das Abtasten des Eingangspins für den IN-Befehl erfolgt, bevor
der OUT-Befehl seine Veränderung am Ausgang bewirkt hat.  Dies ist
notwendig, da der Eingangspin auf den IO-Takt synchronisiert werden
muss und seine Information aber zu dem Zeitpunkt, da der IN-Befehl
abgearbeitet wird, bereits stabil (und CPU-Takt-synchron) bereitgestellt
worden sein muss.  Schließlich soll der IN ja nicht noch einen
WAIT-Zyklus brauchen.

Steht alles im Datenblatt …

von Possetitjel (Gast)


Lesenswert?

Stefan Us schrieb:

> Nu hört doch auf, ihn zu veräppeln.

Okay... hast Du eine Erklärung dafür, dass die erste Version
mit dem NOP nicht geht, während die zweite Version mit dem
NOP funktioniert?


(Und - nein, meine Frage oben enthält keinen logischen Fehler.)

von Max D. (max_d)


Lesenswert?

Possetitjel schrieb:
> Okay... hast Du eine Erklärung dafür, dass die erste Version
> mit dem NOP nicht geht, während die zweite Version mit dem
> NOP funktioniert?

Reproduzierbar ?
Oder jedes Ding einmal probiert ?
Identische HW?
Identische Rest-SW ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Possetitjel schrieb:
> hast Du eine Erklärung dafür, dass die erste Version mit dem NOP nicht
> geht, während die zweite Version mit dem NOP funktioniert?

Copy&paste-Fehler.  Wird aber nur daraus deutlich, dass er fragt,
ob man das ohne NOP umgehen könnte.

von Karsten K. (karsten42)


Lesenswert?

OhhhOhhhh!!

Entschuldigt bitte:

Copy und Paste!

Im ersten Falle ist KEIN NOP();

Danke Jörg für die Erklärung. Und Ja! es steht viel in vielen 
Datenblättern und leider ist manches eben zwischen den Zeilen verborgen 
( so zumindest mein Eindruck ).

Zumindest bin ich jetzt schwer beruhigt, das hier keine merkwürdigen 
Laufzeitfehler oder sonstwas ominöses am Werk ist.

Vielen Dank für eure lustigen und erhellenden Beiträge!

Gruß
Karsten ( DG2LAK )

von Stefan F. (Gast)


Lesenswert?

Ja genau, es kommt überhaupt nicht auf die Taktfrequenz an und auch 
nicht, wieviele Nanosekunden propagation delay nun vorhanden sind. 
Entscheidend ist, dass überhaupt ein Delay vorhanden ist - was 
physikalisch wohl kaum vermeidbar ist.

Der eine Taktimpuls, der die Änderung am Ausgang aktiviert, der liest 
auch den Pegel am Eingang ein. Und da das Signal nicht ohne Zeit vom 
Ausgang zum Eingang kommen kann, braucht man einen NOP dazwischen, so 
dass das Lesen des Eingangs eine Takt später stattfindet.

von Pedant (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Nein, das sind keine Nanosekunden

Warum? Selbst ein Tag 8.64*10^13 Nanosekunden. Ungefähr.

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.