Hallo zusammen, ich hab folgendes Problem: ich habe ein Programm welches über LEDs die Uhrzeit ausgibt (siehe vorherige Foreneinträge). Am Anfang hat alles wunderbar funktioniert, außer dass die LEDs sehr schwach geleuchtet haben. In der ersten "Version" habe ich das DDRx jeweil bei jedem Ausgang einzeln gesetzt. jetzt sieht es folgendermasen aus: .... // initalisieren der Ports void init ( void ) { DDRA = 0xFF; DDRB = 0xFF; DDRC = 0xFF; DDRD = 0xFF; DDRD &=~ (1 << DDD2); //Eingang } .... Hat auch geholfen, also die LEDs leuchten hell (so wie ich es wollte). ABER, die LEDs, welche am Port D hängen leuchten nicht mehr. Ich hab schon auf verschiedene Arten Versucht das Problem zu beheben, z.B. die letzten beiden Zeilen in "DDRD = 0xFB" ändern. Ich freue mich über jeden Verbesserungsvorschlag!
Daniela wrote: > .... > // initalisieren der Ports > void init ( void ) { > DDRA = 0xFF; > DDRB = 0xFF; > DDRC = 0xFF; > DDRD = 0xFF; > DDRD &=~ (1 << DDD2); //Eingang > } > .... > Schön, aber dein main fängt so an int main(void) { init(); // Kontroll LED DDRD = (1 << PD5); und damit ist deine ganze DDRD Einstellung in init() Geschichte geworden.
versteh ich das richtig, dass es gehen müsste wenn die Zeile DDRD = (1 << PD5); gelöscht wird? Die brauch ich im Prinzip auch nicht.
> DDRD = 0xFF; > DDRD &=~ (1 << DDD2); //Eingang Ich finde es überhaupt eine schlechte Idee, ein Port (und sei es auch nur für einen Takt) als Ausgang zu definieren und dann wieder zurück auf Eingang. Wenn an dem Pin etwas hängt, dann kommt es zu einem Kurzschluss. In der Init Routine sollen alle Pins entsprechend der Hardware von Anfang an richtig gesetzt werden.
Daniela wrote: > versteh ich das richtig, dass es gehen müsste wenn die Zeile > > DDRD = (1 << PD5); > > gelöscht wird? Die brauch ich im Prinzip auch nicht. Ich hab mir den Rest des Programmes nicht durchgesehen. Aber wenn du hier eine Zuweisung zu DDRD machst, dann ist deine ganze EInstellung des DDRD Registers in init() sinnlos geworden, weil sie hier ja überschrieben wird.
wäre dann > DDRD &= (1 << DDD2); //Eingang anstatt > DDRD &=~ (1 << DDD2); //Eingang die bessre Lösung? Sonst habe ich nichts an den DDR-Registern geändert.
In 99.999% aller Fälle ist es nicht notwendig die Richtung eines Portpins im laufenden Programm zu ändern. Das macht man genau einmal in einer Init-Routine gemäss der angeschlossenen Hardware und ändert dann nix mehr dran. Demnach würde ich Zugriff auf DDRD ausschließlich in "Init()" machen. Du bist dir der Funktion der beiden Register "DDRD" und "PORTD" aber schon bewusst oder hast du den folgenden Block von irgendwo her kopiert?
1 | // Kontroll LED
|
2 | |
3 | DDRD = (1 << PD5); |
4 | PORTD |= (1 << PD5); |
Am Anfang habe ich jede LED so "angesteuert." Die Kontroll LED gibt es inzwischen gar nicht mehr, die hatte ich nur drin um zu sehen ob überhaupt was geht. Deshalb hab ich auf die beiden Zeilen auch gar nicht mehr geachtet und jetzt auch komplett gelöscht.
> Am Anfang habe ich jede LED so "angesteuert." > > Die Kontroll LED gibt es inzwischen gar nicht mehr, die hatte ich nur > drin um zu sehen ob überhaupt was geht. Deshalb hab ich auf die beiden > Zeilen auch gar nicht mehr geachtet und jetzt auch komplett gelöscht. Gerade im Fehlerfall ist es hilfreich, den Code im Geiste noch einmal nach zu vollziehen und sich über die Bedeutung jeder einzelnen Zeile klar zu werden. http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Zugriff_auf_IO-Ports
Wäre auf jeden fall vermeidbar gewesen, aber ich bin auf dem Thema nicht so fit (wie man merkt), dass mir so was nur durch lesen klar wird.
> Wäre auf jeden fall vermeidbar gewesen, aber ich bin auf dem Thema nicht > so fit (wie man merkt), dass mir so was nur durch lesen klar wird. Deshalb der Link auf das Tutorial ;) Wenn du dir das mal in Ruhe durch gehst und ausprobierst, kommt ganz sicher noch der eine oder andere 'AHA'-Effekt. Viel Erfolg mit deiner Funkuhr ;) Darf ich fragen, was genau an Port B hängt?
ja klar darfst du da kommt das Signal vom DCF-Modul rein, du meinst doch den Eingangsport? Sonst sind überall LEDs oder nichts.
Dem Code nach zu urteilen hängt das DCF-Modul an PortD.2 Alle weiteren Pins sind Ausgänge. Ich frage nur, weil die Ausgabe der Uhrzeit sicherlich etwas eleganter als über das 2 dutzend if-else Konstrukte gelöst werden kann ;) Schaut ein wenig nach simulierter Analog-Uhr (mit "Zeigern") aus
Hmm... wrote: > In 99.999% aller Fälle ist es nicht notwendig die Richtung eines > Portpins im laufenden Programm zu ändern. Ein paar Neuner weniger tun es auch. Beispielsweise ist das bei bidirektionale Protokollen wie I2C und 1-Wire, bei HD44780-LCDs mit R/W und für Powerdown/save-Modi erforderlich.
>> etwas eleganter als über das 2 dutzend if-else Konstrukte >> gelöst werden kann >> Schaut ein wenig nach simulierter Analog-Uhr (mit "Zeigern") aus > ist es auch, war die Aufgabe. Habt ihr schon von Arrays (auf deutsch: Felder) gelernt?
Wenn ich das richtig verstehe, wird also von PD2 das DCF-Signal gelesen, an PD0, PD1, PD3, PD5, PD6 und PD7 hängen die LEDs, und PD4 ist nicht belegt. Mit
1 | DDRD = (1 << PD5); |
konfigurierst du alle PD-Pins außer PD5 als Eingang, weswegen die angeschlossenen LEDs nicht oder nur schwach leuchten. Lass also die Zeile weg, da die Datenrichtung in init schon für alle Ports richtig konfiguriert wurde. Und nimm den Raten von Klaus Falser zu Herzen und ersetze
1 | DDRD = 0xFF; |
2 | DDRD &=~ (1 << DDD2); //Eingang |
durch
1 | DDRD = 1<<DDD0 | 1<<DDD1 | 1<<DDD3 | 1<<DDD5 | 1<<DDD6 | 1<<DDD7; |
oder
1 | DDRD = ~(1<<DDD2 | 1<<DDD4); |
JA es geht!!!!!
tausend mal Dank!
>Habt ihr schon von Arrays (auf deutsch: Felder) gelernt?
Gelernt schon aber können nicht.
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.