Forum: Mikrocontroller und Digitale Elektronik KnightRider - AVR


von Mnb B. (poiuzt)


Lesenswert?

Hallo,

meine Aufgabe besteht darin, einen KnightRider zu programmieren:

* gegeben ist ein 8-bit Mikrocontroller
* auf zwei Ports soll mein KnightRider laufen A und B
* A wird als Ausgang konfiguriert


Mein Quellcode:
1
int main(void)
2
{
3
   DDRA = 0b11111111;  
4
   DDRB = 0b01010101;
5
6
         PORTA = 0b00000111;
7
   int i,j;
8
  
9
  while (1)    {
10
    
11
    if (i=0)    {
12
      PORTA = 0b00000001;
13
      _delay_ms(100);
14
      PORTA = 0b00000011;
15
      _delay_ms(100);
16
    }
17
    
18
    for(i=0; i<9; i++)    {
19
      PORTA = 0b00000111>>i;  
20
      _delay_ms(100);
21
    }
22
    
23
    for(j=0; j<9; j++)    {
24
      PORTA = 0b11100000<<j;    
25
      _delay_ms(100);
26
    }    
27
  }
28
}

Ich habe es bisschen umständlich gemacht aber es funktioniert dennoch. 
Laut meinem Praktikumsbetreuer kann ich die if und for Anweisungen 
kürzen und es auf eine Zeile reduzieren. Es muss ca. so aussehen:
1
PORTA = (((PINB & 0b01010101) | (~0b01010101))<<2);
Das wird aber nicht funktionieren, da ich die Zeile nicht verstehe und 
generell nicht weiß, wie genau es gekützt werden soll, damit in der 
while(1) genau diese Zeile steht.
Kennt sich jemand evtl damit aus oder kennt ein Tutorial (nur mit 
Erklärung) dazu?

von Dr. Sommer (Gast)


Lesenswert?

