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?
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:
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.
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);
Ankit
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 ErgebnisAnkit