Hallo uC-Fans, kurz zu mir, da dies mein erster Beitrag ist. Ich bin 24 und studiere Automatisierungssysteme in Berlin. Ich habe im kommenden Semester ein großes Projekt vor mir und bin bereits in der Vorbereitung, weshalb ich mich mit der Programmierung von uCs beschäftige. Ich nutze eine AVR XMEGA-A1 X-PLAINED Board mit atxmega128a1. Dort gibt es 8 Taster (PD0...PD5+PR0+PR1) und 8 LEDs (PE0...PE7). In einem ersten kleien Programm will ich einfach nur erledigen, dass jeder Taster eine entsprechende LED einschaltet, solange dieser gedrückt wird. PD6 und PD7 sind laut Schaltplan nicht angeschlossen. Wie interpretiert dies der uC? Und wie kann ich die gelesenen Werte von PD0...PD5 mit denen von PR0+PR1 zu einem Ausgabewert für PE vereinen? Mein bisheriger Ansatz funktioniert nur für PE0...PE6, PE7 ist dauer-High. wert = PORTD.IN; // Lese Port D, Bit 0...5 = Taster 0...5, sind "0", wenn Taster gedrückt if(!(PORTR.IN & 0x01)) // Wenn PR0 = 0 (SW6 gedrückt) wert -= 0x40; if(!(PORTR.IN & 0x02)) // Wenn PR1 = 0 (SW7 gedrück) wert -= 0x80; PORTE.OUT = wert; // Port E schreiben Ich danke euch und hoffe auf eine schöne Zeit bei euch, werde wohl öfter hier sein :) Grüße Philipp
Philipp Seckel schrieb: > Und wie kann ich die gelesenen Werte von PD0...PD5 mit denen von PR0+PR1 > zu einem Ausgabewert für PE vereinen? Mit Bitmanipulationen bist du schon auf einem guten Weg. Nur: > > Mein bisheriger Ansatz funktioniert nur für PE0...PE6, PE7 ist > dauer-High. > > wert = PORTD.IN; // Lese Port D, Bit 0...5 = Taster 0...5, sind "0", > wenn Taster gedrückt > > if(!(PORTR.IN & 0x01)) // Wenn PR0 = 0 (SW6 gedrückt) > wert -= 0x40; WEnn du ein Bit löschen willst wert &= ~( 1 << bitnummer ); Wenn du ein Bit gezielt setzen willst wert |= ( 1 << bitnummer ); Grundlage sind immer die Verknüpfungen eines kompletten Bytes mit irgendwelchen 'Masken', die das gewünschte erledigen. Und dann kann man natürlich noch ein Byte als ganzes ein paar Bits nach links oder rechts schieben. Das sind die Operatoren << und >> wert = wert << 1; // schiebt alle Bits von 'wert' um 1 Stelle nach links wert = wert >> 1; // schiebt alle Bits von 'wert' um 1 Stelle nach rechts du könntest zb PORTR als ganzes einlesen, danach mit Bitoperationen alle anderen, dich nicht interessierenden Bits gezielt auf 0 setzen, das Ergebnis davon dann so zurechtschieben, dass du es zum Ergebnis von PORTD dazuodern kannst.
Hallo Philipp, ich habe beim Umstieg auf den XMEGA und AVR32 vieles durch dieses Tutorial gelernt. http://kampis-elektroecke.de/?page_id=876 In Verbindung mit dem AVR-GCC-Tutorial hier, ist das eigentlich alles was man ausser dem Datenblatt noch braucht. Gruß Philipp
Hallo, erstmal Verzeihung, dass ich mich so lange nicht gemeldet habe. Beruf und Studium verlangen derzeit viel Zeit. Ich habe es jetzt über den folgenden Ansatz versucht (dabei hat mir auch das Tutorial von Kampi ganz gut geholfen):
1 | wert = PORTD.IN; // Lese Port D, Bit 0...5 = Taster 0...5, sind "0", wenn Taster gedrückt |
2 | |
3 | wert |= (1 << 6); // Bit6 in wert auf 1 setzen |
4 | wert |= (1 << 7); // Bit7 in wert auf 1 setzen |
5 | |
6 | if(!(PORTR.IN & 0x01)) // Wenn PR0 = 0 (SW6 gedrückt) |
7 | { wert &= ~(1<<6); } // Setze Bit6 in wert = 0 (LED6 an) |
8 | |
9 | if(!(PORTR.IN & 0x02)) // Wenn PR1 = 0 (SW7 gedrück) |
10 | { wert &= ~(1<<7); } // Setze Bit7 in wert = 0 (LED7 an) |
11 | |
12 | PORTE.OUT = wert; // Port E schreiben |
E6 und E7 sind nun aber Dauer-Low, d.h. die LEDs leuchten immer. Das Problem scheint in den if-Abfragen zu liegen. Denn wenn ich diese auskommentiere, sind alle LEDs aus. Wenn ich auch noch die ersten Zuweisungen für Bit6 und Bit7 lösche, sind LED6 und LED7 wiederum immer an. Hab ich da noch einen Knoten in meinen Gedanken? Danke und viele Grüße Philipp
Hallo, habe sie mit
1 | PORTR.PIN0CTRL = 0x18; |
eingeschaltet, hat aber keine Änderung ergeben.
Hallo Philipp, bei LOW aktiven Tastern, die Entprellung nicht vergessen, würde ich deinen Code abändern: Philipp Seckel schrieb: > if(!(PORTR.IN & 0x01)) Wird dann, ich setzte noch mal Klammern, dass Du sichst was zusammen gehört:
1 | if( (~PORTR.IN) & 0x01) { ... } |
Hier eine Entwicklung von Innen nach Außen, was so passiert: Sei PORTR.IN gleich 0b11111110 ~PORTR.IN ist 0b00000001 (~PORTR.IN & 0x01) die verUNDung mit 0x01 liefert 0b00000001, das ist Wahr (true) !
Hallo Uwe, deine Darlegung kann ich zwar nachvollziehen, aber das Ergebnis ist das gleiche. Es müsste nur bei gedrücktem Taster die Bedingung erfüllt werden. Scheinbar ist dem aber nicht so.
Uwe S. schrieb: > bei LOW aktiven Tastern, die Entprellung nicht vergessen Unabhängig davon. Und hier unnötig. Das Flackern der LEDs wird er verkraften ;-) Philipp Seckel schrieb: > habe sie mit PORTR.PIN0CTRL = 0x18; eingeschaltet, hat aber keine Änderung ergeben. Ich kenne den Controller nicht. Mich wundert allerdings, daß die beiden Ports 0 und 1 auf Bit 3 und 4 liegen - ist das korrekt? Gruß Jobst
Hallo Jobst, nein, sie sollten auf Bit 0 und 1 liegen. Wie kommst du auf 3 und 4? Wegen dem Pullup mit 0x18? (siehe dazu http://www.atmel.com/Images/doc8077.pdf Seite 142)
Philipp Seckel schrieb: > Wegen dem Pullup mit 0x18? Ja. Da fehlen mir weitere Informationen. Wie gesagt, ich kenne das Ding nicht. Es ist mir nur aufgefallen. Es zu überprüfen, überlasse ich Dir. :-) Was passiert, wenn Du PortR mal komplett und direkt auf PortE ausgibst? Verhält es sich wie gewünscht? Gruß Jobst
Hallo, hab ich mal ausprobiert. Dann funktionieren mit den besagten Tastern an R0 und R1 die LEDs 0 und 1. Passt also. Bin aber leider immer noch nicht dahinter gestiegen, was das Problem nun verursacht.
Nach einer gründlichen Grübelei läufts nun. Das vollständige Programm für Interessierte im Anhang. Eigentlich keine Geheimnisse dabei. Grüße Philipp
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.