Bitweise auf PORT Ausgeben

Gast #1181744
Lesenswert?

Hi,
die Frage ist mir ja fast schon peinlich, aber gibt es eine EINFACHE 
(2-3 Zeiler) Möglichkeit, die Bits 6 und 7 einer Variable (in meinem 
Fall "counter") auf den PORTB PB0 und PB1 auszugeben (also 6->PB0, 
7->PB1), OHNE PB2...PB7 zu beeinflussen?

Ich könnte jetzt pruefen, ob die Bits gesetzt sind und je nach dem an 
eine Sprungmarke springen und den entsprechenden Port mit SBI bzw. CBI 
setzen bzw. loeschen.

Aber das muss doch einfacher gehen oder nicht!?

Sorry fuer meine auf-dem-Schlauch-Steherei ;-)

Danke
Franz
#1181756
Lesenswert?

Franz M. wrote:
> ach noch vergessen: Ich progge in Assembler

die beiden Bitposition von counter mittels einer AND Maskierung 
freistellen. Um 6 Positionen nach unten schieben. PORTB einlesen, PB0 
und PB1 definiert auf 0 setzen. Die vorher geschobenen beiden Bits mit 
einem Oder drüberschreiben. Das Resultat wieder auf PORTB ausgeben.

->   die Lösung mit cbi/sbi dürfte einfacher sein. Vor allem das 
Schieben um 6 Positionen wird viel Zeit verschlingen.
Persönliche Seite #1181800
Lesenswert?

Die Lösung wird auch davon abhängen, wo man atomar sein will/muss

-- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände 
vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port 
schreiben und sbi/cli ist obsolet

-- wenn man intern atomar sein muss, weil auch eine ISR auf dem Port 
rumnudelt, dann ist ein Lesen/Schreiben des Ports problematisch: Es muss 
dann in cli/sei o.ä. oder man nimmt die sbi/cli-Lösung.

Johann
Gast #1181820
Lesenswert?

Ok habs jetzt so. nicht schoen, nicht schnell, aber es geht:
1
  swap  count3
2
  lsr    count3
3
  lsr    count3
4
  cbi    PORTB, 0
5
  cbi    PORTB, 1  
6

7
  in    temp, PORTB
8
  or    temp, count3
9
  out    PORTB, temp

Es fehlt einfach der richtige Befehl :(
(Bit setzen in Abhaengigkeit eines anderen Bits oder sowas :P )

Danke fuer eure Hilfe!
Gast #1181864
Lesenswert?

Ich merke grade, dass das oben von mir ja gar nicht funktioniert!
Die nach dem SWAP sind die 4 low-bits ja im high-nibble und werden dann 
mit ver-odert.

Aber man kann ja eh nicht "gleichzeitig" beide PBs aendern, ohne wie 
gesagt auf den ganzen PORTB zu schreiben. Also hat man immer einen 
"undefinierten" Zustand zwischendurch.
Oder halt ziemlich großen Aufwand....

Ich mach jetz erstmal Fruehstueck und danach schreib ich euch meine 
Loesung
#1181874
Lesenswert?

Stefan Ernst wrote:
> Über die ori-Zeile würde ich nochmal nachdenken. ;-)

Grrrrr. Brauch gleich noch einen Kaffee.
Beim Überlegen war das noch anders. Aber die Finger haben dann
ganz was anderes geschrieben.

  swap  count3
  lsr   count3
  lsr   count3
  in    temp, PORTB
  andi  count3, 0x03
  andi  temp, 0xFC
  or    temp, count3
  out   PORTB, temp
#1181882
Lesenswert?

Johannes M. wrote:
>
1
> .def counter = r17
2
> 
3
> in r16, PORTB
4
> bst counter, 6
5
> bld r16, 0
6
> bst counter, 7
7
> bld r16, 1
8
> out PORTB, r16
9
>


Das ist trickreich :-)
Endlich hab ich mal verstanden, was so typische Einsatzfälle für das 
T-Flag sind.

Merci für den Denkanstoss!
#1181906
Lesenswert?

Karl heinz Buchegger wrote:
> Das ist trickreich :-)
> Endlich hab ich mal verstanden, was so typische Einsatzfälle für das
> T-Flag sind.
Naja, ich finde, bst und bld fristen zu Unrecht ein Nischendasein. 
Ich vermute fast, dass sich selbst erfahrenere Assembler-Programmierer 
der Existenz dieser beiden Befehle oft übehaupt nicht bewusst sind. Ich 
finde die aber oft ziemlich praktisch. Wie oft hat man das Problem, dass 
man Bitzustände irgendwo herbekommt und in einer völlig anderen 
Reihenfolge woanders augeben muss. Und wie man sieht, gibt es bei 
wenigen Bits sogar bei Beibehaltung der Reihenfolge Codegrößen- und 
Performance-Vorteile.

