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.
Andre G. schrieb: > Irgendwie funktioniert modulo nicht so wie es soll. Da es seit Jahrzehnten bei allen außer dir funktioniert, wirst wohl DU etwas falsch gemacht haben. Als zeig' ein konkretes Minimalprogramm, was das "Problem" für alle nachvollziehbar macht.
:
Wiederhergestellt durch Moderator
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.
Das ist kein Minimalprogramm. BTW: wenn du sowas wie Variable1, variable2, variable3, … hast, möchtest du ein Array nehmen
:
Bearbeitet durch User
Dirk B. schrieb: > Das ist kein Minimalprogramm. Wie schon gesagt, von Relevanz ist nur "uint8_t Digit1 = (Number % 10);" in der Zeile 429.
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.
:
Wiederhergestellt durch Moderator
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?
S. L. schrieb: > Stimmt diese Abfrage in 423..427? Ist mir auch gerade aufgefallen. Da sollte wohl ein > stehen.
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.
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. Man hätte festgestellt, dass das Ergbnis deiner Fehleranalyse falsch war. Dann hätte man weiter suchen müssen.
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...
:
Wiederhergestellt durch Moderator
an Andre G.:
Sie sollten es positiv sehen:
> Das gerichtet und es läuft!
Offenbar war nur dieser eine Fehler im Programm.
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.
Andre G. schrieb: > 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. Wieso das Rad nochmal neu erfinden - dazu die 5-eckige Form? printf() und Konsorten sind keine Option? just my 2ct
Joe L. schrieb: > printf() und Konsorten sind keine Option? 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.
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.
:
Bearbeitet durch User
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. >> [...]
:
Bearbeitet durch User
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()
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
Also die "große Zahl" in einen String umwandlen und dann einfach per index (ein String ist ja ein char array) oder Pointer auf die gewünschte Stelle zugreifen? Clever!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.