putint funktioniert auf den klassischen Controllern genau so, wie es soll. Getestete Conroller waren ATmega328p, ATMega168, ATtiny44 und ATtiny2313.
Binde ich genau denselben Code nun in der tinyAVR 0/1 series ein (getestete Controller ATtiny214 und ATtiny1604), dann gibt mir putint nur Zahlen von 0..9 korrekt aus, bei Werten oberhalb von 10 "spinnt" er herum zählt einfach die Ascii-Zeichen weiter, die nach Ascii-9 kommen.
Für 10 also den Doppelpunkt, für 11 den Strichpunkt etc.
Wo liegt hier der Hund begraben?
Ich gehe schlicht davon aus, dass in meinem putint etwas "unsauber" ist, aber ich finde das nicht !
By the way:
die aufgerufene Funktion my_putchar(uint8_ch) funktioniert problemlos, einzelne Aufrufe in der Art:
MPLABX und ein PICKIT4 oder SNAP zu nehmen und den Code im Singlestep
durchzugehen ist zuviel verlangt?
Mir ist der Aufwand für die kleinen tinyAVR series 0/1 zu groß und ich werde mir hierfür kein PicKit4 zulegen (ich habe nur einen alten PicKit2 für die PIC Controller). MPLAB ist mir, wie ich in einem anderen Thread schon geschrieben hatte, zu groß und zu "schwerfällig", vor allem, wenn man sowieso nach guter alter (veralteter) Sitte sich seine Makefiles selbst zusammen bastelt und das ganze damit auch noch komplett auf der Konsole lauffähig sein soll.
Im "Normalfall" bin ich eher mit STM32 unterwegs, hier dann mit einen originalen ST-Link und Debugger.
Von daher erübrigt sich die Frage nach dem zu viel verlangt sein.
Außerdem hoch verrückt: Nach der Installation von avr-gcc 12.2.0 macht putint das, was es soll. Also laß ich diesen Compiler installiert.
Hier mal die Diskussion zu dem ATTiny26 Bug:
Beitrag "Problem mit ltoa"
Danke Peda (und das Danke meine ich auch uneingeschränkt als Danke). ltoa habe ich nicht ausprobiert, aber itoa. Witzigerweise funktioniert das mit der Version 7.3.0 !!!
Aber das Problem hat sich mit der Version 12.2.0 jetzt eh erledigt. Ich hatte noch nie einen wirklich aktuellen avr-gcc installiert gehabt, weil ich mir bisher damit dann immer andere Probleme eingefangen hatte.
habe ich mir dort den Thread und dem Problem mit der Adressierung sehr aufmerksam durchgelesen.
Danach habe ich meinen eigenen Code genauer angesehen (und natürlich wieder verstanden was ich da gemacht habe, auch wenn es nicht kommentiert ist - ich sollte mehr sprechende Variablennamen verwenden).
Nimmt man das Array zz[] mit den Zehnerpotenzen aus der Funktion heraus und macht dieses Array global, funktioniert putint wie gewünscht auch unter avr-gcc 7.3 .
Allerdings darf das Array nicht als static definiert werden, weil auch dann dieselbe Fehlfunktion auftritt.
Nimmt man das Array zz[] mit den Zehnerpotenzen aus der Funktion heraus
und macht dieses Array global, funktioniert putint wie gewünscht auch
unter avr-gcc 7.3 .
Nun, dann wird es im Initcode vor Main geladen.
Innerhalb einer Funktion wird es aber erst direkt beim Eintritt geladen, d.h bei jedem Eintritt neu.
Man könnte es auch per PROGMEM in den Flash legen, spart dann SRAM ein.
Ein Fehler im Chip ist weiterhin nicht auszuschließen, d.h. eine Instruktion hat einen Seiteneffekt. Der avr-gcc 12.2.0 könnte diesen Befehl anders realisiert haben, so daß der Bug sich nicht auswirkt.
Ein Bug im avr-gcc 7.3 erscheint mir unwahrscheinlich, da ja ATmega168 usw. gehen.
Probier doch mal den Code zu minimieren und schau Dir dann mal an was der Compiler daraus macht. So als Komplettwust wird das niemand verstehen können.
So als Skizze würde ich das wie folgt machen:
void print_ziffer(int *zahl, const int stelle, int *print_null)
{
int cnt=0;
while (zahl>=stelle) {
cnt=cnt+1;
}
if ((cnt!=0) || (*print_null!=0)) {
my_putchar(cnt+'0');
*print_null=1;
}
}
Das rufst Du dann so auf:
void print_zahl(const int zahl_)
{
int zahl=zahl_;
int print_null=0; //keine führenden Nullen
print_ziffer(&zahl, 10000, &print_null);
print_ziffer(&zahl, 1000, &print_null);
print_null=1; //Ab der "einer"-Stelle führende Nullen
print_ziffer(&zahl, 100, &print_null);
my_putchar('.');
print_ziffer(&zahl, 10, &print_null);
print_ziffer(&zahl, 1, &print_null);
}
Damit hast du das Problem in kleinere Teilprobleme zerlegt und kannst sehen wo was schief läuft. Nebenbei brauchst Du da auch kein LPM. Funktionsaufrufe sind auch was, dass der Compiler gut auflösen kann.
void print_ziffer(int *zahl, const int stelle, int *print_null)
...
1
cnt=cnt+1;
1
*zahl=*zahl-stelle; //Fehlte vorher.
}
ich werde deine Vorschläge ausprobieren und sehen, wie groß der Code wird. In einem ATtiny214 hat man nur 2 kByte Speicher, von daher bin ich da mit der Codegröße extrem geizig.
In jedem Fall werde ich die Variablennamen ändern, damit man die Funktion besser verstehen kann.
Mir ist der Aufwand für die kleinen tinyAVR series 0/1 zu groß und ich
werde mir hierfür kein PicKit4 zulegen (ich habe nur einen alten PicKit2
für die PIC Controller). MPLAB ist mir, wie ich in einem anderen Thread
schon geschrieben hatte, zu groß und zu "schwerfällig", vor allem, wenn
man sowieso nach guter alter (veralteter) Sitte sich seine Makefiles
selbst zusammen bastelt und das ganze damit auch noch komplett auf der
Konsole lauffähig sein soll.
[...]
Von daher erübrigt sich die Frage nach dem zu viel verlangt sein.
Professionell ist anders. Aber ok, die Chance, wirklich die Stelle zu finden, wo das Problem genau ist, hast Du Dir damit genommen. Ist dann wohl auch nicht so wichtig.
Professionell ist anders. Aber ok, die Chance, wirklich die Stelle zu
finden, wo das Problem genau ist, hast Du Dir damit genommen. Ist dann
wohl auch nicht so wichtig.
Na ja, ich habe die Stelle ja auch so gefunden !
Zugegeben: Mit Debugger ist vieles einfacher, auf STM32 bin ich damit auch unterwegs. Wirklich immer muß das aber nicht sein.
Außerdem: Ich bin kein professioneller Softwareentwickler