Mnb B. schrieb:
> if (i=0)    {

Das ist eine Zuweisung. Die Bedingung ist nie wahr. Selbst wenn es ein 
Vergleich wäre, wäre es falsch - i und j werden nicht initialisiert und 
enthalten zu Beginn zufällige Werte.

In den beiden for-Schleifen werden 3x sinnvolle Werte ausgegeben, in den 
restlichen 6 Durchläufen wird nur 0 geschrieben. Ist das Absicht?

von Mnb B. (poiuzt)


Lesenswert?

Dr. Sommer schrieb:
> Ist das Absicht?

Vermutlich. Die Idee war einfach von links nach rechts die LEDs zu PortA 
und dann zu B durchlaufen zu lassen. Die "Plätze" verschieben sich aber. 
Sprich wenn es bei 00001000 anfängt, muss es im nächsten Durchlauf 
00000100 sein. Also die Kette ist immer noch dieselbe aber die eins 
verschiebt sich solange, bis die Ursprungsform von 00001000 wiederkehrt 
und dasselbe für PortB.
Die Aufgabe besteht darin, exakt dasselbe durchzuführen, nur 
"einzeilig".

von Falk B. (falk)


Lesenswert?

@ Mnb B. (poiuzt)

>meine Aufgabe besteht darin, einen KnightRider zu programmieren:

Kaum. Eher ein Lauflicht, das wie beim KnightRider aussieht.

>* gegeben ist ein 8-bit Mikrocontroller

Der anscheinend ein AVR ist. Könnte man ja mal sagen, siehe 
Netiquette.

>* auf zwei Ports soll mein KnightRider laufen A und B

Warum 2 Ports?

>* A wird als Ausgang konfiguriert

Und was ist mit Port B?

>    if (i=0)    {

Ist eine ZUWEISUNG und KEINE Abfrage! Typische Falle bei C!
Aber wozu?

>    for(i=0; i<9; i++)    {
>      PORTA = 0b00000111>>i;

Kann man machen, aber warum nicht einfach ein Muster passend schieben, 
immer nur einen Schritt?


Eher so
1
int main(void) {
2
   DDRA = 0b11111111;  
3
   DDRB = 0b01010101;
4
5
   int i, muster;
6
  
7
  while (1)    {
8
    
9
    PORTA  = 0b00000011;
10
    _delay_ms(100);
11
    muster = 0b00000111;
12
  
13
    for(i=0; i<8; i++)    {
14
      PORTA   = muster;
15
      muster <= 1;
16
      _delay_ms(100);
17
    }
18
19
    PORTA  = 0b11000000;
20
    _delay_ms(100);
21
    muster = 0b11100000;
22
    
23
    for(i=0; i<8; i++)    {
24
      PORTA   = muster;
25
      muster >= 1;
26
      _delay_ms(100);
27
    }
28
  }
29
}

von Klaus R. (klaus2)


Lesenswert?

...und wenn man keine Glühlampen sondern LED benutzt (heutzutage ja sehr 
wahrscheinlich), fehlt der "Schweif" per SW PWM - das wäre dann Teil B 
der Hausaufgabe, mit dem du richtig Eindruck schinden könntest...

Klaus.

von Ingo L. (corrtexx)


Lesenswert?

Falk B. schrieb:
> PORTA  = 0b00000011;
>     _delay_ms(100);
>     muster = 0b00000111;
nettes Feature :)

von Mnb B. (poiuzt)


Lesenswert?

Klaus R. schrieb:
> ...und wenn man keine Glühlampen sondern LED benutzt (heutzutage ja sehr
> wahrscheinlich), fehlt der "Schweif" per SW PWM - das wäre dann Teil B
> der Hausaufgabe, mit dem du richtig Eindruck schinden könntest...
>
> Klaus.


Das kommt erst nächstes Jahr. Aber bis dato muss ich erstmal das 
verstehen.

von Mnb B. (poiuzt)


Lesenswert?

Falk B. schrieb:

> Warum 2 Ports?

Um die Schwierigkeit (im Praktikum) zu erhöhen.

Danke für den Quellcode.
Meine Version basiert halt auf Internetwissen, da mein Prof krank ist 
und erst nächstes Jahr kommt. Bis dato muss ich es dennoch irgendwie 
hinkriegen.

von Christopher B. (chrimbo) Benutzerseite


Lesenswert?

Falk B. schrieb:
>
1
>       muster <= 1;
2
>       ...
3
>       muster >= 1;
4
>

das ist übrigens Vergleichstatements die nicht ausgewertet werden. Ich 
gehe davon aus du meinstest <<= bzw. >>=

Gruß

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


Lesenswert?

Ich würde das mit einer Tabelle machen. Etwa so:
1
uint8_t muster[10] = {
2
   0b00000111,
3
   0b00001110,
4
   0b00011100,
5
   0b00111000,
6
   0b01110000,
7
   0b11100000,
8
   0b01110000,
9
   0b00111000,
10
   0b00011100,
11
   0b00001110
12
};
13
14
uint8_t i = 0;
15
16
int main(void) {
17
  DDRA = 0b11111111;  
18
 
19
  while (1)    {
20
    PORTA = muster[i];
21
    i++;
22
    if (i>9) i=0;
23
    _delay_ms(200);
24
  }
25
}

Das lässt sich dann auch ganz einfach ohne großartige Rechnereien an 
andere Muster anpassen:
1
uint8_t muster[18] = {
2
   0b00000001,
3
   0b00000011,
4
   0b00000111,
5
   0b00001110,
6
   0b00011100,
7
   0b00111000,
8
   0b01110000,
9
   0b11100000,
10
   0b11000000,
11
   0b10000000,
12
   0b11000000,
13
   0b11100000,
14
   0b01110000,
15
   0b00111000,
16
   0b00011100,
17
   0b00001110,
18
   0b00000111,
19
   0b00000011
20
};
21
:
22
:
23
    if (i>17) i=0;
24
:

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

@Christopher B. (chrimbo)

>>       muster >= 1;

>das ist übrigens Vergleichstatements die nicht ausgewertet werden. Ich
>gehe davon aus du meinstest <<= bzw. >>=

Uuups, erwischt ;-)

von Mnb B. (poiuzt)


Lesenswert?

Ausgehend von allen Versionen des Codes hier, welchen Ansatz muss ich 
für die while-Schleife verwenden, um beispielweise
1
 PORTA = (((PINB & 0b01010101) | (~0b01010101))<<2);
 zu bekommen?

Die Absicht der Aufgabe besteht darin, den Quellcode nur auf eine Zeile 
zu reduzieren, also:
1
 
2
int main(void) {
3
   DDRA = 0b11111111;  
4
   DDRB = 0b01010101;
5
6
   int i, muster;
7
8
   while(1) {
9
      PORTA = (((PINB & 0b01010101) | (~0b01010101))<<2);
10
   }

Da habe ich überhaupt nichts dazu.

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


Lesenswert?

Mnb B. schrieb:
> Die Absicht der Aufgabe besteht darin, den Quellcode nur auf eine Zeile
> zu reduzieren, also:
Da gibt es dann 2 Möglichkeiten:
1. Das läuft dann halt so schnell durch, dass du einen Logikanalyzer 
brauchst.
Oder
2. Lass die Zeilenumbrüche weg:
1
  while (1)    {
2
    PORTA = muster[i]; i++; if (i>9) i=0; _delay_ms(200);
3
  }
Voila, alles in einer Zeile... ;-)

Mnb B. schrieb:
> PORTA = (((PINB & 0b01010101) | (~0b01010101))<<2);
Was kommt da am Port B herein?

von Falk B. (falk)


Lesenswert?

@Mnb B. (poiuzt)

>Ausgehend von allen Versionen des Codes hier, welchen Ansatz muss ich
>für die while-Schleife verwenden, um beispielweise
> PORTA = (((PINB & 0b01010101) | (~0b01010101))<<2);
> zu bekommen?

Was soll denn PINB hier bewirken? Soll es als Zwischenspeicher dienen? 
Und warum PINB? Wenn schon, dann PORTA.

>Die Absicht der Aufgabe besteht darin, den Quellcode nur auf eine Zeile
>zu reduzieren, also:

Glaub ich nicht so ganz.


>      PORTA = (((PINB & 0b01010101) | (~0b01010101))<<2);

Das ist eine Bitmanipulation, wenn gleich ich den Sinn dahinter 
nicht verstehen.

von Mnb B. (poiuzt)


Lesenswert?

Falk B. schrieb:

> Was soll denn PINB hier bewirken? Soll es als Zwischenspeicher dienen?
> Und warum PINB? Wenn schon, dann PORTA.

Nee aber PORTB war definiert als 01010101. (Kann ich daraus DDRB= 
0b01010101 schlussfolgern?) Daher habe ich PINB mit reingenommen. Weil 
sonst sehe ich keinen Sinn in der Aufgabe Port B überhaupt zu erwähnen.

von Stefan F. (Gast)


Lesenswert?

Kleine Klugscheißerei am Rande:

Das Auto mit dem Lauflicht heißt K.I.T.T.

Der KnightRider ist der fahrende Ritter, also der Mann. Der hatte keine 
Lichter am Körper bzw. an seiner Kleidung.

von Klaus R. (klaus2)


Lesenswert?

Doch! Beim Mauerfall hatte er eine "beeindruckend blinkende Lederjacke" 
an! Aber streng genommen war das sein alter ego als Künstler, da der Job 
bei der FFRUV nicht einträglich genug war...

Klaus.

von Stefan F. (Gast)


Lesenswert?

Klaus R. schrieb:
> Doch! Beim Mauerfall hatte er eine "beeindruckend blinkende Lederjacke"
> an!

Die fand ich ziemlich bescheuert.

von Stefan F. (Gast)


Lesenswert?

Hier ist eine winzige Schaltung mit ATtiny13 für 12 Leuchtdioden:
http://stefanfrings.de/knightrider/index.html

Es ist sogar noch ein Pin frei für Erweiterungen - Hoho!

Wenn man Glühlampen (über SSR angesteuert) verwendet, sieht das richtig 
gut aus.

von Falk B. (falk)


Lesenswert?

@Klaus R. (klaus2)

>Doch! Beim Mauerfall hatte er eine "beeindruckend blinkende Lederjacke"
>an! Aber streng genommen war das sein alter ego als Künstler, da der Job
>bei der FFRUV nicht einträglich genug war...

Aha!!! Also ist der auch beim Verfassungsschutz rausgeflogen! Hat der 
seinen Chef für blöd erklärt oder der Mechanikerin (Name?) an den 
Hintern gefaßt? ;-)

(FFRUV = Foundation für Recht und Verfassung, so jedenfalls die 
denglische Übersetzung)

(dum didel dum, dum didel dum, dum didel dum, dum, dum . . . . . dum 
dum)

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.