Forum: Mikrocontroller und Digitale Elektronik Probleme beim Dividieren


von Julius Krebs (Gast)


Lesenswert?

Es geht um eine einfache Division zweier Zahlen. Ich habe das Ganze in C
realisiert. Ist die Zahl, mit der dividiert wird größer als 4 führt das
zu einem Komplettstillstand im Mikrocontroller.

Hier ist ein Ausschnitt des entsprechnden Programms. Da Ziel ist
besteht darin eine Zahl auf ein Zahlendisplay auszugeben. Das Problem
besteht darin, die auszugebende Zahl in ihre Bestandteile (Einer,
Zehner usw.) aufzuspalten.

int main(void)
{
  char z,z2,z3,e1,e2,e3;
  outp(255,DDRA);
  outp(255,DDRD);
  outp(255,DDRC);
  z=1;
  z2=1;
  for(;;)
  {
    z++;

/* Folgende Zeilen stellen das Problem dar.
    e1=z-((z/10)*10); //Die "Einer" einer dreistelligen Zahl werden
ermittelt
    e2=z/10-((z/100)*10); //Die "Zehner" einer dreistelligen Zahl
werden ermittelt
    e3=z/100; //Die "Hunderter" einer dreistelligen Zahl werden
ermittelt
    */
    idle(100);
    outp(z2,PORTC); //Hier tritt der Fehler auf!
    zahlausgeben(0,e3,0);
    idle(100);
    zahlausgeben(1,e2,0);
    idle(100);
    zahlausgeben(2,e1,0);
  }
}

von OliverK (Gast)


Lesenswert?

Wofür ist eigentlich z2 da? Ausßer einer einmaligen Initialisierung wird
damit doch nichts gemacht?

Du solltest statt
char z,z2,z3,e1,e2,e3;

lieber
unsigned char z,z2,z3,e1,e2,e3;

schreiben.

von Julius Krebs (Gast)


Lesenswert?

Ich hatte bereits unsigend vor der Variablendeklaration stehen, ohne
Erfolg. Auf die einzelnen Variabeln müsst ihr glaube ich nicht näher
eingehen. Es ist wirklich nur ein billiges Testprogramm. Tatsache ist
mein geschildertes Problem. Dafür muss es doch eine einfache Erklärung
geben, oder?

von OliverK (Gast)


Lesenswert?

Der Fehler liegt nicht immer da, wo man ihn vermutet. Wie sieht denn
Deine Funktion

zahlausgeben(0,e3,0);

aus?

von Julius Krebs (Gast)


Lesenswert?

Der Fehler kommt auch zustande, wenn ich den Funktionsaufruf weglasse.
Der Mikrocontroller hängt sich im Grunde genommen an der Ausgabe des
errechneten Wertes an den Port. (Siehe Kommentar im Quellcode)

von OliverK (Gast)


Lesenswert?

Ja aber bei
outp(z2,PORTC); //Hier tritt der Fehler auf!

wird z2 doch gar nicht berechnet! z2 ist mit 1 initialisiert.

von Julius Krebs (Gast)


Lesenswert?

Da hast du natürlich Recht. Denke dir einfach die Variable e2 an diese
Stelle. Es kommt das gleiche bei raus.

von Björn (Gast)


Lesenswert?

Moinsen,
kann dein Problem leider auch nicht lösen, aber ich sitzte jetzt seit
10 min vor deinem Code und komme einfach nicht darauf wie du damit
irgendwelche Dezimalstellen berechnest?! e1 und e2 sind doch immer NULL
- oder bin ich zu blöde??? Ich weiß es geht nicht darum aber um was
geht es denn...
schreib doch einfach mal ne Konstante (in deinem Fall 1) in den
Funktionsaufruf und ziehe den aus der for-Schleife der muss ja
scheinbar eh nicht mehrfach aufgerufen werden.
Ausserdem ist mir nicht ganz klar, warum das ein  Problem mit dem
dividieren seien soll?

Fragen über Fragen
ich mach mir mal nen Wein auf
in diesem Sinne
Prost

von OliverK (Gast)


Lesenswert?

Hi Björn,

