Servus
Ich wieder 8-[ Folgende Aufgabe gilt es zu lösen (ist gelöst, ich such
nur den Fehler :D): Die LEDs solen Binär zählen und zwar per 10bit
geteiltem 16bit Timer1, Zeit einstellbar (0...255 entsprechen dann 2,22
bis 5,xms). Geschrieben haben wir folgenden Code
1
.nolist ; include-file nicht in Listing
2
.include "m128def.inc" ; Definitionen für ATmega 128 einbinden
3
4
5
.list ; Listing erstellen
6
7
8
.def akku = r16 ; r16 als Rechenregister "akku" definieren
9
.def msTimer = r23 ; r23 als Zeit-Einstellungsregister
Der tuts aber nicht! Wenn ich den Makro Aufruf statt in Count in TC1int
schreibe funktioniert alles Tadellos, die LED wird umgeschaltet.. .Ich
gehe damit davon aus das der Timer sowie die einstellung von OCR
funktionieren.
Wenn ich den eigentlichen Zähl Code
1
dec PulsCounter
2
out led_port,PulsCounter
irgendwohin, also entweder in Count, die Programmschleife selbst (das
Dekrementieren dann hinter den SBRC Befehl) oder in den Interrupt selbst
packe funktioniert es auch nicht.
Die LED sind Low Aktiv.
Die überprüfung des Bits im TIFR Register hat der ING genauso in der
Musterlösung, bei ihm soll es funktionieren (ebenfalls Mega128).
Weder der LaborING noch mein Laborpartner noch ich wissen was wirklih
los ist ...
Findet jemand den Fehler? :-s
Grüße
PS: Es liegt nicht daran das der Interrupt Aktiviert und in der Tabelle
steht. Die Globalen Interrupts sind deaktiviert und in einer Aufgabe
vorher haben wir den gleichen Code (kann ich gern Posten) mit dem 8bit
Timer und aktivierten Globalen Interrutps und da funktioniert alles ...
das komplette entfernen der Sprungadresse + Unterprogramm halfen auch
nicht.
PSS: Genau das selbe steht auch im Roboternetz Forum ;)
PSSS: Ich hoffe der Source Code ist nicht zu lang
PSSSS: Beitrag "Atmega128 16-bit Timer" Ich habe das mal
überflogen, kann es sein das ich beim 16bit Timer wirklich TCNT1 bei
jedem durchlauf neu auf 0 setzen muss? Beim 8bit Timer läuft das ja von
selbst ...
Hi!
Ich habe jetzt kein "128"ger Datenblatt, aber wenn ich lese:
>in Count in TC1int schreibe funktioniert alles Tadellos
würde ich jetzt mal vermuten du prüfst in:
> in templ,TIFR> SBRC templ,4
ein falsches Bit. Schaue doch bitte mal genau ins Datenblatt.
Viel Erfolg, Uwe
Es steht aber da, dass das Bit Automatisch gelöscht wird wurde es
ausgelöst
1
OCF1A is automatically cleared when the Output Compare Match A interrupt vector is executed.
2
Alternatively, OCF1A can be cleared by writing a logic one to its bit location.
Es müsste ja wenigstens die LED dann aus gehen und nich ma das tut sie
augen roll ich denke das Problem liegt in TIFR, wobei der Herr
Laboring ebenfalls das 4. Bit abfragt...
Ano Nym wrote:
> Es steht aber da, dass das Bit Automatisch gelöscht wird wurde es> ausgelöst
Da steht, dass es automatisch gelöscht wird, wenn der Interrupt
ausgeführt wird. Das wird er bei dir aber nicht, also musst du es selber
löschen.
> Es müsste ja wenigstens die LED dann aus gehen
Die geht im Augenblick so schnell aus, wieder an, wieder aus, wieder an,
... , dass du es gar nicht siehst.
Aber ich frag das Interrupt Flag doch ab? Ich hab den "Compare-Mode"
aktiviert und frage das "Compare"-Bit ab. Also führe ich den Interrupt
doch aus, oder macht es einen unterschied ob ich in eine x-beliebige
Routine mit der Interrupt Adresse springe oder nicht?
Ich werde es mir aber mal notieren und testen wenn ich wie der im Labor
bin.
Oder kann es daran liegen das TCNT zurückgesetzt werden muss?
Ano Nym wrote:
> Also führe ich den Interrupt> doch aus, oder macht es einen unterschied ob ich in eine x-beliebige> Routine mit der Interrupt Adresse springe oder nicht?
Es macht natürlich einen großen Unterschied, ob du von Hand irgendwo
hinspringst, oder ob der Prozessor automatisch in den Interrupt
springt.
Das heist obwohl ich oben die Interrupt Tabelle habe, mit dem
entsprechenden Interrupt, und ich das Interrupt aktiviert habe muss
ich es Manuell Löschen? Beim 8-Bit Timer funktioniert das auch so ohne
Probleme (Code Postbar)
> Das heist obwohl ich oben die Interrupt Tabelle habe, mit dem> entsprechenden Interrupt, und ich das Interrupt aktiviert habe muss> ich es Manuell Löschen?
Herrgott, ist das denn wirklich so schwer?
Er springt nicht von alleine zur Interruptroutine, also löscht er auch
das Bit nicht von alleine.
> Beim 8-Bit Timer funktioniert das auch so ohne> Probleme (Code Postbar)
Sicher nicht.
Keinen grund ungehalten zu werden. Verstanden habe ich es schon, ich
wollte es nur bestätigt wissen.
Habe mal die 3. Aufgabe mit dem 8-Bit Timer angehangen das ohne Probleme
funktioniert - auser ich hab einen gewaltigen denkfehler was sehr gut
sein kann :)
Ano Nym wrote:
> Habe mal die 3. Aufgabe mit dem 8-Bit Timer angehangen das ohne Probleme> funktioniert
Da ist ja auch ein SEI drin!!!
Also komplett andere Situation.
Und "ohne Probleme" funktioniert es sicher nicht, denn die Funktion
Taster wird dort keinesfalls bei jedem Timer-Interrupt aufgerufen,
sondern nur bei manchen (eher zufällig). Allerdings wohl immer noch oft
genug, dass es nicht direkt auffällt.
Ano Nym wrote:
> Ich meine also die richtigen gesetzt zu haben ... Deshalb mach ich das> auch so umständlich mit den Bitmustern, da weis ich genau was passiert
Das ist in der Tat umständlich und man weiß eben nicht, was passiert!
Warum benutzt Du denn nicht die Bitnamen, dann weiß man, was passiert
und der Code wird leserlicher.
Z.B. im Datenblatt ist das Bootloaderbeispiel mit Bitnamen:
1
; page erase
2
ldi spmcsrval, (1<<PGERS) | (1<<SPMEN)
3
call Do_spm
4
; re-enable the RWW section
5
ldi spmcsrval, (1<<RWWSRE) | (1<<SPMEN)
Ich habe jedenfalls keine Lust, die Bitmuster von Dir erstmal
umständlich aufdröseln zu müssen.
Peter
Das Problem scheint wirklich an dem nicht zurücksetzen des Bits zu
liegen - testen kann ich es erst am Donnerstag.
Über die Schreibweise
1
ldi spmcsrval, (1<<PGERS) | (1<<SPMEN)
habe ich mir noch keine Gedanken gemacht ehrlich gesagt. Macht aber
durchaus mehr Sinn als das Bitmuster. Wobei ich das Datenblatt eh immer
offen habe und bei einem
1
ldi TIFR, 0b00010000
Weis das eben das 4. Bit (von 0 ab gezählt) gesetzt ist und kann
nachschlagen was es bedeutet - das nachschlagen entfällt oben natürlich.
Find ich gut! Danke. Kann das jemand aufdröseln wie es Funktioniert?
"<<" ist ja der Schiebeoperator der das Bit Rechts davon nach Links
durch das Register schiebt, das hier ja eine 1 ist.
Ich weis das das alles ziemlich idiotisch und nervig rüber kommt.
Problem an der ganzen Geschichte ist, dass wir uns alles selbst bei
bringen und keinen blassen Schimmer von ASM haben, ich hab lediglich in
der Theorie vor 3 Monaten mal ein bisschen was mit C gemacht - das hilft
nur bedingt. Deshalb kommt diese 0-Ahnung... Leider. Ich wünschte es
wäre anders ^^
Hi
> ldi msTimer,0x99> out OCR1AL,msTimer> ldi templ,0> out OCR1AH,templ
Datenblatt:
To do a 16-bit write, the high byte must be written before the low byte.
For a 16-bit read, the low byte must be read before the high byte.
Schreib mal dein Programm um.
MfG Spess
Das hatten wir auch schon versucht was auch nichts geändert hat. Genauso
wie ich schon sagte das wir
- das sei entfernt/hinzugefügt hatten
- Den Ansprung (Tabelle/Unterprogramm) entfernt/hinzugefügt hatten
Und da es mit dem Interrupt selbst geht gehe ich immer mehr davon aus
das es einfach nur daran liegt das man das Bit händisch zurück setzen
muss.
Edit: Ich möchte nicht das einer denkt das ich die Tips nicht aufnehme!!
Ich nehme alles zur Notiz und denke darüber nach, viel mehr kann ich
ohne µP nicht tun und da ich nur zwei mal die Woche ins Labor komme kann
ich im moment nicht mehr sagen
@ Ano Nym (oorim)
>Edit: Ich möchte nicht das einer denkt das ich die Tips nicht aufnehme!!>Ich nehme alles zur Notiz und denke darüber nach, viel mehr kann ich>ohne µP nicht tun
Dann kauf dir in Gottes Namen ein einfaches Evalboard bei Pollin und
probiers praktisch aus.
Such mal auf
http://www.pollin.de
nach
Funk-AVR-Evaluations-Board
spess53 wrote:
> Hi>> Habe mal dein Programm von oben getestet und etwas modifiziert. Im> Simulator läuft es.>> MfG Spess
Im Simulator läuft bei mir nicht mal der Timer (zählt nicht hoch, beim
OnChip Debugging tut sich da auch nichts)... warum weis ich auch noch
nicht.
Falk Brunner wrote:
> @ Ano Nym (oorim)>>>Edit: Ich möchte nicht das einer denkt das ich die Tips nicht aufnehme!!>>Ich nehme alles zur Notiz und denke darüber nach, viel mehr kann ich>>ohne µP nicht tun>> Dann kauf dir in Gottes Namen ein einfaches Evalboard bei Pollin und> probiers praktisch aus.>> Such mal auf>> http://www.pollin.de>> nach>> Funk-AVR-Evaluations-Board
Ich finde deine Antworten etwas patzig. Warum? Ich hab dir schlieslich
nix getan ... Das Pollin Board fällt flach, ich hab weder RS232 noch
Parallel zur Verfügung und ich warte eine JTAG Version von Embedded
Projects ab.
Hi
> ldi akku,0b00001100 ; Timer auf CTC !!!!!!!!!!!!!!!!> out TCCR1B,akku ; Übertrage auf Timer Counter Control Register
Dann gings. Bei 10MHz Simulator-Takt wird 'Count' ca. alle 4ms
angesprungen. Allerdings ist ist mir jetzt auf die Schnelle auch nicht
klar, warum der Timer im Normalmode nicht läuft. Werde mir das zu
gegebener Zeit noch mal ansehen.
MfG Spess
@ spess53 (Gast)
>angesprungen. Allerdings ist ist mir jetzt auf die Schnelle auch nicht>klar, warum der Timer im Normalmode nicht läuft.
Möglicherweise ein Simulator-Bug?
MFg
Falk
Hi
Gerade noch mal getestet. Läuft jetzt auch im Normalmode??????
Bei Timern hat der Simulator eigentlich nur bei PWM einige Probleme.
Aber er braucht sowieso CTC. Sonst wird OCF1A nicht gesetzt.
MfG Spess
Okay vielen dank ich habs gerade gesehen und der Absatz
1
Clear Timer on
2
Compare Match (CTC)
3
Mode
4
In Clear Timer on Compare or CTC mode (WGMn3:0 = 4 or 12), the OCRnA or ICRn Register
5
are used to manipulate the counter resolution. In CTC mode the counter is cleared to zero when
6
the counter value (TCNTn) matches either the OCRnA (WGMn3:0 = 4) or the ICRn (WGMn3:0 =
7
12). The OCRnA or ICRn define the top value for the counter, hence also its resolution. This
8
mode allows greater control of the compare match output frequency. It also simplifies the operation
9
of counting external events.
10
The timing diagram for the CTC mode is shown in Figure 51. The counter value (TCNTn)
11
increases until a compare match occurs with either OCRnA or ICRn, and then counter (TCNTn)
12
is cleared.
macht ja klar das man dieses Bit auch braucht - das 4. Bit in TCCR1B
muss also auch gesetzt werden.
Danke!
Mag mir noch jemand erklären wie die bessere Schreibweise des setzen der
Einstellbits funktioniert? Kann ich damit dann auch direkt setzen oder
muss ich auch den umweg über ein normales Register gehen?
Grüße
Hi
>Mag mir noch jemand erklären wie die bessere Schreibweise des setzen der>Einstellbits funktioniert? Kann ich damit dann auch direkt setzen oder>muss ich auch den umweg über ein normales Register gehen?
Das hängt vom Register ab.
Wenn Adresse< $20($40): sbi/cbi io_reg, bitnummer (0..7)
Wenn Adresse< $40($60) ldi rxy,1<<bitnummer
out io_reg,rxy
Wenn Adresse>=$40($60) ldi rxy,1<<bitnummer
sts io_reg,rxy
Siehe Datenblatt 'Register Summary' und 'Instruction Set'
MfG Spess
Vielen vielen dank auch hierfür. [ironie]Was man nicht alles lernen
kann[/ironie]
Wir kriegen wirklich gar nichts beigebracht und um auf alles selbst zu
kommen fehlt im moment einfach die Zeit :( Danke!
Hi
>Antwort: Also kann ihc TIFR mit sbi TIFR,(1<<OCF1A)|(1<<TOIE0)
Nein. Für den Anfänger etwas verwirrend.
'sbi/cbi' gehen nur mit einem Bit (0..7) sbi io_reg,5
'sbr/cbr' gehen mit allen Bits (0..255) sbr reg, (1<<1)|(1<<2)....
MfG Spess
@ Ano Nym (oorim)
>sbi TIFR,(1<<OCF1A)|(1<<TOIE0)
Geht nicht, weil SBI immer nur EIN EINZIGES Bit setzen kann, nicht
mehrere.
Und ich weiss jetzt gar nicht, ob TIFR eine I/O Adresse kleiner als 0x1F
hat. Dann geht SBI auch nicht.
MFG
Falk
Verflucht stimmt ja, SBI ist ja "Set Bit in IO Register" - also ein Bit.
SBR habe ich in dem zusammenhang ignoriert gehabt weil das ja auf
Normale Register zugreift (Wobei ich da auch nur "Set Bit in Register"
im Kopf habe und das auhc nur ein einziges Bit setzen sollte nach meiner
Logik)
Spess53 wrote:
> Hi>>>Mag mir noch jemand erklären wie die bessere Schreibweise des setzen der>>Einstellbits funktioniert? Kann ich damit dann auch direkt setzen oder>>muss ich auch den umweg über ein normales Register gehen?>> Das hängt vom Register ab.>> Wenn Adresse< $20($40): sbi/cbi io_reg, bitnummer (0..7)>> Wenn Adresse< $40($60) ldi rxy,1<<bitnummer> out io_reg,rxy>> Wenn Adresse>=$40($60) ldi rxy,1<<bitnummer> sts io_reg,rxy>> Siehe Datenblatt 'Register Summary' und 'Instruction Set'>> MfG Spess
TIFR hat wie oben geschrieben die Adresse $26($56) und ist damit
<$40($60) (wenn richtig verstanden) und damit muss es dann über den LDI
umweg gesetzt werden, Okay ich sehs ein.
Die Simulation läuft mit dem Timer übrigens wirklich, ich hab das mit
JTAG durcheinander gewürfelt, da funktioniert der Timer irgendwie nicht.
Weis nicht ob das normal ist oder nicht. Gibt es eigentlich eine bessere
Möglichkeit einen Tastendruck zu Simulieren als über das anklicken des
Entsprechenden Pins/Portbits?
Hi
Ich nochmal, habe jetzt eine aktuelle Version angehängt. Der Timer
braucht in der Simulation ewig, wenn ich ihn "verstell" (also OCR nach
unten setze) spinnt alles komplett... Vielleicht hat einer eine Idee
wieso. Das Programm zählt aber Binär hoch, was es tun soll. Langsam,
aber sicher :D
Hi
Wieso geht das langsam? Wenn du bei 'Count:' einen Breakpoint setzt und
'Run' drückst wird der nächste Zählerstand in Sekundenbruchteilen
erreicht.
Ich habe dein Programm mal in eine lesbare Form gebracht und noch ein
paar Bemerkungen gemacht.
MfG Spess
spess53 wrote:
> Hi>> Wieso geht das langsam? Wenn du bei 'Count:' einen Breakpoint setzt und> 'Run' drückst wird der nächste Zählerstand in Sekundenbruchteilen> erreicht.> Ich habe dein Programm mal in eine lesbare Form gebracht und noch ein> paar Bemerkungen gemacht.>> MfG Spess
Naja "lesbar" und "nicht lesbar" ist glaube ich eine sache des Anwenders
- da ich C gewohnt bin hab ich mir das, für mich und meinen Kollegen,
möglichst Strukturiert geschrieben. Ich komm damit ganz gut klar. Ändert
sich aber im laufe der Zeit ständig und immer mehr in die richtung die
du gepostet hast.
Auf die Idee mit dem Breakpoint bin ich nch nicht gekommen, muss ich mal
testen danke. Den Simulator zu bedienen ist scheinbar eine ähnliche
Kunst wie ASM selbst :D
Hi
>Naja "lesbar" und "nicht lesbar" ist glaube ich eine sache des Anwenders>- da ich C gewohnt bin hab ich mir das, für mich und meinen Kollegen,...
Meine ersten Programme habe ich auf dem Papier mit Befehlstabelle
entwickelt und per Hextastatur in den 'Computer' eingetippt. Zu der Zeit
sahen alle Assemlerlistings so aus. Da gewöhnt man sich halt dran. Und
das Programm mit dem ich mir den Code für den Programmrumpf generiere
habe ich mir halt auch so geschrieben.
>Auf die Idee mit dem Breakpoint bin ich nch nicht gekommen, muss ich mal>testen danke. Den Simulator zu bedienen ist scheinbar eine ähnliche>Kunst wie ASM selbst :D
Nö. Auch der Simulator hat eine Hilfe. Und Breakpoints sollte man als
Programmierer eigentlich kennen. Oder testest du ein mehrere tausend
Quelltextzeilen langes PC-Programm im Einzelschritt.
MfG Spess
P.S. Noch zwei Sachen:
1. Denke dran , das Leds meist invertiert angesteuert werden.
2. Wenn du schon bei deinem Stil bleiben willst, dann stell wenigstens
die Tabweite im Editor auf 1. Dann sieht das Programm wenigstens in
jedem Editor gleich aus.
Die LEDs sind invertiert angsteuert ja, deshalb läuft der Counter auch
Rückwärts um Vorwärts zu zählen ;)
Breakpoints setze ich relativ selten. 1. Sind unsere Programme in
C++/MatLab ("Fortran") und Assembler bisher nicht so groß und 2. laufen
90% aller Programme im ersten rutsch so wie sie sollen, falls nicht ist
dann meistens ein Verschreiber drin. Falls nicht setze ich natürlich
breakpoints, aktiviere zwischen Ausgaben, bastel mit Fehler Handlings
etc. Das ist klar.
Im Thema Software-Engineering sind wir noch ganz am Anfang.
Auf die Hilfe zum Simulator kam ich auch noch nich, sind immer die
einfachen Dinge im Leben auf die man mal kommen muss ^^ Wieder was
gelernt. Werde ich mir definitiv mal ansehen! Genauso die Tabbreite.
Die Befehlstabellen haben wir einmal kurz gesehen - mit dem Satz "so war
das früher, ihr braucht das nicht, macht das in euerm Stil"... naja,
lernen tun wir in der Vorlesung so oder so nichts. Wir sind 100% auf uns
gestellt :(
Grüße
Rechtschreibfehler dürfen gefunden und behalten werde und dienen
lediglich der belustigung des Lesers!
Hi
>Die LEDs sind invertiert angsteuert ja, deshalb läuft der Counter auch>Rückwärts um Vorwärts zu zählen ;)
Aber nicht mit 'inc PulsCounter'. Das Getödel könnt ihr euch sparen mit:
com PulsCounter ; invertieren
out led_port,PulsCounter ; ausgeben
com PulsCounter ; invertieren
Mit dem jetzigen Programm wird nicht gezählt: Bei 0 wird $FF geladen und
danach incrementiert. Ergibt wieder 0. und das Spiel geht von vorn los.
MfG Spess
Ja gut ich habe das auf die weise Marke endlos basteln wollen
Zählt von 0 bis 255, geht wieder auf 0 und zählt wieder bis 255 usw.
Auf das invertieren wäre ich jetzt nicht gekommen...
1111 invertiert ergibt 0000
0000 invertiert ergibt 1111
Da zähl ich doch nicht hoch?
Wenn ich aber 0000 3 mal inkrementiere habe ich ja dann
0001
0010
0011
Und er zählt Binär hoch?
Edit: Incrementieren war hochzählen, Dekrementieren runterzählen, hab
ichs wieder versaubeutelt ... Peinlich
Hi
>Da zähl ich doch nicht hoch?
Das hat nichts mit dem Zählen zu tun. nur mit der invertierten Ausgabe.
Das 'inc' bleibt drin. Dafür kannst du dir
breq CountExit
ldiPulsCounter,0xFF
sparen.
Abgesehen kann das auch bei 'dec' entfallen, da
dec (0) =$FF (auf Byteebene)
MfG Spess
Jep danke... Es sollte ja auch ohne das invertieren gehen wenn ichs
einfach immer fröhlich DEkrementiere - da spare ich mir auch das
Invertieren.
Grüßle und dankeschön
PS: Gibt es beispiele für Kompliziertere ASM Codes wie zB einen GPS
Logger oder PID Regler? Ich hab mal gegooglet aber nichts gefunden und
mich würde das mal interessieren wie da der ASM Code aussieht. Kann mir
komplexere dinge nicht so recht vorstellen :/
Hi
>Gibt es beispiele für Kompliziertere ASM Codes wie zB einen GPS...
Wenn du dich durchwühlen willst: Ich habe einen GPS mit Grafikdisplay
und Anzeige von Position, Uhrzeit, Datum, Richtung,
helligkeitsgesteuerter LCD-Beleuchtung ... und Anzeige eines
Kartenausschnitts mit der Position mit einem ATMega128 in Assembler
programmiert. Das PC-Programm um aus handelsüblichen Routenprogrammen
verwertbare Kartendaten zu generieren hat länger als das
Assemblerprogramm gedauert und mehr Nerven gekostet. Deshalb ist es bei
einer ca.25x25km umfassenden Karte, die ich in den oberen 64k des Atmega
untergebracht habe, geblieben.
MfG Spess