Forum: Mikrocontroller und Digitale Elektronik 3 led mit atmega8


von Patrick N. (emerand)


Lesenswert?

Hallo Leute!
Ich versuche gerade im Rahmen meiner anfänglichen Arbeit mit 
Mikrocontroller 3 Led nacheinander an und auszuschalten mit Hilfe einer 
Atmega8 von Atmel.

So schaut mein code aus:

#define F_CPU 3686400
#include <avr/io.h>
#include <util/delay.h>

//#define F_CPU 3686400
const int delay = 10000000;

int main(void)
{
  DDRB = 0xFF;       // setzt PortB als ausgang

    while(1)
    {
      PORTB |= (1<< PORTB0);   // setzt Bit 0 von Port B auf 1
    _delay_ms(delay);    // warte eine Zeitspanne

   PORTB &= (1<< PORTB0);  // lösche Bit 0 von Port B
   PORTB |=(1<< PORTB1);     // setzt Bit 1 von Port B auf 1
   _delay_ms(delay);        // warte wieder eine zeitspanne

   PORTB &= (1<< PORTB1);  // usw.
   PORTB |=(1<< PORTB2);
   _delay_ms(delay);
    }
}

Anstatt nacheinander an und auszugehen, leuchten die LEDs alle 
gleichzeitig.
Was stimmt mit meinem code nicht??
Danke schon mal im voraus

von Stefan (Gast)


Lesenswert?

Hallo,
>> const int delay = 10000000;
int ist bestenfalls 16 bit.
Stefan

von chris (Gast)


Lesenswert?

Hallo,

wie lange dauert denn dein _delay_ms(delay); ?

von Karl H. (kbuchegg)


Lesenswert?

_delay_ms(delay);

_delay_ms will eine tatsächliche Konstante. Auch wenn du die Variable 
const gemacht hast, ist das in C keine Konstante im eigentlichen Sinne 
(in C++ wäre sie es).

Ausserdem sind 10000000 viel zu lang. 10000 Sekunden sind 166 Minuten, 
also gut und gerne 2.5 Stunden. Ich denke nicht, dass du so lange warten 
willst.
1
#define F_CPU 3686400
2
#include <avr/io.h>
3
#include <util/delay.h>
4
5
//#define F_CPU 3686400
6
#define TIME 500
7
8
int main(void)
9
{
10
  DDRB = 0xFF;       // setzt PortB als ausgang
11
12
    while(1)
13
    {
14
      PORTB |= (1<< PORTB0);   // setzt Bit 0 von Port B auf 1
15
    _delay_ms(TIME);    // warte eine Zeitspanne
16
17
   PORTB &= (1<< PORTB0);  // lösche Bit 0 von Port B
18
   PORTB |=(1<< PORTB1);     // setzt Bit 1 von Port B auf 1
19
   _delay_ms(TIME);        // warte wieder eine zeitspanne
20
21
   PORTB &= (1<< PORTB1);  // usw.
22
   PORTB |=(1<< PORTB2);
23
   _delay_ms(TIME);
24
    }
25
}


Der Optimizer des Compilers ist eingeschaltet?

von Max (Gast)


Lesenswert?

Außerdem:

> The maximal possible delay is 262.14 ms / F_CPU in MHz.

von Karl H. (kbuchegg)


Lesenswert?

Max schrieb:
> Außerdem:
>
>> The maximal possible delay is 262.14 ms / F_CPU in MHz.

Das gilt schon lange nicht mehr.

von Kurt B. (kurt)


Lesenswert?

Patrick N. schrieb:
> PORTB &= (1<< PORTB0);  // lösche Bit 0 von Port B

PORTB &= ~(1<< PORTB0);  // lösche Bit 0 von Port B

von Timmo H. (masterfx)


Lesenswert?

Karl Heinz Buchegger schrieb:
> _delay_ms(delay);
>
> _delay_ms will eine tatsächliche Konstante. Auch wenn du die Variable
> const gemacht hast, ist das in C keine Konstante im eigentlichen Sinne
> (in C++ wäre sie es).

Nein, _delay_ms kann auch mit Variablen umgehen, dadurch wird der Code 
aber sehr groß.

Max schrieb:
> Außerdem:
>
>> The maximal possible delay is 262.14 ms / F_CPU in MHz.
und der darauf folgende Absatz:
1
The maximal possible delay is 262.14 ms / F_CPU in MHz.
2
3
When the user request delay which exceed the maximum possible one,
4
 _delay_ms() provides a decreased resolution functionality. In this mode
5
 _delay_ms() will work with a resolution of 1/10 ms, providing delays up to
6
 6.5535 seconds (independent from CPU frequency). The user will not be
7
 informed about decreased resolution.

von Karl H. (kbuchegg)


Lesenswert?

Timmo H. schrieb:
> Karl Heinz Buchegger schrieb:
>> _delay_ms(delay);
>>
>> _delay_ms will eine tatsächliche Konstante. Auch wenn du die Variable
>> const gemacht hast, ist das in C keine Konstante im eigentlichen Sinne
>> (in C++ wäre sie es).
>
> Nein, _delay_ms kann auch mit Variablen umgehen, dadurch wird der Code
> aber sehr groß.

