ATmega2560-Assembly-Pin-Lese- und Vergleichslogikproblem

Ich entschuldige mich, wenn meine Frage vage war.

Programm: Atmel Studio 6

Ich versuche, ein Programm zu erstellen, das in eine Schleife eintritt, aus der es nur ausbricht, wenn ein Pin niedrig wird.

;Set PA0 high before entering loop checking for low
CBI DDRA,DDA0       ;PA0 to input
SBI PINA0,0         ;PA0 pull-up enable
;PA0 is now input & high

chklow: inc r16     ; Increase r16
in r18,PORTA0       ; Copies PINA0 to r18
cpi r18,0           ; Compares r18 to 0
brne chklow         ; Branch if PA0 is not low
nop             ; Loop exit (do nothing)

Was passiert ist, dass, wenn ich PINA0 setze, PORTA0 hoch geht. Ich denke, das ist gut, es ist, als hätte ich einen Knopf gedrückt, der mit PINA0 verbunden ist.

Jetzt betrete ich die Schleife, und ich habe mein E/A-Anzeigefeld oben, sodass ich sehe, dass PORTA0 eingestellt ist. Dies ist das Feld ganz rechts in PORTA.

Aber "in r18, PORTA" macht r18 nicht zu '1' ... es bleibt 0.

Und so wird das Z-Bit auf 1 gesetzt, weil der Vergleich erfolgreich war und die Verzweigung nicht auftritt.

Was ist falsch? Ich möchte, dass die Schleife endlos fortgesetzt wird, bis ich PORTA0 niedrig mache.

EDIT: Ich habe es jetzt geändert, mit Ihrem Rat:

CBI DDRA,DDA0           ;PA0 to input
SBI PORTA0,0            ;PA0 pull-up enable


chklow:
in r18,PORTA        ; Copies PINA0 to r18
cpi r18,0x00        ; Compares r18 to 0
brne chklow         ; Branch if PA0 is not low
nop             ; Loop exit (do nothing)

Was ich also geändert habe, war, dass ich das gesamte PORTA-Byte kopiert habe, anstatt zu versuchen, das PORTA0-Bit zu kopieren, was nicht möglich ist (zumindest mit meiner Methode), und jetzt funktioniert es. Danke ;)

Ich weiß auch, dass dies eine schmutzige Lösung ist, weil es fehlschlägt, wenn irgendein Bit in Pin A gesetzt ist, aber ich kann das später verfeinern, dies ist ein funktionierender Prototyp: D

Warum stimmen Ihre Kommentare nicht mit Ihrem Code überein?
Ich dachte, sie taten es. Können Sie darauf hinweisen, welcher Kommentar nicht übereinstimmt?
in r18,PORTA0 ; Copies PINA0 to r18
@IgnacioVazquez-Abrams Ah ok. Nun, Sie sehen, ich habe mir gedacht, wenn ein Port '1' ist und der Pin zum Lesen des Werts des Ports dient, dann ist das Lesen des Pins gleichbedeutend mit dem Lesen des Ports. Liege ich mit diesem Verständnis falsch?

Antworten (1)

Paar Dinge, die mich die Stirn runzeln lassen:

SBI PINA0,0         ;PA0 pull-up enable

Laut Datenblatt:

Jedem Port sind drei E/A-Speicheradressen zugeordnet, jeweils einer für das Datenregister – PORTx, das Datenrichtungsregister – DDRx und die Port-Eingangspins – PINx. Die E/A-Position der Porteingangsstifte ist nur lesbar, während das Datenregister und das Datenrichtungsregister lesbar/schreibbar sind. Das Schreiben einer logischen Eins in ein Bit im PINx-Register führt jedoch zu einem Umschalten des entsprechenden Bits im Datenregister. Darüber hinaus deaktiviert das Pull-up Disable – PUD-Bit in MCUCR die Pull-up-Funktion für alle Pins in allen Ports, wenn es gesetzt ist.

Um den Pullup zu aktivieren, sollten Sie PORTAnot to schreiben PINA0. Beachten Sie auch den Unterschied PINA0und PINAin Ihrem Code. Sie können kein einzelnes Bit von einem IO-Port lesen, Sie müssen das ganze Byte lesen. ANDAnschließend können Sie mit , SBRCoder ein oder mehrere Bits im gelesenen Byte prüfen SBRS.

nop             ; Loop exit (do nothing)

Verwenden Sie nicht nop"nichts tun", da der Mikrocontroller mit der nächsten Anweisung im Flash fortfährt, die alles sein kann , einschließlich einer Anweisung aus einem vorherigen Programm, das sich im Flash befand, wenn es nicht überschrieben wurde. Da kann alles passieren.

Während das Schreiben auf PINxdiese Weise zufällig funktionieren kann (da das Schreiben auf PINxdie Bits in invertiert PORTx), stimme ich zu, dass Sie es nicht auf diese Weise tun sollten.
@IgnacioVazquez-Abrams Ein entsprechendes Zitat aus dem Datenblatt hinzugefügt.
Ja, ich habe das Datenblatt gelesen und 1 an Pin gesendet, weil es, wie es heißt, den Port umschaltet. Aber warum bewirkt "in r18, PORTA0" nicht, dass der Wert von PORTA0, der 1 ist, zu r18 geht ...?
@jippie, ich habe es jetzt geschafft, stattdessen an PORTA zu schreiben. Macht das gleiche, aber wie du sagst, sauberer. OK. Wie kann ich jetzt den Wert von PORTA0-Bit auf r18 bringen, damit ich ihn dann mit '0' vergleichen kann?
@DrOnline Woher wissen Sie, dass es nicht funktioniert? Ihr Code macht nach dem nichts Nützlichesbrne
@jippie Nun, ich kann sehen, dass das Bit ganz links in PORTA gesetzt ist, das ist PORTA0. Also PORTA0=1, wie ich es verstehe. Dann komme ich zu der Zeile "in r18,PORTA0", und r18 bleibt '0' .... Warum wird es nicht '1'?
@jippie Um klar zu sein, was ich will: Ich möchte PORTA0 hoch setzen. Geben Sie dann eine Schleife ein, die den Wert von PORTA0 nach r16 kopiert, dann diesen Wert mit '0' vergleicht und die Schleife nicht verlässt, bis PORTA0 auf '0' gesetzt wurde.
Sie müssen das ganze Byte von lesen PORTAund dann Bit0 testen, zum Beispiel mit AND R18,0x01. Sie können nicht direkt ein einzelnes Bit von einem Port lesen.
Eine Alternative zum Testen mit ANDsind die Anweisungen SBRCund SBRS.
@jipi Danke. Ich wusste nicht, dass ich das ganze Byte lesen musste. Vielen Dank. Ich kann noch nicht positiv abstimmen, weil ich keinen Repräsentanten habe, oder ich würde;)
Oh, und das Nop, nun, ich beabsichtige, mehr Programm darunter hinzuzufügen, also wartete es darauf, dass ich die Dinge erweitere :D