[AVR] Modulo funktioniert nicht richtig

OP #7407970
Lesenswert?

Schönen Samstag Nachmittag,

ich habe gerade ein kleines Problem und komme irgendwie nicht weiter.

Irgendwie funktioniert modulo nicht so wie es soll. Weder mit dem a % b noch "von Hand ausprogrammiert" ( damit meine ich a-(b*(a/b)) ).

Bei a < b funktioniert alles. Sobald a > b ist funktioniert es nicht mehr, ich bekomme nur noch 0 als Ergebniss.

a ist ein uint16_t und b ist ein uint8_t.

Ich verwende AtmelStudio 6 und einen AtMega8.

Ich wäre um jede Hilfe dankbar.

OP #7408006
Lesenswert?

Wie gewünscht, Code im Anhang.

Ihr werde nur nicht viel damit anfangen können, die Ausgabe erfolgt über 4 doppelte Siebensegment Module. Die Module haben je zwei gemeinsame Anoden (eine für die linke und eine für die rechte Stelle), die Segment-Kathoden sind alle zusammengeschlossen und gehen über Vorwiderstände direkt auf den µC. Die gemeinsamen Anoden gehen direkt auf den µC.

Ja, das könnte man auch eleganter lösen aber darum geht es jetzt nicht, es geht mir nur um die modulo Sache in Zeile 429. Ja, die Funktion "ReturnDigitFromNumber" ist noch nicht fertig, ich wollte erstmal nur die Einerstelle ausgeben, dann wenn das klappt auch noch die Zehnerstelle und so weiter.

Angehängte Dateien:
#7408017
Lesenswert?

Andre G. schrieb:

Wie gewünscht, Code im Anhang.

Nein, das ist ganz und garnicht "wie gewünscht". Das ist erstens kein Minimalprogramm und zweitens...

Ihr werde nur nicht viel damit anfangen können, die Ausgabe erfolgt über 4 doppelte Siebensegment Module.

...auch nicht problemlos für jeden nachvollziehbar. Den Grund nennst du ja bereits selber: Es ist eine konkrete Hardware nötig, um das Problem überhaupt erkennen zu können. Was doch sehr stark dafür spricht, dass nicht die Modulofunktion an sich das Problem sein kann, sondern nur deine Verwendung selbiger im Kontext deiner Anwendung falsch ist.

OP #7408021
Lesenswert?

Ok.

Ich wollte mit dem modulo eine große Zahl in einzelne Ziffern aufteilen um diese einzeln auf den jeweiligen 7 Segmentanzeigen darstellen zu können.

Das Darstellen von einzelenn Ziffern (0 bis 9) funktioniert, aber wenn ich von einer größeren Zahl die Einerstelle "auslesen" will dann funktioniert das nicht.

Um die Einerstelle von z.B. 12345 zu bekommen kann man doch 12345%10 nehmen, oder? Das würde 5 entsprechen richtig? Modulo ist doch "der Rest der Division" (vereinfacht gesagt).

Oder habe ich das was falsch verstanden?

OP #7408028
Lesenswert?

Yalu X. schrieb:

S. L. schrieb:

Stimmt diese Abfrage in 423..427?

Ist mir auch gerade aufgefallen. Da sollte wohl ein > stehen.

Danke! DANKE!!1

Das gerichtet und es läuft!

Also funktioniert % einwandfrei, nur der "Rest" drumherum.

Bei einem "Minimalbeispiel" wo das Ergebniss von der Modulo-Operation direkt z.B. über UART ausgegeben wird oder einfach direkt auf einen PORT wäre das nicht aufgefallen.

Eine Nacht drüber schlafen und DEN GANZEN CODE ansehen hätte in dem Fall geholfen.

Entschuldigung dass ich eure Zeit hier mit meiner Inkompetenz verschwendet habe.

#7408035
Lesenswert?

Andre G. schrieb:

Bei einem "Minimalbeispiel" wo das Ergebniss von der Modulo-Operation direkt z.B. über UART ausgegeben wird oder einfach direkt auf einen PORT wäre das nicht aufgefallen.

Das hätte immerhin gezeigt, dass Modulo funktioniert. Du also de facto den Fehler an der falschen Stelle suchst...

Entschuldigung dass ich eure Zeit hier mit meiner Inkompetenz verschwendet habe.