Ich musste es aber auch erst hinschreiben, um zu sehen, dass es 
tatsächlich kürzer ist als die anderen Vorschläge. Habe schon ziemlich 
lange nichts ernsthaftes mehr in Assembler programmiert...

> Merci für den Denkanstoss!
Keine Ursache. Weiß nicht, wie oft ich schon Denkanstöße von Dir 
bekommen habe (und ich glaube, das geht den meisten, die sich schon 
länger hier im Forum rumtreiben, so)...
#1181913
Lesenswert?

Franz M. wrote:
> ja das is echt tricky :P
>
> Wenn sich jetzt nicht zwischen "in r16, PORTB" und "out PORTB, r16" was
> am PORTB aendert, ist alles OK ;-)
Das Problem haste bei Read-Modify-Write-Zugriffen dummerweise immer. In 
dem Falle wäre tatsächlich die Methode mit sbi und cbi die einzig 
empfehlenswerte. Die ist aber länger...

EDIT:
OK, meist genügt es natürlich, für die Zeit vom in bis zum out die 
Interrupt-Bearbeitung zu sperren. Nur wenn irgendwelche Hardware (Timer, 
serielle Interfaces) auf PORTx zugreifen, genügt das nicht mehr.
#1181933
Lesenswert?

Johann L. wrote:
> Die Lösung wird auch davon abhängen, wo man atomar sein will/muss
>
> -- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände
> vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port
> schreiben und sbi/cli ist obsolet

Ganz genau umgekehrt ist es richtig, man muß SBI/CBI nehmen, um atomar 
zu sein!

Nimmt man IN,AND,OR,OUT ist das nicht mehr atomar.
Dann muß mit CLI/SEI geklammert werden, wenn auch Interrupts den Port 
benutzen.


Peter
Persönliche Seite #1182095
Lesenswert?

Peter Dannegger wrote:
> Johann L. wrote:
>> Die Lösung wird auch davon abhängen, wo man atomar sein will/muss
>>
>> -- wenn man an den Ausgängen atomar sein muss, also Zwischenzustände
>> vermeiden, die man garnicht ausgeben will, muss man auf den ganzen Port
>> schreiben und sbi/cli ist obsolet
>
> Ganz genau umgekehrt ist es richtig, man muß SBI/CBI nehmen, um atomar
> zu sein!
>
> Nimmt man IN,AND,OR,OUT ist das nicht mehr atomar.
> Dann muß mit CLI/SEI geklammert werden, wenn auch Interrupts den Port
> benutzen.
>
>
> Peter

ALLES lesen, was ich schrieb :-)

Ein wenn sich das "atomar" auf die Signale bezieht (keine seltsanmen 
Zwischenzustände), heisst das wohl "glitch" oder so im Fachchinesisch?

Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach 
11 oder 01 nach 10 etc.

Das ist u.a. auch dann von Belang, wenn im Programm nicht asynchron auf 
die Ports gegriffen wird.

Wenn asynchron auf die Ports gegriffen wird, dann "atomar" mit sbi/sbi 
wie ich schon schrieb.

Beispiel: In der Anwendung werden .0 und .1 gesetzt, in einer ISR .6. 
Dann braucht man cli/sei.

Johann
#1182155
Lesenswert?

Johann L. wrote:

> ALLES lesen, was ich schrieb :-)
>
> Ein wenn sich das "atomar" auf die Signale bezieht (keine seltsanmen
> Zwischenzustände), heisst das wohl "glitch" oder so im Fachchinesisch?

Du kannst nicht einfach dem Begriff "atomar" ne falsche Bedeutung geben.
Wenn Du glitch meinst, dann ist das was völlig anderes als atomar.

Atomar bedeutet nicht unterbrechbar, hat mit Glitches überhaupt nichts 
zu tun.
Nicht atomar ist etwas, wenn ein Interrupt dazwischen haut und dann die 
Änderung des Interrupts verloren geht.


> Beispiel: mit sbi/cbi kommt man nicht ohne Zwischenzustand von 00 nach
> 11 oder 01 nach 10 etc.

Das hat überhaupt nichts mit "atomar" zu tun, ist ne völlig andere 
Baustelle.

Gleichzeitig ist eh nie ein Wechsel zweier Signale, Du hast immer 
unterschiedliche Schaltzeiten und wenn es nur Picosekunden sind.
Wenn Du das willst, mußt Du Graycode nehmen oder die Signale mit einem 
Takt latchen, nachdem sie stabil sind.

Schau Dir mal die NXP ARM7-TDMI an, die haben getrennte Set- und 
Clear-Register, d.h. Du kannst dort nichtmal im gleichen Maschinenzyklus 
mehrere Pins setzen und löschen.
Sie sind aber extra dazu eingeführt worden, um atomar zuzugreifen, da 
bei den ARM7 ein Interrupt-Disable eine ziemliche Verrenkung ist (nicht 
im Usermode möglich).

Sowohl atomar als auch (fast) gleichzeitig kann der ARM-Cortex M3, da er 
spezielle Bitbefehle hat.


Peter

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