Hier habe ich mal aus Spaß und Langeweile statt nur Flags einen 4bit
Counter platziert. Mit gcc auf dem PC funktioniert das: Beim
Dekrementieren zählt er von 15 auf 0 und fängt dann wieder bei 15 an.
Auf dem AVR zählt er ein bisschen anders....
1
S_status.counter=15;
2
for(uint8_ti=20;i<21;--i){
3
itoa(S_status.counter,buffer,10);
4
uart_puts(buffer);
5
uart_puts_P("\n\r");
6
--S_status.counter;
7
}
ergibt:
5
4
1
0
5
...
Hat der Compiler hier etwas tot optimiert?
Flags: -Wall -Os -fpack-struct -fshort-enums -ffunction-sections
-fdata-sections -std=gnu99 -funsigned-char -funsigned-bitfields
-mmcu=atmega8a -DF_CPU=4000000UL
AVR-Bastler schrieb im Beitrag #5151726:
> ich benutze auf den AVRs gerne Bitfelder um Flags zu speichern. Die> Bitfelder lege ich dann auf ein Register unterhalb 0x1F
Und warum legst du die nicht ins RAM?
Falls du den Fehler im Compiler vermutest, wo ist dias Disassembly? ->
.lss
Sonst: MemoryMapped-IO-Register, die jederzeit ihren Wert ändern kann,
ist mit "volatile" zu deklarieren, weil?
Eventuell genau deshalb.
AVR-Bastler schrieb im Beitrag #5151726:
> #define S_status (* (volatile SYS_STATUS_REG *) &TWCR)
Gehts noch, was soll der Unfug?
TWCR ist ein Konfigurationsregister, d.h. man darf nur die erlaubten
Bits setzen oder löschen (siehe Datenblatt).
Und das hat in der Regel Folgen für die damit verbundenen IO-Pins.
Und viel Spaß, wenn Du Interruptenablebits setzt, aber keinen Handler
dafür hast.
Bitfelder erzeugen oft deutlich umständlicheren Code als Bytevariablen.
Daher sieht man oft, daß erfahrene Programmierer ein ganzes Byte als
Flag "verschwenden".
Und Zählervariablen <8Bit wirst Du bei denen auch nicht finden können.
jz23 schrieb:> Und warum legst du die nicht ins RAM?
Wie ich oben schon sagte: aus Neugierde, nicht aus Notwendigkeit.
Peter D. schrieb:> man darf nur die erlaubten> Bits setzen oder löschen
Peter, Du bist wenigstens etwas näher dran als die Anderen:
Das Problem ist nicht, dass es ein Konfigurationsregister ist (denn wenn
die Peripherie ausgeschaltet wäre, könnte ich konfigurieren so viel ich
will).
Das Problem ist, dass es genau dieses Register ist:
1. Es ist gar nicht unterhalb 0x1F, entspricht also gar nicht dem
gewünschten Zweck.
2. Genau hier ist neben dem TWINT auch das TWEN drin - hier wird also
entgegen jedem Sinn und Verstand das unbenutzte TWI aktiviert.
3. Bit 1 gibt's hier gar nicht - deshalb zählt er auch so komisch.
Fazit: Tippfehler, es sollte TWBR sein, nicht TWCR. Es war halt schon
spät...
Mannomann - hätte ich nicht spaßeshalber den Counter da reingepackt
sondern ein Flag an Position 1, hätte ich lange gesucht.
Ansonsten möge mancher, der hier geantwortet hat, mal seine Antwort mit
den Fakten vergleichen. Es ist doch immer witzig hier. Und so
freundlich...
AVR-Bastler schrieb im Beitrag #5151930:
> Fazit: Tippfehler, es sollte TWBR sein, nicht TWCR.
Trotzdem wirst Du sowas bei einem erfahrenen Programmierer nicht finden.
Da steht Lesbarkeit und Fehlervermeidung an erster Stelle.
Wie Du ja selber gemerkt hast, ist das aber Fehler provozierend.
Es besteht auch keinerlei Grund, mit RAM zu geizen, Du kannst ja bis zum
ATmega328 upgraden.
So ein Code ist auch unfair gegenüber demjenigen, der Deinen Code weiter
warten muß. Der wird erstmal das Grübeln kriegen, was zum Teufel diese
Funktion mit dem TWI zu tun hat. Er wird ins Datenblatt schauen müssen,
was das Register bedeutet. Er wird also lange brauchen, um den dirty
hack als solchen zu erkennen, nur damit ein paar Byte und CPU-Zyklen
gespart werden. Und dann darüber den Kopf schütteln und es nochmal
sauber hinschreiben.
Und wenn Du selber den Code später um TWI erweitern willst, wirst Du den
Hack längst vergessen haben und Dir dann aber so richtig die Karten
legen.
Peter D. schrieb:> Es besteht auch keinerlei Grund, mit RAM zu geizen, Du kannst ja bis zum> ATmega328 upgraden.
Für diese Anwendung reichte auch ein Atmega48. Den müsste ich aber
bestellen. Von den Atmega8A liegen dagegen noch zu viele hier herum.
Wenn mal irgendjemand durch dieses Gerät in solche Begeisterung versetzt
wird, dass ich ein Millionengeschäft wittere, dann werde ich bei den
dann zu erwartenden Stückzahlen sicher neu über den "besten" µC für
diesen Zweck nachdenken.
Peter D. schrieb:> So ein Code ist auch unfair gegenüber demjenigen, der Deinen Code weiter> warten muß.
Life is not fair. It never was.
In diesem speziellen Fall ist aber alles eine Frage der Dokumentation.
Ich für meinen Teil habe die Angewohnheit, nicht nur wichtige Stellen im
Code zu markieren und zu kommentieren, sondern auch ein "Vorwort" im
Kopf der main.c des Projektes zu schreiben, aus dem hervorgeht, welche
Pins (für den Fall, dass die Doku der Schaltung mal abhanden kommt),
welche Peripherie und welche GPIORs benutzt werden sowie welche Todos
und Limitations noch offen sind.
Das alles mache ich nur für mich selbst, denn es können Jahre vergehen,
bis ich mal wieder in den Code schaue.
Vor allem aber:
Alles, was Du schreibst, ist richtig und wichtig für den jugendlichen
Programmier-Schüler, der von einer Zukunft als Software-Entwickler
träumt.
In meinem Fall ist aber die einzige Kontrollinstanz der µC. Wenn der
sagt: "Das geht so nicht.", dann muss ich ihm glauben.
Allen anderen höre ich zu.
AVR-Bastler schrieb im Beitrag #5152228:
> In diesem speziellen Fall ist aber alles eine Frage der Dokumentation.> Ich für meinen Teil habe die Angewohnheit, nicht nur wichtige Stellen im> Code zu markieren und zu kommentieren, sondern auch ein "Vorwort" im> Kopf der main.c des Projektes zu schreiben, aus dem hervorgeht, welche> Pins (für den Fall, dass die Doku der Schaltung mal abhanden kommt),> welche Peripherie und welche GPIORs benutzt werden sowie welche Todos> und Limitations noch offen sind.
Du solltest mal ganz dringend Buecher wie "Clean Code" lesen
Kaj G. schrieb:> Du solltest mal ganz dringend Buecher wie "Clean Code" lesen
Nein, sollte ich nicht. Warum nicht? Lies noch einmal, was ich
geschrieben habe.
@Feldstecher
Ja, ich habe meine Frage ausführlich beantwortet.
Ich weiß auch nicht, was a da noch zu "eiern" gibt.