Forum: Mikrocontroller und Digitale Elektronik Pins und Bits verknüpfen


von Dietmar (Gast)


Lesenswert?

Hallo,

ich fange gerade mit C an und versuche einzelne Pins meines Atmega8 
einem Bit der Ausgabevariable zuzuordnen.

der folgende Code macht komische Sachen, wo ist mein Denkfehler?
1
DDRC = (1 << DDRC1) |(0 << DDRC2) | (0 << DDRC3) | (0 << DDRC4) | (0 << DDRC5);
2
PORTC =         (1 << PORTC2)| (1 << PORTC3)| (1 << PORTC4)| (1 << PORTC5);
3
4
Ausgabe = (PINC5 << 0) | (PINC4 << 1) | (PINC3 << 2) | (PINC2 << 3);
5
//Ich will hier Bit 0-3 entsprechend der PINC's setzen

Mit freundlichem Gruß
Dietmar

von vn nn (Gast)


Lesenswert?


von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dietmar schrieb:
> Ausgabe = (PINC5 << 0) | (PINC4 << 1) | (PINC3 << 2) | (PINC2 << 3);
Das ist unüblich. Selber ausgedacht? Was macht der '<<' Operator in C?
Er schiebt das, was links von ihm steht um so viele Bits nach links, 
wie das angibt, was rechts von ihm steht.
Was ist z.B. PINC2? Wenn du genau nachschaust: es ist die Zahl 2. Und 
warum sollte man jetzt die Zahl 2 um 3 Stellen nach links schieben?

Also: tritt einen Schritt zurück und überleg, was denn eigentlich 
passiert...

Ein kleiner Tipp: so ein "0<<" ist eigentlich unnötig und wird nur 
eingesetzt, um zu zeigen: ich habe nichts vergessen, ich mache das 
bewusst so.
Hauptsächlich verwendet ist ein "1<<", also eine binäre 000000001, die 
um eine bestimmte Anzahl Bits nach links geschoben wird...

: Bearbeitet durch Moderator
von Dietmar (Gast)


Lesenswert?

Okay, den Fehler erkenne ich jetzt.
Selbst mit langem studieren der Tutorials komme ich nicht darauf wie ich
den Bits einer Variable den logischen Status eines Portpins zuordnen 
kann.
Angeschlossen hab ich dort 3x BCD Codierschalter die bunt durcheinander 
mit dem µC verdrahtet sind.
In Bascom oder Luna würde ich es aus dem Stand schaffen, aber mit C ist 
das nicht so komfortabel.
so leider nicht: Ausgabe.1 = pinb.2

MfG Dietmar

von RTC-Modul (Gast)


Lesenswert?

(0<<DDRC1) bedeutet schiebe eine 0 um DDRC3 Stellen nach links.

von Hanswurst (Gast)


Lesenswert?

> Selbst mit langem studieren der Tutorials komme ich nicht darauf
> wie ich den Bits einer Variable den logischen Status eines Portpins > zuordnen 
kann.

Wenn Du uns sagst, an welcher Stelle genau es hakt, dann könne wir 
helfen und evtl. das Tutorial an dieser Stelle noch verbessern.

Also: Ich versuche Dir mal Hinweise zu geben, wie Du den Text anschauen 
solltest und was Du uns mitteilen solltest, wo und wie es hakt.

Gehe Satz für Satz, Bild für Bild, durch.

Welchen Satz kannst Du im Moment noch nicht deuten? Welches Bild?

Was ist genau das Problem? Liegt es an einem bestimmten Teilsatz, einer 
Phrase oder einem Wort?

Oder falls es um ein Bild geht: Um welches grafische Element geht es?

Was ist genau das Problem? Ist es an sich keinem Begriff zuzuordnen? Ist 
unklar in welcher Beziehung es mit anderen Teilen des Bildes steht? Oder 
unklar, in welcher Beziehung es zu dem Text steht? Wenn letzteres: 
Welchen Teil des Textes?

Einfach den ersten Satz, das erste Bild bei dem es hakt, hier posten und 
erklären, was das Problem ist. Dann helfen hier bestimmt Leute weiter.

von Dominik B. (odysseus1710)


Lesenswert?

So wie es Lothar schon beschrieben hat. Du willst damit ja bestimmte 
Bits eines Registers setzen/löschen.

Zum Setzen schiebst du eine '1' an die gewünschte Stelle, z.B.
1
DDRC |= (1 << DDRC3)
setzt das Bit DDRC3 (also Bit 3) im DDRC-Register

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Dietmar schrieb:
> In Bascom oder Luna würde ich es aus dem Stand schaffen, aber mit C ist
> das nicht so komfortabel.
> so leider nicht: Ausgabe.1 = pinb.2

 Macro für Pinabfrage schreiben und noch einen für Port oder gleich
 einen für Pinabfrage wenn das Ganze festverdrahtet ist.

von B. S. (bestucki)


Lesenswert?

Dietmar schrieb:
> Ausgabe = (PINC5 << 0) | (PINC4 << 1) | (PINC3 << 2) | (PINC2 << 3);

PINCx sind defines in avr/io.h. Diese werden vor dem Kompilieren durch 
den Präprozessor ersetzt.
1
#define PINC5 5
Dies bedeutet nun, dass überall in deinem Code (sofern der Header 
eingebunden ist), PINC5 durch 5 ersetzt wird. Dies geschieht analog für 
alle defines.

