www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik IF-Abfrage in ASM für mehrere Ausgänge


Autor: Gray (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich versuche mich seit kurzem im programmieren eines Attiny2313 und 
möchte folgendes:

Wenn an PortD 5 & 6 jeweils der Wert auf 0 steht, so soll PortD 5 auf 1 
gesetzt werden.

In PHP würde ich es so machen:
if($PortD[5] == 0 && $PortD[6] == 0){
     $PortD[5] = 1;
}

Ich hoffe ihr wisst was ich machen möchte, das ganze würde ich gerne in 
ASM hinbekommen, thx für eure Hilfe.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gray wrote:
>
> Ich hoffe ihr wisst was ich machen möchte, das ganze würde ich gerne in
> ASM hinbekommen, thx für eure Hilfe.

Den Port abfragen.
Mit einem AND alle anderen Bits wegmaskieren (definiert auf 0 setzen).
Wenn das Ergebnis 0 ist, dann sind Bit 5 und Bit 6 definitiv auf 0.

In Assembler ist das eigentlich eine übliche Vorgehensweise mittels
AND und OR Bits gezielt zu löschen, bzw. gezielt zu setzen.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Logik

Autor: df311 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mir wäre jetzt nicht bekannt, dass man mit avr's i/o-pins bidirektional 
nutzen kann, also von daher dürfte das ganze schon schwieriger werden.
andi temp, 0xC0
tst temp
brne _skip
ldi temp, 0x10
out temp, PORTD
_skip:
; weiter im programm

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sbic PinD, 5
rjmp Nix
sbic PinD, 6
rjmp Nix
sbi  DDRD, 5
sbi  PortD, 5
rjmp zurück (oder 'ret' bei Unterprogramm)

Nix:
cbi  DDRD, 5
cbi  PortD, 5
rjmp zurück (oder 'ret' bei Unterprogramm)


Nebenbei bemerkt, ist es problematisch, einen Portpin zu setzen, den man 
auch als Eingang abfragt. Aber vielleicht muß das ja bei Dir so sein.

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>mir wäre jetzt nicht bekannt, dass man mit avr's i/o-pins bidirektional
>nutzen kann

Na aber sicher doch. Schon immer! Es gibt nur einige Ausnahmen bei AVRs, 
bei denen es einige Portpins gibt, die nur als Eingang oder nur als 
Ausgang fungieren.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ df311:
andi temp, 0xC0
tst temp
brne _skip
ldi temp, 0x10
out temp, PORTD
_skip:
; weiter im programm

Wieso 0xC0? Bit 5 und 6 sind 0x60.
Wozu das tst? andi setzt doch schon das Z-Flag.
Wieso 0x01? Bit 5 ist 0x20.

@  Travel Rec.:
So wie er seinen PHP-Code geschrieben hat, will er Bit 5 abhängig vom 
aktuellen Output an Bit 5 und 6 setzen. Und von einem "sonst Bit 5 auf 
0" steht da auch nichts.

Mein Vorschlag:
IN   Reg, PORTD
ANDI Reg, 0x60
IN   Reg, SREG
SBRS Reg, 1
SBI  PORTD, 5

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst wrote:

>
> IN   Reg, PORTD
> ANDI Reg, 0x60
> IN   Reg, SREG
> SBRS Reg, 1
> SBI  PORTD, 5
> 


He, he.
Mit dem IN REG, SREG dürftest du dem OP eine harte Nuss
zu knacken gegeben haben. :-)

Für den OP: Es geht auch so
        IN   Reg, PORTD
        ANDI Reg, 0x60
        BRNE NOSET
        SBI  PORTD, 5
NOSET:

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl-Heinz

IN   Reg, PORTD

Ich bin zwar kein asm-Spezi, aber ich würde:

IN   Reg, PIND

schreiben.

MW

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups, mein Code enthält einen Fehler:
SBRS -> SBRC

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Wilhelm wrote:
> @ Karl-Heinz
>
> IN   Reg, PORTD
>
> Ich bin zwar kein asm-Spezi, aber ich würde:
>
> IN   Reg, PIND
>
> schreiben.

Das kommt drauf an, was er erreichen will (und das geht aus
dem Eröffnungsposting so nicht klar hervor).

  IN  Reg, PORTD

kann durchaus Sinn machen, wenn er zb den zuvor am einem
Port ausgegebenen Wert haben möchte. Oder wenn es darum geht
Pull-Up Widerstände zu- oder wegzuschalten.

Autor: wjunky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo alle zusammen.

AVRs können für gewöhnlich
in Reg, SREG
da das SREG sich als normales IOReg misshandeln lässt. Verbraucht nur 
unnötig mehr cycles als die vordefinierten, hardware-implementieren 
branches.

@Gray: was genau willst du?
wenn du
in Reg, PORTD machst holst du dir den wert, den du dort 
hineingeschrieben hast. PORTx ist eine Speicherstelle, die nur von 
deinem Programm verändert wird. Sie kann also als Variable missbraucht 
werden, wird aber nicht von außen geändert.
Wenn du wissen willst, ob der Pin high oder low ist musst du PINx 
auslesen.
PINx liefert dir in Abhängigkeit von DDRx entweder den Wert der außen 
anliegt (DDRxn auf input) oder den das bit im PORTx (DDRxn auf output).
Sollte es dennoch Probleme geben, dann schau mal nach, ob der Pin nicht 
überschrieben wird (Doku => alternate Portfunctions). Eine Reihe von 
Devices sind in der Lage die Werte in DDR und PORT zu überlagern. DDR 
und PORT geben zwar immer den Wert zurück der in sie hineingeschrieben 
wurde (von deinem Programm), aber der eigentliche Wert am PIN kann vom 
erwarteten Ergebnis abweichen, wenn beispielsweise das TWI die PINs 
gerade kontrolliert.

Schreib mal etwas genauer, was du machen willst, dann können wir dir 
auch detaillierter helfen...

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wjunky wrote:

> Verbraucht nur
> unnötig mehr cycles als die vordefinierten, hardware-implementieren
> branches.

Ja, meine Variante braucht genau 1 Cycle mehr.
Ich bevorzuge trotzdem die Skip-Befehle (vorausgesetzt es muss wirklich 
nur ein Befehl übersprungen werden), weil ich finde, dass es der 
Übersichtlichkeit dient, wenn man Sprungmarken einspart. (Ist aber wohl 
eher persönliche Geschmackssache)

> PINx liefert dir in Abhängigkeit von DDRx entweder den Wert der außen
> anliegt (DDRxn auf input) oder den das bit im PORTx (DDRxn auf output).

Nein, PINx liefert immer den Wert "von außen". Der sollte bei 
DDRx=output allerdings mit PORTx übereinstimmen. Wenn er mal nicht 
übereinstimmt, lebt der Port sicher nicht mehr lange. ;-)

Autor: Gray (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
THX@ALL

Ui, hätte ja nicht gedacht das mein erstes Projekt doch so kompliziert 
sein könnte.

Ich möchte insgesamt folgendes:

Ich habe 2 Taster und 4 Ausgänge

Wenn Taster 1 gedrück wird soll Ausgang 1 kurz einen Impuls bekommen und 
Ausgang 2 dauerhaft an bleiben

bis

Tatser 2 gedrückt wird, jetzt gibt es an Ausgang 3 einen Impuls und 
Ausgang 4 wird dauerhaft eingeschaltl dafür aber wieder Ausgang 2 aus.

Das ganze ist für die Eisenbahnanlage, da ich nur weichen habe die keine 
Rückmeldung und auch keine Endabschaltung haben, hab ich mir das so 
vorgestellt, das beim einschalten alles auf eine "Startposition" 
gebracht5 wird (deshalb die Abfrage anch den Pin 5 & 6).

Wenn ich Tatser 1 drücke geht die Weiche per Impuls nach links und LED 1 
leuchtet und wenn ich Tatser 2 drücke geht die Weiche nach rechts und 
LED 2 leuchtet.

Mag zwar sein das man das einfacher lösen kann mit FlipFlops oder so, 
aber ich brauch halt was praktisches um das proggen der kleinen Dinger 
zu lernen ;)

Autor: wjunky (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hiho!

@Stefan: stimmt schon, wenn der AVR schon raucht, kann PIN schonmal was 
anderes anzeigen :D

@Gray
Das kannst du sogar mit nur einem Taster realisieren :-)

Aber zu deinem Aufbau:
Die Taster-Pins solltest du gegen GND mit Pull-ups betreiben (DDR clear 
und PORT set). Die LED solltest du gegen VCC (mit Widerstand) betreiben. 
Du ziehst dann einfach den PIN auf GND (DDR und PORT clear). Das ist 
schonender für den AVR.

Dann kannst du dir überlegen, ob du mit Timern oder mit Schleifen bzw. 
mit Interrupts oder mit Polling arbeitest. Für Anfänger sind Schleifen 
und Polling erstmal einfacher. Zum Programmieren lernen, kannst du dich 
dann später noch mit Timer-Interrupts, externen Interrupts und 
Sleepmodes beschäftigen.

Um bei dem ganzen nicht total den Überblick zu verlieren, würde ich den 
aktuellen Zustand einfach in einem Register speichern und dann einfach 
damit arbeiten. Dann schreibst du dir eine Methode, die abhängig vom 
aktuellen Zustand einfach die Port-Register richtig setzt. Das hat auch 
den Vorteil, dass du nur diese Methode ändern musst, wenn du die 
Pinbelegung änderst.

Ich will jetzt nicht zu viel Hilfe geben, da du selber basteln willst. 
Wenn du nochmal hängst, kannst du dich ja noch mal melden.

Autor: Hannes Lux (hannes)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Da Du in jeder Weichenstellung eine LED dauerhaft einschalten willst und 
einen Impuls für die Weichenspule erzeugen willst, reicht es nicht, mit 
kombinatorischer Logik zu arbeiten, da muss sequentielle Logik her. Und 
da Du beim Kauf Deines Tiny2313 die Timer bereits mit bezahlt hast, wäre 
es Unfug, sie (zumindest einen davon) nicht zu benutzen. Und weil der 
Tiny2313 genug I/O-Pins für 2 Weichen hat, wäre es Verschwendung, das 
Programm für nur eine Weiche auszulegen. Und damit Deine Weichen nicht 
bei jedem Rad-Schiene-Funken von alleine schalten, sollte man die 
Tasteneingänge auch ordentlich entprellen. Damit Du Dir nicht erst 
irgendwelchen Blödsinn mit Bitparaden (sowas wie 0b00110101) angewöhnst, 
habe ich die Bits "getauft" und nenne sie beim Namen.

Im Anhang findest Du einen Programm-Quelltext, den Du mit Hilfe der 
enthaltenen Kommentare, des Datenblattes des Tiny2313, der Hilfe (F1) 
des AVR-Studios und des Simulators des AVR-Studios analysieren kannst, 
um die Funktion zu verstehen.

Du kannst natürlich auch einfach die Hexdatei erzeugen und in Deine AVRs 
brennen und Dich freuen, dass es funktioniert, aber dabei lernst Du 
nicht wirklich was...

...

Autor: df311 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups, die fehler bei den hex-zahlen oben tun mir leid - ich sollte nicht 
zwischen zwei vorlesungen zuviel nachdenken ;-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.