zu Deinem Zeitpunkt war meine Wein leider schon alle :-(

Alles in Allem muß ich sagen, daß ich froh bin, meine AVRs nur in
Assembler zu programmieren. Ich verfolge schon eine Weile die ganzen
Probleme mit diversen freien C-Compilern. Das ist ein gewagtes Spiel,
das ich nicht spielen möchte.

Ich schmeiße das Handtuch bei obigem Problem.

von Marcel (Gast)


Lesenswert?

Mahlzeit,

zu Deinem Problem mit den Einern, Zehnern, ...(stimmt e2 überhaupt?).
Mach es doch einfach mit der Modulo-Division.

einer = ergebnis%10;
zehner = (ergebnis/10)%10;
..

Gruß Marcel

von Matthias (Gast)


Lesenswert?

Hi

mal davon abgesehen das man outp() nicht mehr verwenden sollte kan ich
keinen Grund entdecken warum dein code nicht funktionieren sollte.
Kannst du mal ein Stück Code posten das den Fehler aufweist und
compiliert werden kann.

BTW:
Das e1=z-((z/10)*10); zu e1=0; optimiert wird ist dir klar?

Matthias

von Julius Krebs (Gast)


Lesenswert?

Dass der Compiler den Code so stark „optimiert“ bis am Ende der
Rechnungen jeweils 0 raus kommt, wusste ich nicht. Ich hatte gehofft,
dass alles schön nach der Reihenfolge abgearbeitet wird.
Es folgt ein für sich lauffähiges Testprogramm. Darin sollte mein
Problem eigentlich deutlich werden.

#include <io.h>
#define F_CPU 8000000
void idle(unsigned int milli)
{
    unsigned int z,z2;
    for(z=0;z<milli;z++)
    for(z2=0;z2<(F_CPU/1000);z2++){/*waiting 1 Millisec*/}
}
int main(void)
{
  unsigned int a,b;
  outp(255,DDRC);
  a=1;
  for (;;){
    a++;
    if (a == 2500)
      a=1;
    b = a/10; //Setzt mal spaßenshalber statt "10" "4" ein. Ihr
werdet sehen, dass bei diesem Wert alles vollkommen problemlos läuft.
    outp(b,PORTC);
    idle(100);
  }
}

von Matthias (Gast)


Lesenswert?

Hi

Controller?

Matthias

von Björn (Gast)


Lesenswert?

Moinsen,
also ich habe den Code mal bei mir in den CCS (PIC) reingehauen und da
läuft das Ding (in VC++ auch).
Wie kommst du denn darauf das es da zu Absturß kommt? Hast du das
simuliert oder richtig in einen uC gebrannt?
Du darfst nicht vergessen das eine Division durch eine Zahl 2^n (also
4, 8, 16 ...) nur einfache Schiebeoperationen ( nach rechts schieben)
sind und das geht relativ fix.
Wobei wenn du durch 10, 11 , oder 17 teielst muss der Compiler doch
einiges mehr an Code umsetzten. Das dauert halt.....(is ja wohl ein
8-Bit uC)
Schau dir doch mal dein Assemblerlisting an.
Wenn du den Code simuliert hast, dann führe ihn nicht im
Einzelschrittmodus aus sondern setzte einen Breakpoint auf
outp(b,PORTC).
Mal sehen ob's dann klapp

In diesem Sinne
Hummel, Hummel

von Matthias (Gast)


Lesenswert?

Hi

compiliert für einen ATmega16 funktioniert dein Code.
dito für einen AT90S8515
(aktueller WINAvr)

Matthias

von Julius Krebs (Gast)


Lesenswert?

Ich habe in meiner Verzweiflung den Chip (es war ein ATmega 16) mit
einem anderen ausgetauscht. Nachdem dies auch nichts brachte steckte
ich den Chip wieder zurück, und da o Wunder ging es auf einmal. Ich
kann mir das absolut nicht erklären. Denn wäre etwas an der Hardware
defekt gewesen hätten ja eigentlich deutlich mehr Störungen anfallen
müssen.

Wie auch immer, jetzt läuft alles. Euch vielen Dank für die Tips.

Übrigends funktionieren unten stehende Code zur Berechnung der
Dezimalwerte so wie ich es mir gedacht habe. Nix da mir 0!

    e1=z-((z/10)*10); //Die "Einer" einer dreistelligen Zahl werden
ermittelt
    e2=z/10-((z/100)*10); //Die "Zehner" einer dreistelligen Zahl
werden ermittelt
    e3=z/100; //Die "Hunderter" einer dreistelligen Zahl werden
ermittelt

von Björn (Gast)


Lesenswert?

JAAAA
Schande über mein Haupt ist ja ein int und kein Gleitkomma....
Ich sach ja vielleicht bin ich zu DOOF. Das darf der Compiler ja
garnicht optimieren.
in diesem Sinne

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Warum schreibst du statt
  z-((z/10)*10)
nicht einfach
  z % 10
?

von Julius Krebs (Gast)


Lesenswert?

Ich bin in C noch nicht so bewandert. Du hast natürlich Recht, dass es
mit dem Divisionsrest einfacher geht.

von Steffen (Gast)


Lesenswert?

So ein Problem hatte ich auch schon mal. Allerdings in ASM. Ich hab
Tagelang den Fehler gesucht warum mir der Prozessor an einer bestimmten
Stelle abschmiert.

Im Programm konnte ich keinen Fehler finden und der Prozessor war auch
OK.

Nach drei Tagen hab ich dann den Fehler dann gefunden. Ich hatte eine
kaum sichtbare Lötbrücke auf der Platine. Wenn ich den Port auf High
gesetz habe, habe ich den dadurch gegen Masse kurzgeschlossen und die
Spannung ist kurz zusammengebrochen --> Reset.

Vielleicht war´s so etwas?

Steffen

von Julius Krebs (Gast)


Lesenswert?

Ich hatte das Glück das Starterboard gesponsert bekommen zu haben. Und
da ist eine nicht sichtbare Lötbrücke unwahrscheinlich. Außerdem war
mein Problem ein rein mathematisches. Ich vermute, dass bei den
Standarteinstellungen des AVRs irgendetwas faul war. Wirklich
rausfinden werde ich es wohl nie.

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.