Forum: Mikrocontroller und Digitale Elektronik Werte aus zwei Ports "vereinen"


von Philipp S. (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Philipp S. (pschaefer)


Lesenswert?

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

von Philipp S. (Gast)


Lesenswert?

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

von Jobst M. (jobstens-de)


Lesenswert?

Die Pullups für Port R sind aktiviert?


Gruß

Jobst

von Philipp S. (Gast)


Lesenswert?

Hallo,
habe sie mit
1
PORTR.PIN0CTRL = 0x18;
 eingeschaltet, hat aber keine Änderung ergeben.

von Uwe (de0508)


Lesenswert?

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) !

von Philipp S. (Gast)


Lesenswert?

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.

von Jobst M. (jobstens-de)


Lesenswert?

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

von Philipp S. (Gast)


Lesenswert?

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)

von Jobst M. (jobstens-de)


Lesenswert?

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

von Philipp S. (Gast)


Lesenswert?

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.

von Philipp S. (Gast)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.