Hallo leute,
Ich arbeite gerade das Tutorial durch und in Ermangelung eines LCD's
habe ich mir gedacht, das Zeitsignal auf UART auszugeben.
Das funktioniert auch alles bestens nach ca. 12h arbeit (jaja, bin noch
neu).
Das Vorgehen ist, dass ich den nicht bei null anfange zu zäheln, sondern
bei der Ascii-Null (0x30). Das Ergebnis gebe ich dann sekündlich auf
UART aus.
Was noch nicht zufriedenstellend ist:
Ich brauche dafür 9 Register. Denn jede Stelle an der Uhr (hh:mm:ss)
bekommt ein Register, das sind schonmal 6. +2 Statusregister +temp1
Meine Frage:
Kann man das optimieren?
Welche stellen sind unschön?
Gruß, fiete
1
.include "m8def.inc"
2
3
.def temp1 =r16
4
.def flag =r17
5
.def subcount =r18
6
7
.def lsekunden =r19
8
.def hsekunden =r20
9
.def lminuten =r21
10
.def hminuten =r22
11
.def lstunden =r23
12
.def hstunden =r24
13
14
15
.org 0x0000 ;reset Handler
16
rjmp main
17
18
.org OVF0addr ;sprung zu 't0_OverFlow' bei Timer0 - Overflow
@ Friedrich Kpunkt (fiete)
>Das Vorgehen ist, dass ich den nicht bei null anfange zu zäheln, sondern>bei der Ascii-Null (0x30). Das Ergebnis gebe ich dann sekündlich auf>UART aus.
So weit, so gut.
>Ich brauche dafür 9 Register. Denn jede Stelle an der Uhr (hh:mm:ss)>bekommt ein Register, das sind schonmal 6. +2 Statusregister +temp1
Naja, für den Anfang OK.
>Kann man das optimieren?
Durch Nutzung von Speicher: SRAM, siehe AVR-Tutorial: SRAM>Welche stellen sind unschön?
Für den Anfnag ist das OK. Schönen Programmierstil lernst du u.a. durch
Durcharbeiten des AVR-Tutorial
MFG
Falk
Danke für die Antworten.
Im RAM ablegen hatt ich auch schon gedacht, aber da muss ich noch viel
drüber nachdenken, wie genau das geschehen soll. Aber ich hab schon
ideen.
BCD-Code muss ich mir mal angucken, was das ist, und wie man das
verwerten kann.
Noch eine Frage: gibt es ein "Skip If equal"? Ich habe es mir mühvoll
zusammengebastelt, aber zufrieden bin ich damit nicht. Ware das folgende
eine Möglichkeit: SREG in temp laden und dann Z-Flag mit Sbis checken
Da kannst du dann auch gleich einen Branch if equal machen
Noch was
ldi hminuten, 48
Da frage ich mich doch gleich, was der spezielle Zahlenwert 48 mit den
Minuten zu tun hat. Nach langen Analysen kommt man dann drauf, dass das
eigentlich der ASCII Code von '0' ist. Schreib das doch gleich so hin
ldi hminuten, '0'
dann sieht man das gleich viel besser. Ein
inc lsekunden ;einer-sekunde um 1 erhöhen
cpi lsekunden, '9' + 1 ;maximum (10) erreicht?
erzählt mir im Code schon viel mehr über die Absicht des Programmierers
an dieser Stelle als ein
inc lsekunden ;einer-sekunde um 1 erhöhen
cpi lsekunden, 58 ;maximum (10) erreicht?
wobei hier pikanterweise auch noch die zahlenmässige Ähnlichkeit zu 59
(der höchsten Sekundenzahl in einer Minute) hinzukommt und man an einen
Tippfehler denken könnte
@ Friedrich Kpunkt (fiete)
>Noch eine Frage: gibt es ein "Skip If equal"? Ich habe es mir mühvoll>zusammengebastelt, aber zufrieden bin ich damit nicht. Ware das folgende>eine Möglichkeit: SREG in temp laden und dann Z-Flag mit Sbis checken
Hör auf das Rad neu zu erfinden und mach es so wie der Rest der Welt.
AVR-Tutorial: Vergleiche
Danke für die Kritik Karlheinz. Genau sowas ist enorm hilfreich, vor
allem, weil man selber schnell den Überblick verlieren kann. Freut mich
sehr, dass du dir die Mühe gemacht hast, das anzugucken.
Falk: Die sache ist, dass ich absoluter neuling bin. Es so zu machen
'wie der rest der Welt' ist nicht so einfach, wenn man nicht weiß, wie
der Rest der Welt es macht.
Ein "Skip if Equal" gibt es offensichtlich nicht, und die Lösung mit
breq erfordert das setzen eines neuen Zweiges. Das wollte ich mir
einfach nur ersparen und wissen, wie der Rest der Welt ein solches
Problem löst.
Sei nachsichtig mit solchen Anfängerfragen, ich frage nicht um euch zu
nerven, sondern weil ich eben nicht das Rad ständig neu erfinden möchte.
Gruß, fiete
Friedrich Kpunkt schrieb:
> Ein "Skip if Equal" gibt es offensichtlich nicht, und die Lösung mit> breq erfordert das setzen eines neuen Zweiges.
Was willst du uns damit sagen?
> Das wollte ich mir> einfach nur ersparen und wissen, wie der Rest der Welt ein solches> Problem löst.
Mittels branch.
Diese Skip Befehle sind zwar toll aber so universell eigentlich auch
nicht. branch (in allen Varianten) kann man immer benutzen, skip ist
eher die Aussnahme, die manchmal geht, wenn man auf ein bestimmtes Bit
in einem Register testen will. Völlig sinnlos ist es aber, das SREG
zuerst in ein Register zu transferieren um dann ein bestimmtes Bit zu
testen. Genau dafür gibt es die branch Befehle, die das SREG direkt zur
Entscheidung benutzen. Und kein Mensch verbietet, dass das Ziel eines
Branch nur eine Instruktion entfernt ist und somit effektiv ganz einfach
die nächste Anweisung übersprungen (ge-skippt) wird.
okok, ich benutze branch.
Was beim Branch ein bissel das problem ist, dass ich noch nicht genau
begreife, wo der ret hin geht.
Er bekommt die Adresse ja aus dem Satack. Läd jeder Branch eine
Rücksprung-Adresse in den Stack. Warum ich mich so gegen den Branch
wehre ist, dass ich den Stack noch nicht so recht verstanden habe, und
bei ret schon mehrmals mist passiert ist.
Ich werde mich wohl nochmal mit dem Stack auseinandersetzen müssen...
gruß, fiete
Friedrich Kpunkt schrieb:
> okok, ich benutze branch.>> Was beim Branch ein bissel das problem ist, dass ich noch nicht genau> begreife, wo der ret hin geht.
Was für ein ret?
> Er bekommt die Adresse ja aus dem Satack.
Nein.
> Läd jeder Branch eine> Rücksprung-Adresse in den Stack.
Hä.
Das eine hat mit dem anderen nichts zu tun!
branch if equal
kann man übersetzen mit: Spring dort und da hin, wenn das Zero-Flag
gesetzt ist. Da in der Überwiegenden Mehrzahl der Fälle, so etwas nach
einem Vergleich gemacht wird, und das Zero-Flag in diesem Fall anzeigt,
dass die beiden zu vergleichenden Werte gleich gross sind, ist ein
gesetztes Zero-Flag daher in den meisten Fällen identisch mit: equal
> Warum ich mich so gegen den Branch> wehre ist, dass ich den Stack noch nicht so recht verstanden habe, und> bei ret schon mehrmals mist passiert ist.
Da brauchst du keinen Stack und auch keinen ret.
Du redest von 'Branch' denkst aber an 'Call'
Das ist eine ganz andere Baustelle
1
ldi r16, 0x20 ; lade irgendwas in r16
2
ldi r17, 0x30 ; lade was anderes nach r17
3
4
cpi r16, r17 ; vergleiche r16 mit r17
5
breq mach_was_bei_gleich ; wenn r16 und r17 gleich waren, dann
6
; gehst bei mach_was_bei_gleich weiter
7
8
; andernfalls geht es hier weiter
9
... code bei Ungleich
10
11
mach_was_bei_gleich:
12
... code bei Gleichheit
kein Mensch braucht da einen Stack oder ein return für irgendetwas.
Was ich nicht verstehe: In deinem Code wimmelt es doch nur so von brne
(also Branch if not equal). Warum hast du jetzt so grosse Probleme mit
einem breq (Branch if equal). Das ist doch einfach nur die Umkehrung der
Bedingung wann der branch genommen wird.
Karl heinz Buchegger schrieb:
> Was ich nicht verstehe: In deinem Code wimmelt es doch nur so von brne> (also Branch if not equal). Warum hast du jetzt so grosse Probleme mit> einem breq (Branch if equal). Das ist doch einfach nur die Umkehrung der> Bedingung wann der branch genommen wird.
Ja, ich habe diese Codeteile aus dem Tutorial übernommen (nicht kopiert!
ich schreibe alles selbst - ab), geglaubt sie verstanden zu haben und
dann halt verwendet. Ich dachte der Branch ist eine art interrupt, der
dann irgendwann wieder beendet wird. Aber nun weiß ich, dass ich das mit
call verwechsel. Jetzt verstehe ich auch euer unverständnis.
So, habe jetzt nen bissel weiter dran rumgebastelt. Jetzt benötigt man
kein einziges Register, weil alles im RAM abgelegt wird.
Nun habe ich allerdings noch ein Problem. Die Uhr geht ca. 1%nach und
ich hab nach vielen Überlegungen immernoch keinen Schimmer, woran es
liegt.
Auch zahlreiche Threats hab ich schon durchgelesen, aber nur die zwei
Fehlerquellen gefunden:
-"Schaltsekunden" fallen weg, da CTC Prescaler auf 1024 und Overflow:
3600-1
- Der externe Takt des STK500 ist falsch (3.683400 MHz) Das kann ich
leider nicht überprüfen, weder direkt noch indirekt.
- Es werden Interrupts verschluckt
das kann ich mir allerdings wirklich nicht vorstellen, weil ich
Interruptzeiten von max 70 takten habe. Der nächste Interrupt ist um 5
Größenordungen höher.
Ferner ist die Ausgabe im Hyper-Terminal komisch. Das Terminal ist ja in
zwei Bereiche geteilt. Diese werden aber irgendwie unterschiedlich
dargestellt. Im weißen Bereich sind IMMER alle Zahlen hübsch
untereinander. Scrollt man nach oben, dann bekommt man in unregelmäßigen
Abständen Fragmente. Hab mal einen Screenshot angehängt.
Ideen, was da los ist?