AtMega2560: sbi, sbis Probleme

OP #3237037
Lesenswert?

Hallo.
Ich habe vor kurzem begonnen Atmel Mikrocontroller zu programmieren und 
einige erfolge mit Tiny, Mega8, Mega32 gehabt.
Jetz versuche ich einen Atmega2560 einen Pin mittels Timer ein und 
wieder aus zu schalten mit mässigem erfolg.
Kann mir jemand erklären warum sbis, sbic, sbi, cbi Bzw: sbrs, sbrc, 
sbr, cbr nicht funktionieren?
Hier die 3 Varianten die einfach nicht funktionieren wollen:

1.

 .nolist
 .include "m2560def.inc"
 .list
 .org  0x0000
                    rjmp    reset
 .org  0x002e
                    rjmp    timer0_overflow
timer0_overflow:
          sbis    porta,       1
          sbi     porta,       1
          sbic    porta,       1
          cbi     porta,       1
;
          ldi     r16,       250
          out     tcnt0,     r16
;
                    reti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2.

timer0_overflow:
          in      r16,         porta
          sbrs    r16,       1
          sbr     r16,       1
          sbrc    r16,       1
          cbr     r16,       1
          out     porta,     r16

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3.

timer0_overflow:
          lds     r16,       porta
          sbrs    r16,       1
          sbr     r16,       1
          sbrc    r16,       1
          cbr     r16,       1
          sts     porta,     r16

Die möglichkeit die funktioniert ist:


timer0_overflow:
          in      r16,       portg
          com     r16
          out     portg,     r16

Damit wäre ich ja auch zufrieden, aber beim Versuch Tastenkomginationen 
einzulesen sties ich auf das gleiche Problem mit sbrs, sbis, ......

Bitte kann mich jemand mit der nase auf meinen Fehler stossen. Steh 
irgendwie total auf der Leitung.
Gast #3237046
Lesenswert?

>Bitte kann mich jemand mit der nase auf meinen Fehler stossen. Steh
>irgendwie total auf der Leitung.

Du kannst portg nicht über sbi usw ansprechen.
Das Register liegt ausserhalb der Reichweite dieser Befehle.
Es geht nur mit in und out.
#3237060
Lesenswert?

Allen drei Versionen gemeinsam ist, dass deine prinzipielle Logik zum 
Pin-Toggeln nicht funktioniert. Spiel die vier Befehle doch einfach mal 
Schritt für Schritt für bei Fälle durch.

Bei 2 und 3 kommen dann noch weitere Probleme dazu, wie das 'lds', oder 
die Tatsache, dass hier
>          sbrs    r16,       1
>          sbr     r16,       1
unterschiedliche Bits in r16 angesprochen werden.
OP #3237066
Lesenswert?

Als erstes Danke fürs Interresse.

Diesen Hinweis hab ich auch schon hier im Forum gefunden, ausserdem 
liess AtmelStudio 6.1 mich das auch nicht Assemblieren.

Deshalb hab ich es mit PortA probiert und über Register R16. Das klappt 
auch nicht.
Ausserdem funktioniert das unter anderen umständen auch nicht mit 
Registern. sbr,cbr, sbrs, sbrc an R16,17,18,19,20 ausprobiert.

Müsste einige Bedingungen setzen für die mir beim besten Willen keine 
anderen Befehle als Sbis, sbrs, einfallen.
Gast #3237082
Lesenswert?

friedrich werdnik schrieb:

>           sbis    porta,       1
>           sbi     porta,       1
>           sbic    porta,       1
>           cbi     porta,       1

Ohohoh. Überlege doch bitte bloß mal, was da passiert!

Deine Absicht ist offensichtlich, das Portbit einmal pro Lauf zu 
toggeln.

Das funktioniert nur genau einmal und zwar auch nur dann, wenn PORTA1 
zuvor auf 1 intialisiert wurde. Danach (wenn PORTA1 beim Eintritt in die 
Routine 0 ist) passiert folgendes:

sbis springt nicht, also wird sbi ausgeführt->Portbit wird 1.

sbic springt ebenfalls nicht, also wird cbi ausgeführt->Portbit ist 
wieder 0.

D.h.: du hast gleich zweimal getoggelt und das Portbit war für nur genau 
zwei Takte auf 1.

Merke: Nicht jeder Code, der elegant aussieht, ist auch zwingend 
korrekt!
Gast #3237104
Lesenswert?

c-hater schrieb:

> Ohohoh. Überlege doch bitte bloß mal, was da passiert!

Hätte ich lieber zweimal machen sollen. Wie ich geschrieben habe, wäre 
es, wenn du wenigstens das gleiche Portbit setzen und prüfen würdest. 
Tust du aber nicht. Prüfen tust du Bit1, gesetzt wird aber Bit0.

Wenn du also geplant hattest, ein Input-Bit mit Zeitverzögerung an einem 
anderen Pin wieder auszugeben und dabei zu invertieren, dann ist der 
Code doch korrekt...
Gast #3237182
Lesenswert?

Hi

>Müsste einige Bedingungen setzen für die mir beim besten Willen keine
>anderen Befehle als Sbis, sbrs, einfallen.

