www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Probleme beim Dividieren


Autor: Julius Krebs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
  }
}

Autor: OliverK (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Julius Krebs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: OliverK (Gast)
Datum:

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

zahlausgeben(0,e3,0);

aus?

Autor: Julius Krebs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: OliverK (Gast)
Datum:

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

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

Autor: Julius Krebs (Gast)
Datum:

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

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: OliverK (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Marcel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Julius Krebs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
  }
}

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Controller?

Matthias

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

Matthias

Autor: Julius Krebs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Björn (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

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

Autor: Julius Krebs (Gast)
Datum:

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

Autor: Steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Julius Krebs (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.