Forum: Mikrocontroller und Digitale Elektronik PORT in Schleife mit delay ändern


von Vergeßlicher (Gast)


Lesenswert?

Hallo,

nachdem ich mich gestern mit meiner Frage zur Einbindung von 
Assembler-Dateien blamiert habe (bin ich von geheilt), habe ich mir doch 
das gute alte STK500 gegriffen und mit WinAVR 20100110 sowie Atmel 
Studio 4.18 wieder große Schritte gemacht. Also: Blinky ist Freund ...

Das die LED's logisch "invertiert" angesteuert werden, wußte ich noch.

Das Problem mit PORTA auf meinem ATMega88 ließ sich dank der 
Compilermeldung auch flugs lösen (kennt er nicht weil gibt's nicht...).

Für das Problem PORTB6 und PORTB7 habe ich dann schon eine gute Stunde 
gebraucht ... Schön mit Durchklingeln, messen direkt am Pin, internen 
Oszillator auswählen usw. Jetzt weiß ich auch, warum die meisten 
LCD-Codes mit PORTD arbeiten. Ohne STK500 hätte es gleich geklappt, aber 
wozu hat man es denn...

Nun habe ich aber ein Brett vor dem Kopf:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main (void)
5
    {
6
        uint16_t i;
7
        DDRD = 0xFF;    // PORTD Ausgang
8
        while(1)
9
            {
10
                PORTD = 0xFF;           // PORTD komplett "1" => LED's aus
11
                for (i=0; i<1000; i++)  // Sekunde warten
12
                    {
13
                        _delay_ms(1);
14
                    }
15
                PORTD = 0x00;           // PORTD komplett "0" => LED's an
16
            }
17
        return 0;
18
    }
Da blinkt nix.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
int main (void)
5
    {
6
        uint16_t i;
7
        DDRD = 0xFF;
8
        while(1)
9
            {
10
                PORTD ^= 0xFF;
11
                for (i=0; i<1000; i++)
12
                    {
13
                        _delay_ms(1);
14
                    }
15
            }
16
        return 0;
17
    }

Da blinkt es artig.
Warum nicht beim ersten Code???

von Cyblord -. (cyblord)


Lesenswert?

Weil beim 1. Code zwischen PORTD=0x00 und PORTD=0xFF praktisch keine 
Verzögerung mehr liegt. Was soll da blinken?

von Justus S. (jussa)


Lesenswert?

es wird auch beim ersten Code blinken, aber so kurz, dass du es nicht 
sehen kannst...denn so hast du es schließlich programmiert...

von Cyblord -. (cyblord)


Lesenswert?

So ein typischer Anfängerfehler. Keine Ahnung warum. Man könnte sich den 
Programmablauf ja auch einfach mal kurz bildlich vorstellen.

Und warum machst du nicht einfach _delay_ms(1000); anstatt deiner 
Schleife.

Und es erstaunt schon ein wenig, dass wir von ASM-Code einbinden, über 
LCD-Ansteuerung jetzt tatsächlich bei der vielzitierten blinkenden LED 
angekommen sind. Ob man dafür einen Thread aufmachen muss? Für eine 
blinkende LED. Wie wärs wenn du erstmal noch bisschen mit dem STK500 
spielst, Tut liest, Beispiele anguckst und komplexe Sachen auf später 
verschiebst.

von Vergeßlicher (Gast)


Lesenswert?

cyblord ---- schrieb:
> So ein typischer Anfängerfehler. Keine Ahnung warum.
Oh S...., ich verkriech mich ...
Nun habe ich mich so auf die Hardware eingeschossen und das Gehirn 
ausgeschaltet.
> Und warum machst du nicht einfach _delay_ms(1000); anstatt deine
> Schleife da?
Irgendwo stand, daß erst ab avr-libc 1.7 größere delays möglich sind. 
Ausprobiert habe ich es natürlich nicht. Werde ich aber, jetzt wo es 
ordnungsgemäß blinkt.
> Und es erstaunt schon ein wenig, dass wir von ASM-Code einbinden, über
> LCD-Ansteuerung jetzt tatsächlich bei der vielzitierten blinkenden LED
> angekommen sind. Ob man dafür einen Thread aufmachen muss? Für eine
> blinkende LED. Wie wärs wenn du erstmal noch bisschen mit dem STK500
> spielst, Tut liest, Beispiele anguckst und komplexe Sachen auf später
> verschiebst.
Genau das mache ich doch gerade ...

von amateur (Gast)


Lesenswert?

Die blinken beide! Frag' Dein Oszi!

Dein Problem ist, Deine Pupille ist zu langsam!

Versuchs mal mit halbe-halbe.

while(1)
{
  PORTD = 0xFF;           // PORTD komplett "1" => LED's aus
  for (i=0; i<500; i++)  // 1/2 Sekunde warten
  {
    _delay_ms(1);
  }
  PORTD = 0x00;           // PORTD komplett "0" => LED's an
  for (i=0; i<500; i++)  // 1/2 Sekunde warten
  {
    _delay_ms(1);
  }
}

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


Lesenswert?

Ein Oszilloskop ist in so einem Fall Gold wert (eines aus der Bucht für 
30€ hätte gereicht). Da hättest du das "Aufblitzen" der LED gut erkennen 
können, wärst recht schnell auf die richtige Spur gekommen und hättest 
letztlich was gelernt. Das (richtige) Lernen blieb jetzt mit der 
Präsentation des Fehlers leider auf der Strecke...

von Vergeßlicher (Gast)


Lesenswert?

Nein, keine Angst. Der Fehler war bzw. ist mir durchaus bewußt. Nur habe 
ich mich oberpeinlicher Weise nur noch auf die Hardware konzentriert, 
weil ich vorher nur Hardwareprobleme hatte. Der Code war einfach zu 
simpel, um einen zweiten Blick drauf zu werfen. Zumal eine minimale 
Änderung ja reichte, daß es ging. Voll verrannt halt.

Ein Oszilloskop habe ich nicht und werde mir wohl auch keines zulegen. 
Für 10 € aber habe ich den guten LA, der mit sigrok auch 1a läuft. Da 
hätte ich es auch locker mit sehen können. Aber wie gesagt: Völlig 
falschen Weg eingeschlagen.

von Beobachter #42 (Gast)


Lesenswert?


von Hans O. (piwibit)


Lesenswert?

Hättest Du den zweiten Code genauso schön kommentiert wie den ersten...

> int main (void)
>     {
>         uint16_t i;
>         DDRD = 0xFF;
>         while(1)
>             {
>                 PORTD ^= 0xFF;           // Zustand PORTD wechseln
>                 for (i=0; i<1000; i++)   // Sekunde warten
>                     {
>                         _delay_ms(1);
>                     }
>             }
>         return 0;
>     }

... dann wäre es Dir vielleicht aufgefallen

LG
Hans

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.