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
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.
1 | andi temp, 0xC0 |
2 | tst temp |
3 | brne _skip |
4 | ldi temp, 0x10 |
5 | out temp, PORTD |
6 | _skip: |
7 | ; weiter im programm |
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.
@ df311:
1 | andi temp, 0xC0 |
2 | tst temp |
3 | brne _skip |
4 | ldi temp, 0x10 |
5 | out temp, PORTD |
6 | _skip: |
7 | ; 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:
1 | IN Reg, PORTD |
2 | ANDI Reg, 0x60 |
3 | IN Reg, SREG |
4 | SBRS Reg, 1 |
5 | SBI PORTD, 5 |
Stefan Ernst wrote:
>
1 | > IN Reg, PORTD |
2 | > ANDI Reg, 0x60 |
3 | > IN Reg, SREG |
4 | > SBRS Reg, 1 |
5 | > SBI PORTD, 5 |
6 | > |
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
1 | IN Reg, PORTD |
2 | ANDI Reg, 0x60 |
3 | BRNE NOSET |
4 | SBI PORTD, 5 |
5 | NOSET: |
@ Karl-Heinz IN Reg, PORTD Ich bin zwar kein asm-Spezi, aber ich würde: IN Reg, PIND schreiben. MW
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... ...
ups, die fehler bei den hex-zahlen oben tun mir leid - ich sollte nicht zwischen zwei vorlesungen zuviel nachdenken ;-)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.