Brauchst du überhaupt nicht. Um ein oder mehrere Bits in einem Register 
zu invertieren nimmt man den Befehl 'eor' :
1
  ldi r16,0b01010101
2
  ldi r17,0b00001111
3
  eor r16,r17   ;-> r16=0b01011010

Portpins lassen sich bei neueren AVRs, also auch beim ATMega2560, ganz 
leicht invertieren:
1
  ldi r16,0b00000001
2
  out (sts) *PINx* ,r16

Invertiert Bit0 vom Portx.

MfG spess
OP #3237223
Lesenswert?

c-hater schrieb:
> Wie ich geschrieben habe, wäre
> es, wenn du wenigstens das gleiche Portbit setzen und prüfen würdest.
> Tust du aber nicht. Prüfen tust du Bit1, gesetzt wird aber Bit0.


>           sbis    porta,       0
>           sbi     porta,       1
>           sbic    porta,       0
>           cbi     porta,       1

So würde ich die gleichen Bits abfragen und setzen? Hab ich das richtig 
verstanden?

Nach meinem verständnis sage ich in der ersten zeile wenn PB0 gesetzt 
ist springe zu zeile3.
Dann, wenn PB0 gesetzt ist springt das Programm nicht sondern macht in 
zeile 4 weiter und löscht das Bit.

Beim nächsten durchlauf ist PB0 nicht gesetz also springt das Programm 
nicht und macht in Zeile 2 weiter wo PB0 gesetzt wird. In Zeile 3 
springt das Programm weiter über Zeile4 da PB0 nicht gesetzt ist.

Das funktioniert aber nicht. Hab anscheinend einen gewaltigen 
Denkfehler.
OP #3237257
Lesenswert?

Spess53 schrieb:
> Ist Pin0 vom PortA ein Eingang oder Ausgang?

Sind alles Ausgänge.

MWS schrieb:
> Lad' Dir doch mal das AVR Instruction Set.


Werd mir nochmal das Instruction Set Einverleiben und mich mit den 
logischen Befehlen auseinandersetzen.

Vielen Dank erstmal für die hilfe an alle. Dachte ich hätte schon mehr 
verstanden. Etwas depremierend, aber da muss man durch.
#3237282
Lesenswert?

Oben herrscht ja grosse Verwirrung ueber die Bitnummern-Syntax:

SBI, CBI, SBIS, SBIC nehmen alle eine Bitnummer von 0 bis 7
SBI PORTA, 1
und
SBIS PORTA, 1 beziehen sich also auf dasselbe Bit!

Auch SBRS und SBRC nehmen eine Bitnummer von 0 bis 7

Ausnahme sind die SBR/CBR-Befehle, die eigentlich verkappte 
ORI/ANDI-Befehle sind (SBR r,k == ORI r,k; CBR r,r == ANDI r, 
(Komplement von k) ).

In Fall 1 geht also die Logik schief (wenn Bit auf 0, dann auf 1 setzen, 
sofort danach das auf 1 gesetzte Bit wieder loeschen).

In Fall 2 und 3 geht die Bitnummerierung schief wegen der anderen 
Bedeutung in den SBR/CBR-Befehlen.
OP #3237805
Lesenswert?

Oh Gott wie dumm von mir!
Muss mich jez mal outen.
Keine ahnung ob man Ports überhaupt mit Sbis oder Sbic abfagen kann, 
aber die Pins kann man abfragen.
So einfach wärs gewesen:

                    sbis    pina,      0
                    sbi     porta,     0
        sbic    pina,      0
              cbi     porta,     0

Funktioniert einwandfrei.

Schmeiss eindeutig zu schnell die Nerven weg.
Danke nochmal für die Hilfe. Werd mir mal die anderen Lösungsansätze 
ansehen die ich hier bekommen hab. Könnten vill das nächste Problem 
lösen bevor ein neuer Rekord in Nervenweitwurf aufgestellt wird.

Es is doch ein anderes arbeiten als auf der Baustelle als Schlosser.
Muss an meiner Arbeitseinstellung arbeiten. Viel hilt nicht immer viel 
und mit gewalt geht gar nix.
OP #3240663
Lesenswert?

So, trotz wenig Zeit hab ich doch einiges geschmökert (InstructionSet) 
und gegooglt und hier auf der Mikrocontoller seite gelesesen. Hab mein 
Problem mit :

Spess53 schrieb:
> Portpins lassen sich bei neueren AVRs, also auch beim ATMega2560, ganz
> leicht invertieren:
>   ldi r16,0b00000001
>   out (sts) PINx ,r16

gelöst und hab sogar meinen Denkfehler meiner ersten versuche kapiert.

Stefan Ernst schrieb:
> Wieso "da PB0 nicht gesetzt ist"? Im Satz davor schreibst du doch selbst
> "wo PB0 gesetzt wird".

Stefan Ernst schrieb:
> Aber nur mit Glück (wegen der Art wie das Sampeln der Pins in der
> Hardware realisiert ist). Der logische Ablauf dieser 4 Befehle ist immer
> noch genauso falsch, wie vorher.

So, und nun Weiter im Programm. Mal sehn was sich als nächstes für 
Probleme stellen.

P.s.: Danke nochmal für die nette Hilfe von allen! Echt Super Forum 
hier.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren