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.
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
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.
>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.
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:
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.
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...
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. ;-)
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 ;)
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.
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...
...