ATMega8 - PORT C - Problem mit digitalem Ausgang

Was ich versuche zu tun, ist Pin PC0 von PORT C als Ausgang zu setzen, um eine LED zu leuchten. Der Code, den ich dafür verwende, lautet:

//SET PORT C
//PC0 = RELAY STATUS LED - O/P
//PC1 = RELAY CTL LINE - O/P
//PC2 = PUSH BUTTON - I/P
//PC3 = SPARE - O/P

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3) & _BV(PC2);

//SET PC0 = HIGH

PORTC |= _BV(PC0);

Aber das oben genannte funktioniert nicht. Ich habe meine Verbindungen überprüft und kann nicht herausfinden, warum es nicht funktioniert. Es sollte eine ziemlich einfache Sache sein.

Der einzige Grund, von dem ich denke, dass es sich darauf auswirken könnte, ist, dass ich auch einen ISP habe, der mit dem AVR verbunden ist ⇒ PC6, der von ihm als Reset-Leitung verwendet wird.

Irgendwelche Ideen, warum das oben Gesagte nicht funktioniert?

Antworten (2)

Ihr Problem:

Ihre DDR-Einstellung ist falsch: Sie haben geschrieben

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3) & _BV(PC2);

aber du willst

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3)
DDRC &= ~_BV(PC2);

Du sagst, du willst mehr Details, weil du einfach andere DDRC-Aufgaben nachgeahmt hast und nicht wirklich verstehst, was du geschrieben hast? Okay, hier gehts:

Wie man Register mit bitweisen Operatoren auf dem AVR setzt.

Lassen Sie uns die _BV()Makro- und PCx-Definitionen für einen Moment entpacken. _BV(x)ist einfach 1 << x. Wenn Sie schreiben _BV(5), wertet das Makro die Zahl aus 0b 0001 0000. PCx ist einfach ein Makro, das auf den Wert von x definiert ist, also _BV(PC5)wird dasselbe ausgewertet wie _BV(5). Sie erwarten wahrscheinlich Folgendes:

   0b 0000 0001  // PC0
|  0b 0000 0010  // PC1
|  0b 0000 1000  // PC3
&  0b 0000 0100  // Misconception: AND does not cause this to output a zero at the set bit
|= ------------
   0b 0000 1011

Allerdings löschen Sie PC2 nicht korrekt. Sie wenden am Ende ein binäres UND an. UND hat in C eine höhere Priorität als ODER, also ist Ihre Operation tatsächlich

DDRC |= _BV(PC0) | _BV(PC1) | ( _BV(PC3) & _BV(PC2) );

PC3 ist 0b 0000 1000 und PC2 ist 0b 0000 0100, also ergibt der Abschnitt in Klammern Null. Dies ist eigentlich ein Glück für PC2, aber unglücklich für PC3, das klar bleibt, wann Sie es eingestellt haben wollten. Um ein Bit zu löschen, verwenden Sie &, aber Sie müssen das Komplement der Zahl mit dem ~Operator bilden. In den folgenden Gleichungen habe ich ?für Bits verwendet, die wir nicht ändern möchten:

   0b ???? ???1  // Set PC0
|  0b ???? ??10  // Set PC1 
|  0b ???? 1?00  // Set PC3
|= ------------
   0b ???? 1?11

   0b ???? 1?11
&  0b 1111 1011  // Clear PC2
&= ------------
   0b ???? 1011

Im Code lauten diese Gleichungen:

DDRC |= _BV(PC0) | _BV(PC1) | _BV(PC3)
DDRC &= ~_BV(PC2);

wie oben gezeigt. Sie können dies entweder wie ich in zwei Schritten tun oder den vorherigen Wert von DDRC mit einer Bitmaske anwenden:

DDRC = (DDRC & 0xF0) | ( ( _BV(PC0) | _BV(PC1) | _BV(PC3) ) & ~_BV(PC2) );

0xF0 oder 0b 1111 0000, wenn UND mit dem vorherigen Wert von DDRC verknüpft, gibt 0b zurück ???? 0000, mit der wir unsere unteren vier Bits ODER verknüpfen können. Ich denke, die zweistufige Methode ist übersichtlicher: Ihre Ein- und Ausgänge befinden sich in verschiedenen Zeilen (beachten Sie, dass Sie zusätzliche Eingänge hinzufügen können, z. B. mit DDRC &= ~_BV(PC2) & ~_BV(PC4)). Manchmal teile ich es sogar auf mehrere Zeilen auf:

DDRC |= _BV(PC0)   // RELAY STATUS LED - O/P
DDRC |= _BV(PC1)   // RELAY CTL LINE - O/P
DDRC &= ~_BV(PC2)  // PUSH BUTTON - I/P
DDRC |= _BV(PC3)   // SPARE - O/P

Das ist für mich der klarste Mechanismus, der möglich ist, und der für zukünftige Leser am einfachsten zu verstehen ist. Es ist auch am ausführlichsten, aber wen interessiert das? Der Compiler optimiert alle drei Mechanismen auf denselben Code.

danke für den Hinweis und die ausführliche Erklärung ... sehr zu schätzen! das hat es aber auch nicht behoben. Ich habe das auf einfachste Weise mit umcodiert, DDRC = 0b00000001; PORTC |= _BV(PC0);aber die LED ist immer noch aus. Ich habe meine Verbindungen doppelt überprüft, daran liegt es also nicht. habe auch einen anderen ATMEGA8 ausprobiert, nur um sicherzugehen. gleiches Ergebnis
nvm .. funktioniert jetzt ... es stellt sich heraus, dass ich Zeilen in meinem Code über dieser hatte, die sich auf Peter Fleurys LCD-Bibliothek beziehen, die sie möglicherweise stören ... wenn ich diese Zeilen auskommentiere, funktioniert alles wie erwartet. Jetzt geht es los, um herauszufinden, wie diese Zeilen mit PORTC herumspielen!

Welchen Mikrocontroller verwendest du? ist es Atmega32 oder 16 oder irgendetwas anderes?, dann überprüfen Sie das Datenblatt, entweder haben sie eine JTAG-Schnittstelle oder nicht. Wenn sie über JTAG verfügen, können Sie PortC Few-Pins möglicherweise nicht verwenden, da JTAG standardmäßig ab Werk aktiviert ist.

Dazu müssen Sie JTAG von Fuses deaktivieren, indem Sie das JTAGEN- Fuse-Bit deaktivieren

oder

Schreiben Sie dies in die Initialisierung oder den Start Ihres Codes

MCUCSR|= (1<<JTD);