Daher hast du über diese defines keinen direkten Zugriff auf die Pins, 
das musst du von Hand erledigen. Die defines dienen nur dazu, den Code 
lesbarer und portabler gestalten zu können.

von Hanswurst (Gast)


Lesenswert?

Ach ja. Es wird auch hilfreich sein, wenn Du das, was Du zu verstehen 
meinst, einmal in eigenen Worten (und Bildern) beschreibst. So können 
wir auch noch besser erkennen, wo es hakt, selbst wenn Du das nicht 
ausdrücklich beschreiben kannst.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Dietmar schrieb:
> so leider nicht: Ausgabe.1 = pinb.2

 So glücklicherweise doch.
 Man muss nur ein bisschen nachdenken, evtl. zeichnen welcher
 Eingangspin an welchem Ausgangspin wieder ausgegeben werden soll
 oder welches bit in einer Variable gesetzt werden soll.

: Bearbeitet durch User
von Dietmar (Gast)


Lesenswert?

Guten Morgen,

ich habe die Pins 5/4/3/2 vom PortC mit der Wertigkeit 1/2/4/8
Meine aktuelle Idee ist es:
- den Port komplett abzufragen und die einzelnen Bits zu maskieren 
(logisch und)
- dann hab ich die Information welchen logischen Zustand mein Pin hat
- das ganze in eine If-Abfrage und dann das entsprechende Bit in meiner 
Ausgabevariable ändern.

Das Bit setzten muss ich aber noch komfortabler gestalten als ich es in 
der Ausgaberoutine programmiert habe
1
//macros
2
#define Heizung_an (PORTC |= (1 << PORTC1));    // Funktion um das Relais zu schalten
3
#define Heizung_aus (PORTC &= ~(1 << PORTC1));    // Funktion um das Relais zu schalten

Gruß
Dietmar

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Dietmar schrieb:
> ich habe die Pins 5/4/3/2 vom PortC mit der Wertigkeit 1/2/4/8

 Du willst folgendes:

 Ausgabe =    |7|6|5|4|  3  |  2  |  1  |  0  |
                         ^     ^     ^     ^
                        / \   / \   / \   / \
                         |     |     |     |
                         |     |     |     |
 PINC    =            |  2  |  3  |  4  |  5 |

 machen, oder wie ?

von Dietmar (Gast)


Lesenswert?

Genau!
Bei den anderen sind die Pins auch an verschiedenen Ports...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Dietmar schrieb:
> Bei den anderen sind die Pins auch an verschiedenen Ports...

 Hier, auf die Schnelle, sollte funktionieren:
1
#define chkB(vVar, pPin, vBit)  ((-((PINB >> pPin) & 1) ^ vVar) & (1 << vBit))
2
#define chkC(vVar, pPin, vBit)  ((-((PINC >> pPin) & 1) ^ vVar) & (1 << vBit))
3
#define chkD(vVar, pPin, vBit)  ((-((PIND >> pPin) & 1) ^ vVar) & (1 << vBit))
4
5
int main(void)
6
{
7
 Ausgabe ^= chkB(Ausgabe, 5, 0);    //* PinB.5 ==> Ausgabe.0
8
 Ausgabe ^= chkB(Ausgabe, 4, 1);
9
 Ausgabe ^= chkB(Ausgabe, 3, 2);
10
 Ausgabe ^= chkB(Ausgabe, 2, 3);
11
12
 Ausgabe ^= chkC(Ausgabe, 2, 4);    //* PinC.2 ==> Ausgabe.4
13
14
 Ausgabe ^= chkD(Ausgabe, 7, 5);    //* PinD.7 ==> Ausgabe.5
15
}

 Es geht wahrscheinlich schöner aber das macht auch den Job.

 EDIT:
 Oder du machst Macros daraus:
1
#define chkB(vVar, pPin, vBit)  ((-((PINB >> pPin) & 1) ^ vVar) & (1 << vBit))
2
#define chkC(vVar, pPin, vBit)  ((-((PINC >> pPin) & 1) ^ vVar) & (1 << vBit))
3
#define chkD(vVar, pPin, vBit)  ((-((PIND >> pPin) & 1) ^ vVar) & (1 << vBit))
4
5
#define mapB(vVar, pPin, vBit) { vVar ^= chkB(vVar, pPin, vBit); }
6
#define mapC(vVar, pPin, vBit) { vVar ^= chkC(vVar, pPin, vBit); }
7
#define mapD(vVar, pPin, vBit) { vVar ^= chkD(vVar, pPin, vBit); }
 und dann:
1
int main(void)
2
{
3
 mapB(Ausgabe, 5, 0);    //* PinB.5 ==> Ausgabe.0
4
5
 mapC(Ausgabe, 2, 4);    //* PinC.2 ==> Ausgabe.4
6
7
 mapD(Ausgabe, 7, 5);    //* PinD.7 ==> Ausgabe.5
8
}

 EDIT2:
 Mit macros wird jedesmal der zugehörige Code übersetzt, falls du
 eine function daraus machst (Hausaufgabe) wird der entsprechende
 Codeschnipsel nur aufgerufen, etwa so:
1
  Ausgabe = mapB(5, 0);    //* PinB.5 ==> Ausgabe.0
 oder so:
1
  Ausgabe = map(PINB, 5, 0);    //* PinB.5 ==> Ausgabe.0

: Bearbeitet durch User
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.