Forum: Mikrocontroller und Digitale Elektronik Kleine Aufgabe und AvR Rechnet falsch?


von Patrick90 (Gast)


Lesenswert?

Hi ich hab nen kleines Programm geschrieben das einfach 4 bits also 
00001111
immer weiter nach links schieben soll und die bits die beim 8ten bit 
rausfallen sollen wieder im ersten bit reinfallen also
11110000
11100001
usw

Nun hab ich mir das ganze so aufgebaut das es logischer weise 
funktionieren müsste allerdings scheint avr irgenetwas komplett falsches 
zu tuhen D: 11100001= 240-15(=225) avr errechnet mir aber 223
Warum tut er dies?


1
//Schieber
2
#include <avr/io.h>
3
int f[3];
4
int main (void){
5
6
7
8
up:
9
f[1]=15;
10
f[2]=15;
11
f[3]=0;
12
13
14
while (f[3]<=4){
15
16
PORTB=f[1];
17
f[1]=f[1]*2;
18
f[3]++;
19
}
20
21
22
while (f[3]>=3){
23
24
f[1]=f[1]-f[2];
25
f[2]=f[2]*2;
26
PORTB=f[1];
27
f[3]--;
28
}
29
goto up;
30
return 0;
31
}

von raketenfred (Gast)


Lesenswert?

Patrick90 schrieb:
> up:
[...]
> goto up;
Pfui, nimm ne while(true){} , ist ganz schlechter stil

Ebenso rast dein Programm dadurch, ich denke mal, dass du es noch 
nichtmals flackern siehst, sondern die LEDs nur auf einer gewissen 
helligkeit sind?!

1. Tipp:
kein goto
2. Tipp: nach dem setzten von Portb _delay_ms(XX); verwenden
3. Tipp: bit schubserein verwenden, ich denke das ist eleganter als 
deine jetztige methode
4. anstatt int wüde ich byte verwenden

von Patrick90 (Gast)


Lesenswert?

Nun danke für die Tipps aber die sind nun banal für mich btw bei der 
2ten schleife soll <=1 stehen nicht 3

es ist nur verwirrent das avr das nicht richtig berechnen kann =/

von kolabier (Gast)


Lesenswert?

nimm bitoperationen

bsp. für 10x shiften:
1
unsigned char value = 0x0f;
2
unsigned char upperbit;
3
int i;
4
for (i=0; i<10; i++)
5
{
6
    upperbit = value & 0x80;        // oberstes bit merken
7
    value <<= 1;                    // nach links shiften
8
    if (upperbit) value |= 1;       // wenn oberstes bit gesetzt war, unterstes bit setzen
9
10
}

von ... (Gast)


Lesenswert?

Schon mal was von einrücken gehöhrt?
Schon mal der erste Fehler:
1
int f[3];
2
f[3]=0;
Die Sache mit Arrays und Indizes solltest Du Dir nochmal anschauen.
An welcher Stelle im Program erhällst Du 223. Am Besten Du nimmst Dir 
Bleistift und Papier und spielst selber mal µC. Btw., Du weist aber 
schon, daß int 16 Bit hat?

von .../... (Gast)


Lesenswert?

// schiebt ein Byte bitweise nach links und fügt links herausfallende 
Bits
// rechts wieder ein.

uint8_t i;
i = irgendetwas;

while(1)
  {
  if (i & 0x80)    // das Bit.7 testen, wenn gesetzt
    {
    i << 1;    // nach links schieben und
    i++;    // das links rausgefallende Bit rechts wieder einfügen
    }
  else      // wenn Bit.7 nicht gesetzt,
    {
    i << 1;    // dann nur schieben
    }

  machwas_mit_dem_Byte;
  }

von ... (Gast)


Lesenswert?

Noch ne Frage. Wie kommst Du auf "240-15"??? Das kommt in Deinem 
Programm nicht vor.

von Patrick90 (Gast)


Lesenswert?

fehler gefunden ^^ bei ersten while bedingung 3 anstatt 4

von Björn C. (bjoernc) Benutzerseite


Lesenswert?

Patrick90 schrieb:
> Nun danke für die Tipps aber die sind nun banal für mich btw bei der
> 2ten schleife soll <=1 stehen nicht 3
>
> es ist nur verwirrent das avr das nicht richtig berechnen kann =/

solche Aussagen sollte man sich schnell abgewöhnen - denn meistens sitzt 
der Fehler 50 cm vor dem Bildschirm. Es kommt zwar vor das uC's oder 
bestimmte Cores Fehler aufweisen, nur sind diese sehr sehr selten und 
meistens schon im DB dokumentiert. Steht dorts nichts sollte man den 
Fehler exakt identifizieren - und zwischen dem C-Sourcecode und dem 
Programmieren des uC's gibts noch einige Stationen wo etwas schief gehen 
kann ;).

von asdf (Gast)


Lesenswert?

Patrick90 schrieb:
> 11110000
> 11100001

da du den datentyp int geaehlt hast, ist f[] 2 byte gross. ausserdem 
wird eine multiplikation niemals durch das carry rotieren.
sonst wuerde ja aus einer gerade zahl (LSB = 0) irgendwann eine ungerade 
werden (LSB = 1)

deine erste schleife wird 5 mal durchlaufen, das ist dir klar?

debugge das programm schritt fuer schritt und beobachte die 
registerinhalte. an welcher stelle ist f[1] == 223? die info solltest du 
noch dazuschreiben.

das goto eine todsuende ist, wurde ja schon geschrieben.

von Martin (Gast)


Lesenswert?

f[3] könnte problematisch werden, wenn danach noch eine variable kommt. 
Dein Index geht nur von 0 - 2.

von W.S. (Gast)


Lesenswert?

Mein Gott, ihr könnt es aber auch kompliziert machen.

  MOVLW  B'00001111'
  MOVWF  MeineZelle        ; MeineZelle vorbelegen

zyklus:
  RLF    MeineZelle,W      ; MSB ins Carry
  RLF    MeineZelle,F      ; Carry ins LSB
  GOTO   zyklus

Sowas braucht beim PIC nur 800 ns, wovon der GOTO die Hälfte frißt.

Apropos GOTO, Ich halte das GOTO Statement sowohl bei C als auch bei 
Pascal durchaus nicht für schlechten Stil. Wo man eine Ewigschleife zu 
drehen beabsichtigt, da ist GOTO genau richtig!

Auf alle Fälle ist das besser und lesbarer als sowas wie while(true) 
{....}

oder gar while (1)....


W.S.

von kolabier (Gast)


Lesenswert?

Patrick90 schrieb:
> fehler gefunden ^^ bei ersten while bedingung 3 anstatt 4

Ich liege am Boden.
Dein Code macht überhaupt nicht, was er soll. Er ist umständlich, 
langsam, fast unlesbar, und funktioniert nur mehr oder weniger zufällig 
für Zahlen <=15 als Startwert.
Arrays scheinen dir auch sehr zu gefallen, einfache Variablen sind ja 
schließlich langweilig.

Dann geben dir 2 Leute Tips, wie man Linksshifts mit Carry korrekt und 
auf einfache Weise implementiert, das interessiert dich aber nicht die 
Bohne.

Ich bin weg. Luft abgelassen.

von Mark B. (markbrandis)


Lesenswert?

Kleine Aufgabe und Mensch programmiert falsch. ;-)

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.