Es gibt schlimmeres. Du hast immerhin erkannt, dass der Fehler bei dir lag (und mit Modulo rein garnix zu schaffen hatte).

Nicht jedem gelingt es, so mit eigenen Fehlern umzugehen. Insofern besteht zumindest Hoffnung...

#7408048
Lesenswert?

Bravo. Du hast erfolgreich widerstanden, eines der tausenden Beispiele im Web anzuschauen, wie andere eine 8-stellige Anzeige multiplexen. 500 Zeilen hat bestimmt keiner geschafft.

Das mit den Anoden direkt an den IO-Pins solltest Du nochmal überdenken. Als Operating Conditionen werden für den ATmega8 max 20mA angegeben. Bei 7 Segmenten sind also max 2,8mA zulässig. 8 Digits multiplexen bedeutet, sie leuchten nur 12,5% der Zeit. Das ergibt dann effektiv 0,35mA je LED, dürfte also recht dunkel sein. Daß LEDs nie direkt an Ports gelegt werden dürfen, sondern immer einen Vorwiderstand zur Strombegrenzung benötigen, setze ich mal voraus.

#7408083
Lesenswert?

Geht auch mit sehr viel weniger Speicher:

1
#include <stdio.h>
2
#include <stdint.h>
3
typedef uint8_t uint8;
4
typedef uint16_t uint16;
5

6
uint8 toDigits(uint16 number, uint8* digits) {
7
  uint8 ret = 0;
8
  do {
9
    digits[ret] = number%10;
10
    ret++;
11
  } while((number = number/10) > 0);
12
  return ret;
13
}
14

15
void main(void) {
16
  uint16 number = (uint16)54321;
17
  uint8 digits[5];
18
  
19
  uint8 count = toDigits(number, digits);
20
  
21
  for (uint8 i = count; i > 0; i--) {
22
    printf("%c", '0'+ digits[i-1]);
23
  }
24
  printf("\n");
25
}

Die printf Ausgabe ist nur zu Kontrolle, auf einem µC versuche ich printf bzw. sprintf zu vermeiden.

#7408150
Lesenswert?

Stefan F. schrieb:

Wahrscheinlich hat er sich gedacht: printf() braucht 1,5 kB Flash, das ist gar nicht gut. Und dann hat er 1,4 kB selbst programmiert, um das "Problem" zu umgehen.

Was soll ich darauf antworten? Ihr habt natürlich alle recht ...

Aber wie wärs zwischendurch mal mit "The Zen of Python" - eine Sammlung von 19 "Leitprinzipien" zum Schreiben von Computerprogrammen, nicht nur in Python? Der Software-Ingenieur Tim Peters formulierte diese Leitprinzipien und veröffentlichte sie 1999 auf der Python-Mailingliste.

[https://mail.python.org/pipermail/python-list/1999-June/001951.html]

Nicht, dass ich Python sonderlich mag, aber offensichtlich werden diese Prinzipien in manchen Kreisen also so wichtig angesehen, dass (moderne) Python-Interpreter auf

import this

antworten mit:

[...] Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. [...]

Gast #7408335
Lesenswert?

Wenn man keinen Debugger verwenden kann, bietet sich eine serielle Schnittstelle an, auf der man mit printf() den Inhalt von Variablen ausgeben kann.

Bei Arduino gehört das ja schon zur Grundausstattung*. Für Projekte ohne Framework hilft meine Vorlage zur Anregung: http://stefanfrings.de/avr_hello_world/index.html

Die Soft-Serial Version (in HelloTiny) eignet sich auch gut für Fälle, wo die seriellen Ports des Mikrocontrollers schon alle belegt sind. Eine Ausgabe auf einem einzelnen freien I/O Pin lässt sich fast immer leicht hinzufügen.

*) allerdings mit Serial.print()

Persönliche Seite #7408400
Lesenswert?

Macht villeicht Spaß, das Rad immer wieder neu zu erfinden, aber Umwandlung in Dezimalstring gibt's doch schon:

1
#include <stdint.h>
2
#include <stdlib.h>
3

4
void ausgabe_string (const char*);
5

6
void ausgabe_u16 (uint16_t n)
7
{
8
    static char str[6];
9
    ausgabe_string (utoa (n, str, 10));
10
}
11

12
int main (void)
13
{
14
    ausgabe_u16 (1234);
15
    ausgabe_u16 (0);
16
}

https://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#gad50d835af7e358518fd100179732e948

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