Verzögerung bei Lauflicht / Atmega8 / C

Gast #4648066
Guten Tag,
ich habe vor 2 Tagen angefangen mich mit der 
Mikrocontroller-Programmierung
zu beschäftigen und habe nun versucht ein Lauflicht zu Programmieren 
welches hin und her läuft.
Das hin un her laufen habe ich hinbekommen, jedoch hat das Lauflich 
nachdem es einmal hin und her gelaufen ist eine kurze Verzögerung die 
ich nicht weg bekomme.
Könnt ihr mir evtl. sagen was ich falsch gemacht habe?
1
#include <util/delay.h>
2
#include <avr/io.h>  
3

4
int main(void)
5
{
6

7
int n, EINAUS=0;
8

9
DDRB = 0xFF; // Alle Pins in PORTB als Ausgang definieren
10
DDRD = 0x00; // Alle Pins in PORTD als Eingang definieren
11
PORTD = 0b00001100; // PULL-UP Widerstände für PD2 und PD3 setzen
12

13

14

15
while(1)
16
{
17

18
  if (!(PIND & (1<<PD2))) // Lauflicht einschalten
19
  {
20
  EINAUS = 1;
21
  }
22

23
  if (!(PIND & (1<<PD3))) // Lauflicht ausschalten
24
  {
25
  EINAUS = 0;
26
  }
27

28
  if (EINAUS == 1) 
29
  {
30
    for (n=0; n<=7; n++) // Pin 0-7
31
    {
32
      PORTB |= (1<<n); // Pin n im Port B setzen
33
      _delay_ms(1000); // Verzögerung von 1000ms
34
      PORTB &= ~(1<<n); // Pin n im Port B rücksetzen
35
    }
36
    
37
    for (n=7; n>=1; n--) // Pin 7-0
38
    {
39
      PORTB |= (1<<n); // Pin n im Port B setzen
40
      _delay_ms(1000); // Verzögerung von 1000ms
41
      PORTB &= ~(1<<n); // Pin n im Port B rücksetzen
42
    }
43
    
44
  }
45
  else
46
  {
47
  PORTB = 0x00; // Alle Pins im Port B auf 0 setzen
48
  }
49
}
50

51
}

Viele Grüße
Tim0
Gast
Endlich kann ich mal helfen!
Die Antwort ist ganz einfach:

while(1)
{

  if (!(PIND & (1<<PD2))) // Lauflicht einschalten
  {
  EINAUS = 1;
  }

  if (!(PIND & (1<<PD3))) // Lauflicht ausschalten
  {
  EINAUS = 0;
  }

  if (EINAUS == 1)

Nach jedem Durchlauf wird geprüft, ob das alles zutrifft, das braucht
Zeit. Hatte damals am Anfang exakt das gleiche "Problem".
Eine interessante Lösung bieten die Interrupts, schon mal damit 
gespielt?
Ist wirklich einfach, man muss sich nur einmal durcharbeiten!

Grüße aus Wien!
Tobias
Gast
Tobias schrieb:
> Nach jedem Durchlauf wird geprüft, ob das alles zutrifft, das braucht
> Zeit.

und du glaubst irgend jemand sieht das? Die Abfrage geht in viel weniger 
als 1ms.

> Endlich kann ich mal helfen!
nicht wirklich.
Gast
Danke für schnellen Antworten :)
Ich hatte gleich mehrere Fehler.
Eric B. schrieb:
> Tipp: welche Werte nimmt n nacheinander an?
Ich dachte die Verzögerung wäre nach einem Durchlauf, aber sie war 
mittendrin beim Wechsel zwischen den Schleifen.

Außerdem habe ich nur 6 LED's angeschlossen ^^'

Tobias schrieb:
> ...
> Nach jedem Durchlauf wird geprüft, ob das alles zutrifft, das braucht
> Zeit. Hatte damals am Anfang exakt das gleiche "Problem".
> Eine interessante Lösung bieten die Interrupts, schon mal damit
> gespielt?
> Ist wirklich einfach, man muss sich nur einmal durcharbeiten!
>
> Grüße aus Wien!
> Tobias

In diesem Fall war es wohl nicht der Fehler, aber das ist gut zu Wissen 
:)
Ich arbeite gerade die Videos von Stefan Wintgen durch, Interuppts sind 
tatsächlich das nächste Thema :)
https://www.youtube.com/watch?v=UpxemFUVnFI&index=5&list=PLg8rGAQEOsuh9ZCwP6aW5ycCM5PFFqoNe
Falls ihr noch weitere gute Tutorials zum Thema µC-Programmierung kennt, 
würde ich mich freuen wenn ihr diese hier Posten würdet :)

