Forum: Mikrocontroller und Digitale Elektronik AtMega2560: sbi, sbis Probleme


von Fritzl W. (friz)


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.

von holger (Gast)


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.

von Stefan E. (sternst)


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.

von Fritzl W. (friz)


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.

von Fritzl W. (friz)


Lesenswert?

Stefan Ernst schrieb:
> 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.

Aha, wiso andere Bits? In beiden fällen Bit 1 in R16 oder hab ich da was 
falsch verstanden?

von MWS (Gast)


Lesenswert?

friedrich werdnik schrieb:
> Deshalb hab ich es mit PortA probiert und über Register R16. Das klappt
> auch nicht.

PortA ist 0x20 und damit oberhalb 0x1F, die Grenze für diese Opcodes. 
Lad' Dir doch mal das AVR Instruction Set.

von Stefan E. (sternst)


Lesenswert?

friedrich werdnik schrieb:
> Stefan Ernst schrieb:
>> 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.
>
> Aha, wiso andere Bits? In beiden fällen Bit 1 in R16 oder hab ich da was
> falsch verstanden?

In der zweiten Zeile ist es Bit 0.

von c-hater (Gast)


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!

von c-hater (Gast)


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...

von Spess53 (Gast)


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

von Bastler (Gast)


Lesenswert?

Atmega2560 toggled seine PORTn-Pins durch schreiben einer 1 in das 
entsprechende Bit in PINn. 1..2 Takte, je nach Lage des PINn-Registers.

von Bastler (Gast)


Lesenswert?

Spess war schneller;-)

von Fritzl W. (friz)


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.

von Bastler (Gast)


Lesenswert?

C-hater hasst C und macht lieber alles ASM.
Auch das, was die Hardware selber kann!

Versuch das Schreiben einer Eins in PINn.

von Spess53 (Gast)


Lesenswert?

Hi

>           sbis    porta,       0
>           sbi     porta,       1

Ist Pin0 vom PortA ein Eingang oder Ausgang?

MfG Spess

von Fritzl W. (friz)


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.

von Tassilo H. (tassilo_h)


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.

von Stefan E. (sternst)


Lesenswert?

friedrich werdnik schrieb:
> 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.

Wieso "da PB0 nicht gesetzt ist"? Im Satz davor schreibst du doch selbst 
"wo PB0 gesetzt wird".

von Fritzl W. (friz)


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.

von Stefan E. (sternst)


Lesenswert?

friedrich werdnik schrieb:
> Funktioniert einwandfrei.

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.

von Fritzl W. (friz)


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.

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.