Probleme beim Dividieren

Gast #47700
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);
  }
}
Gast #47701
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.
Gast #47702
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?
Gast #47704
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)
Gast #47707
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
Gast #47708
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.
Gast #47709
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
Gast #47710
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
Gast #47711
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);
  }
}
Gast #47713
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
Gast #47715
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
Gast #47719
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
Gast #47720
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.

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