Marc V. schrieb:
> Tim0 schrieb:
>> for (n=7; n>=1; n--) // Pin 7-0
>
>  Und bit 0 ?

Bit 0 wird bei "Neustart" der If-Schleife wieder aufgerufen :)

Hier mein korrigierter Code
1
#include <util/delay.h>
2
#include <avr/io.h>  
3

4
int main(void)
5
{
6

7
int n, EINAUS=0;
8

9
DDRB = 0xFF; // Alle Pins in PORTB als Ausgang definieren
10
DDRD = 0x00; // Alle Pins in PORTD als Eingang definieren
11
PORTD = 0b00001100; // PULL-UP Widerstände für PD2 und PD3 setzen
12

13

14

15
while(1)
16
{
17

18
  if (!(PIND & (1<<PD2))) // Lauflicht einschalten
19
  {
20
  EINAUS = 1;
21
  }
22

23
  if (!(PIND & (1<<PD3))) // Lauflicht ausschalten
24
  {
25
  EINAUS = 0;
26
  }
27

28
  if (EINAUS == 1) 
29
  {
30
    for (n=0; n<=4; n++) // Pin 0-4 // bzw. LED 1-5
31
    {
32
      PORTB |= (1<<n); // Pin n im Port B setzen
33
      _delay_ms(1000); // Verzögerung von 1000ms
34
      PORTB &= ~(1<<n); // Pin n im Port B rücksetzen
35
    }
36
    
37
    for (n=5; n>=1; n--) // Pin 5-1 // bzw. LED 6-2
38
    {
39
      PORTB |= (1<<n); // Pin n im Port B setzen
40
      _delay_ms(1000); // Verzögerung von 1000ms
41
      PORTB &= ~(1<<n); // Pin n im Port B rücksetzen
42
    }
43
    
44
  }
45
  else
46
  {
47
  PORTB = 0x00; // Alle Pins im Port B auf 0 setzen
48
  }
49
}
50

51
}

Viele Grüße
Tim0
Gast
Tim0 schrieb:
> PORTB |= (1<<n);

wenn man ganz genau sein will, dann darf man das auch so nicht 
schreiben. Bei einem Atmel wird (1<<n) in einer schleife berechnet. 
Damit hast du abhängig von n unterschiedliche Ausführungszeiten.
Gast
Peter II schrieb:
> Tim0 schrieb:
>> PORTB |= (1<<n);
>
> wenn man ganz genau sein will, dann darf man das auch so nicht
> schreiben. Bei einem Atmel wird (1<<n) in einer schleife berechnet.
> Damit hast du abhängig von n unterschiedliche Ausführungszeiten.

Wie könnte ich das denn alternativ schreiben?

Gruß
Tim0
Gast
Tim0 schrieb:
> Wie könnte ich das denn alternativ schreiben?
1
uint8_t value = 1;
2
while( value != 128 )
3
{
4
      PORTB = value; // Pin n im Port B setzen
5
      _delay_ms(1000); // Verzögerung von 1000ms
6
      PORTB = 0;
7
      value = value << 1;
8
}
9
    
10
while( value != 1 )
11
{
12
      PORTB = value; // Pin n im Port B setzen
13
      _delay_ms(1000); // Verzögerung von 1000ms
14
      PORTB = 0;
15
      value = value >> 1;
16
}

aber den unterschied wirst du nicht sehen. Das geht dabei wirklich nur 
im ein paar Takte.
Gast
Peter II schrieb:
> Tim0 schrieb:
>> Wie könnte ich das denn alternativ schreiben?
> uint8_t value = 1;
> while( value != 128 )
> {
>       PORTB = value; // Pin n im Port B setzen
>       _delay_ms(1000); // Verzögerung von 1000ms
>       PORTB = 0;
>       value = value << 1;
> }
>
> while( value != 1 )
> {
>       PORTB = value; // Pin n im Port B setzen
>       _delay_ms(1000); // Verzögerung von 1000ms
>       PORTB = 0;
>       value = value >> 1;
> }
>
> aber den unterschied wirst du nicht sehen. Das geht dabei wirklich nur
> im ein paar Takte.

Danke :)
Auch wenn der Unterschied in dem Beispiel wohl kaum merkbar ist, wollte 
ich mir ganz gerne von vornherein angewöhnen sauberen Code zu schreiben. 
:)

Gruß
Tim0

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 10 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.