OK.
Umgehen ist das falsche Wort. Die Zeiten stimmen nicht, was ja nicht im 
Sinne des Erfinders ist.

von Patrick N. (emerand)


Lesenswert?

Hallo Leute!
Erstmal vielen dank für die schnellen und zahlreichen Antworten. Das hat 
mir sehr viel geholfen. So sehr dass ich mich bereit fühlte für den 
nächste schritt. Und zwar dieses mal eine Routine zu schreiben womit ich 
alle LEDs die an einem PORT angeschlossen sind nacheinander an und 
ausschalten kann.
und so sieht mein Code aus:


#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 3686400
#define delay 1
#define leuchtdauer 4
#define meinbit 7

void warten_1sek() {
  unsigned long n;
  for(n=0; n<50; n++)
    _delay_ms(80);
}

void warten_Nsek (unsigned long n) {

    unsigned long k;
    for (k=0; k<n; k++)
      warten_1sek();
}

void led_on_off (void){
unsigned long i;
for (i=0; i<= meinbit; i++)
warten_Nsek (delay);
PORTB |= (1<< i);
warten_Nsek (leuchtdauer);
PORTB = 0x00;
}


int main(void)
{
DDRB = 0xFF;       // setzt PortB als ausgang

    while(1)
    {
    led_on_off();
    }

    }

Aber wie e bei Anfänger so ist, klappt es auch wieder nicht. Die LEDs 
gehen überhaupt nicht an. woran kann es dieses mal liegen?
Danke

von Karl H. (kbuchegg)


Lesenswert?

Patrick N. schrieb:

Rücke diesen Code mal so ein, wie du es haben willst. Welche Anweisungen 
sollen in der for-Schleife sein:

> void led_on_off (void){
> unsigned long i;
> for (i=0; i<= meinbit; i++)
> warten_Nsek (delay);
> PORTB |= (1<< i);
> warten_Nsek (leuchtdauer);
> PORTB = 0x00;
> }


Nachdem du deine Vorstellung davon, was alles innerhalb der Schleife 
passieren soll, mal sauber durch einrücken klar gemacht hast, zeig ich 
dir, wie der Compiler die Sache sieht. Nämlich so
1
void led_on_off (void)
2
{
3
  unsigned long i;
4
5
  for (i=0; i<= meinbit; i++)
6
    warten_Nsek (delay);
7
8
  PORTB |= (1<< i);
9
  warten_Nsek (leuchtdauer);
10
  PORTB = 0x00;
11
}

und das ist etwas anderes als du wolltest.

Fazit: eine vernünftige optische Aufbereitung deines Codes, kann dir 
helfen Fehler zu sehen.

Du willst das hier

1
void led_on_off (void)
2
{
3
  unsigned long i;
4
5
  for (i=0; i<= meinbit; i++)
6
  {
7
    warten_Nsek (delay);
8
    PORTB |= (1<< i);
9
  }
10
11
  warten_Nsek (leuchtdauer);
12
  PORTB = 0x00;
13
}

Die { } Klammern machen den Unterschied. Bei mir sieht man auf einen 
Blick, dass sie da sind. Bei deinem Originalcode muss man wissen, dass 
man danach suchen soll, sonst siehst du nie und nimmer, dass du sie 
vergessen hast. Das du dein Vergessen nicht siehst, liegt nicht zuletzt 
daran, dass dein Code ein monolithischer Haufen Buchstaben ohne jede 
Struktur ist.


Was zb stimmt hier nicht?
1
int main(void)
2
{
3
DDRB = 0xFF;       // setzt PortB als ausgang
4
5
    while(1)
6
    {
7
    led_on_off();
8
    }
9
10
    }

Antwort: Die jeweils schliessende } steht nicht unter der zugehörigen 
öffnenden {
In der while Schleife ist das davon abhängige Statement nicht 
eingerückt.
Dein Einrückungsschema ist inkonsistent. Warum steht das setzen von DDRB 
am linken Rand und das while danach ist um 4 Zeichen eingerückt. An 
anderer Stelle in deinem Code hast du 2 Zeichen eingerückt.

Das ganze sollte so aussehen
1
int main(void)
2
{
3
  DDRB = 0xFF;       // setzt PortB als ausgang
4
5
  while(1)
6
  {
7
    led_on_off();
8
  }
9
}

optisch sauberer Code ist kein Selbstzweck. Er ist ein Mittel um dem 
Gehirn eine Leitlinie zu geben. D.h. man macht das immer und nicht erst 
irgendwann hinterher! Und es hilft dir Fehler zu sehen.

von Patrick N. (emerand)


Lesenswert?

Ich bin dir sehr dankbar für deine Anmerkungen und Antworten an meine 
Sorgen. Werde mich ab heute viel mehr mühe geben meine code struktur und 
Sauberkeit zu geben.
Danke noch mal.

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.