KnightRider - AVR

#5619546
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?
Gast #5619573
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?
#5619586
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".
#5619598
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
}
Moderator (Firma: Titel) Persönliche Seite #5619626
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
:
#5619632
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.
Moderator (Firma: Titel) Persönliche Seite #5619635
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?
#5619637
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.
#5619648
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.
#5619700
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)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren