out TCCR1B, akku ;counter control register in akku laden
10
ldi akku, (1<<TOIE1) ; TOIE1: Interrupt bei Timer Overflow
11
12
out TIMSK, akku
13
14
ldi akku, 0x78
15
out OCR1AH,akku ; überläufe nach 10ms ?
16
17
sei
18
19
endlosschleife: rjmp endlosschleife
20
21
TastTimerISR: ; Timer 1 Overflow Handler
22
call TastRead
23
reti
also der wirre code zu meinem Problem. was mich schon zur ersten Frage
bringt^^
ich bin ja kein freund von irgendwelchen namenlosen bits setzen.
allerdings funktioniert diese schreibweise für z.b den prescaler nicht:
; ldi TCCR1B, (1<<CS12) |(0<<CS12)| (1<<CS10)
das hauptproblem ist aber dass der timer nicht zählt.
ich hab mal mit einem Dragon gedebuggt und einfach mal das interrupt
flag bit OCF1A gesetzt. dann tut das programm genau was es soll.
ich hab aus dem tutorial nicht herausbekommen was genau den timer nun
veranlasst die zählung zu starten. Ich sag ihm doch mit einstellen des
Prescalers, dass er den systemtakt als bezug nehmen soll. initialisiert
ihn das nicht eine zählung zu starten?
Belz Heining schrieb:> ; ldi TCCR1B, (1<<CS12) |(0<<CS12)| (1<<CS10)
natürlich funktioniert das nicht.
TCCR1B muss mit einem out beschrieben werden und nicht mit einem ldi
Erst die Bits in einem Register setzen, dann das Register mit einem out
ausgeben. Dann funktioniert das auch.
> ich hab aus dem tutorial nicht herausbekommen was genau den timer nun> veranlasst die zählung zu starten.
Sobald er einen Prescaler hat, läuft er.
> OCF1A
Hmm. Wie passt das mit
> ldi akku, (1<<TOIE1)
zusammen? Gar nicht.
TOIE #T#imer #O#verflow #I#nterrupt #E#nable Overflow!
OCF1 #O#utput #C#ompare #F#lag Output Compare!
Das sind 2 verschiedene Dinge.
Karl Heinz Buchegger schrieb:> TCCR1B muss mit einem out beschrieben werden und nicht mit einem ldi
Ups, hab ich glatt überlesen. Also so:
ldi akku, (1<<CS12) |(0<<CS12)| (1<<CS10)
out TCCR1B, akku
Wobei das 0<<CS12 nichts bewirkt, daher mein Link zu Bitmanipulation.
ok danke schonmal.. jetzt ergibt einiges mehr sinn.
warum liest er mir bei dem code schnibbsel keinen wert ins OCR1AH ?
in akku, OCR1AH
sbr akku,0x78
out OCR1AH,akku ; überläufe nach 10ms ?
also das akku register hat bis zur 2ten zeile den wert, den es haben
soll.
in der 3ten zeile passiert quasi nix -_-
er hat den prscaler akzeptiert. aber TCNT1L und TCNT1H behalten beide
den Wert 0x00
Belz Heining schrieb:> ok danke schonmal.. jetzt ergibt einiges mehr sinn.>> warum liest er mir bei dem code schnibbsel keinen wert ins OCR1AH ?>> in akku, OCR1AH> sbr akku,0x78> out OCR1AH,akku ; überläufe nach 10ms ?>> also das akku register hat bis zur 2ten zeile den wert, den es haben> soll.> in der 3ten zeile passiert quasi nix -_-
Bei 16 BIt Werten, die über 2 Register abgehandelt werden:
* Beim Lesen: erst Low lesen, dann High
* Beim Schreiben: erst High schreiben, dann Low
Du MUSST beim Lesen (zb beim ADC) das High-Register lesen
Du MUSST beim Schreiben (zb OCR) das Low-Register schreiben
Der jeweils erste Zugriff verriegelt die beiden Register, der jeweils
zweite Zugriff hebt diese Verriegelung auf und führt dann die Operation
durch.
Also: Wenn du den ADC ausliest, dann verriegelt der Lesezugriff auf ADCL
die beiden ADC Register gegen weitere Updates vom ADC. Erst das Lesen
von ADCH hebt diese Verriegelung wieder auf. Dies stellt sicher, dass
die beiden Werte aus den beiden Registern auch tatsächlich aus derselben
Messung stammen.
Und umgekehrt beim Schreiben. Durch das Beschreiben des High-Registers,
wird der Wert erst mal in einem Zwischenbuffer zwischengespeichert und
erst mit dem Schreiben des Low-Registers werden dann beide Werte
gemeinsam gesetzt. Dies stellt sicher, dass der Timer nicht auf einen
ungültigten Zwischenzustand reagiert, wenn du zb den Wert von 0x0199 auf
0x0200 ändern willst, und zwischendurch sich der Wert 0x0299 ergibt,
weil High schon verändert wurde aber Low noch nicht und der Timer just
in diesem Moment genau diesen Wert hat (oder wenn der Update bei TOP
erfolgt, genau zu diesem Zeitpunkt der TOP-Update erfolgt)
ah ok. ich verstehe... nach deiner beschreibung funktionierts
natürlich^^.
kann nun alles so beschreiben wie ich es wollte. verstehe allerdings
nicht warum das OCF1A flag nicht gesetzt wird.
nach dem der timer den eingetragenen wert erreicht müsste doch das flag
gesetzt werden, oder ?
hier nochmal der jetzige code.
1
ldi akku, 0b00000101 ;Prescaler
2
out TCCR1B, akku ;counter control register in akku laden
3
4
5
in akku, TIMSK
6
sbr akku, (1<<OCIE1A); (erst die bits in einem register setzen
7
out TIMSK, akku ; dann das register mit einem out ausgeben)
8
9
in akku, TCCR1A
10
sbr akku, 0b11000000; compare output mode 1a auf 1
11
out TCCR1A, akku
12
13
14
in akku, OCR1AH ;erst high schreiben,verriegelt register
15
sbr akku,0x00
16
out OCR1AH, akku ; dann low
17
; (beim lesen umgekehrt)
18
19
in akku, OCR1AL ;2ter zugriff(aufHigh) hebt verrieglung auf
Hi
>kann nun alles so beschreiben wie ich es wollte. verstehe allerdings>nicht warum das OCF1A flag nicht gesetzt wird.
Das Flag wird gesetzt, aber bei Interruptauslösung sofort wieder
gelöscht.
MfG Spess
Was hast du da mit deinen sbr beim Beschreiben von OCR1?
Setz doch einfach den Wert und gut ists. An dieser Stelle willst du doch
gar nicht, dass ein eventueller alter WErt überlebt.
Überhaupt: Du übertreibst es da ein wenig, mit dem
Lesen-Verändern-Update Zyklus. Wenn man einen Timer beim Programmstart
einrichtet, dann will man normalerweise gesicherte Verhältnisse! Da darf
es keine Unsicherheiten geben, weil irgendwelche Bits unbekannterweise 1
sind. An dieser Stelle nagle ich die Konfigurationsregister MIT ALLEN
BITS auf einen Wert fest.
1
ldi akku, (1<<CS12) | (1<<CS10) ; Prescaler: 1024
2
out TCCR1B, akku
3
4
ldi akku, (1<<OCIE1A)
5
out TIMSK, akku
6
7
ldi akku, (1<<COM1A1) | (1<<COM1A0) ; Set OC1A on Compare Mactch
8
out TCCR1A, akku
9
10
ldi akku, HIGH( 0x0078 )
11
out OCR1AH, akku
12
ldi akku, LOW( 0x0078 )
13
out OCR1AL, akku
14
;
15
sei
16
;
17
main: rjmp main
18
;
> verstehe allerdings nicht warum das OCF1A flag nicht gesetzt wird.
Sobald der Interrupt Vektor angesprungen wird (übrigens: wo ist der in
deinem Code?) wird das Flag automatisch gelöscht.
> "Das Flag wird gesetzt, aber bei Interruptauslösung sofort wieder> gelöscht.>> MfG Spess"
ähm entschuldige die doofe frage, aber was heißt das für mich ?
das wäre ja dann so richtig oder ? es soll ja nicht gesetzt bleiben
damit der "compare" immer wieder aufs neue beginnt, also wie eine
regelmäige abfrage..
>> verstehe allerdings nicht warum das OCF1A flag nicht gesetzt wird.> Sobald der Interrupt Vektor angesprungen wird (übrigens: wo ist der in> deinem Code?) wird das Flag automatisch gelöscht.
naja er wird scheinbar nicht angesprungen. löse ich das flag manuell aus
schon...also im debug mode( dann macht das prog was es soll) allerdings
im programmfluss nicht.
achso die interrupt vektoren hab ich gesondert geschrieben, weil das ja
eigentlich ein unterprogramm sein soll..
sieht aber so aus:
Belz Heining schrieb:> achso die interrupt vektoren hab ich gesondert geschrieben, weil das ja> eigentlich ein unterprogramm sein soll..
Zeig immer den kompletten Code.
So umfangreich ist der ja nicht.
Denn der Fehler sitzt oft nicht dort, wo du ihn vermutest.
> .org 0x0018 ;Interrupt-Vektor T/C-1-Interrupt
dafür gibt es vordefinierte Namen. Das sind Zahlen, die man sich nicht
merken muss.
Sagtest du nicht, du hättest das Tutorial studiert? Du machst lauter
Sachen, die im Tutorial möglichst vermieden werden und von denen im Tut
gezeigt wird, wie man sie besser machen kann.
>Sagtest du nicht, du hättest das Tutorial studiert? Du machst lauter>Sachen, die im Tutorial möglichst vermieden werden und von denen im Tut>gezeigt wird, wie man sie besser machen kann.
naja studieren ist so eine sache. ich muss es ja erstmal machen, was ich
dort lese.. vieles vergisst man wieder und versucht problemstellungen
erstmal nach aktuellem verständnis zu lösen.
bin noch nicht solange dabei kann mir leider nicht alles merken und
richtig machen (;
Belz Heining schrieb:>>Sagtest du nicht, du hättest das Tutorial studiert? Du machst lauter>>Sachen, die im Tutorial möglichst vermieden werden und von denen im Tut>>gezeigt wird, wie man sie besser machen kann.>> naja studieren ist so eine sache. ich muss es ja erstmal machen, was ich> dort lese..
das ist eigentlich so gedacht, dass man nach jedem Kapitel erst mal das
Gelesene verdaut und damit übt.
Wenn du alles in einem Rutsch liest - logisch vergisst du da alles
wieder. Es ist nun mal viel Information, die man absorbieren muss.
spess53 schrieb:> Hi>> Nochmal:>>>.org 0x0018 ;Interrupt-Vektor T/C-1-Interrupt>>rjmp TastTimerISR>> ist falsch! Mach es so, wie Karl-Heinz es geschrieben hat.
Kann sein, das wir eine Zeitüberschneidung hatten.
So wie hier
Beitrag "Re: Timer zählt nicht atmega32"
Und wenn ich hinzufügen darf:
Achte ein wenig mehr auf die äussere Form deines Programmes!
Das ist kein Selbstzweck!
Es ist nämlich kein Zufall, dass diejenigen Programmierer mit den
unübersichtlichsten Programmen immer die mit den seltsamsten Fehlern
sind.
So.
Jetzt machst du mal in deinem AVR-Studio die Datei
m32def.inc
auf.
Im Projektbaum sollte die irgendwo vorkommen und wenn nicht, dann suchst
du sie dir eben auf dem Installationsverzeichnis vom AVR-Studio.
Wenn du sie offen hast, dann suchst du nach dem Abschnitt, der mit
INTERRUPT VECTORS
überschrieben ist (danach kann man den Editor zb suchen lassen)
Du findest das hier
.equ OC1Aaddr = 0x000e ; Timer/Counter1 Compare Match A
9
.equ OC1Baddr = 0x0010 ; Timer/Counter1 Compare Match B
10
.equ OVF1addr = 0x0012 ; Timer/Counter1 Overflow
11
.equ OC0addr = 0x0014 ; Timer/Counter0 Compare Match
12
.equ OVF0addr = 0x0016 ; Timer/Counter0 Overflow
13
.equ SPIaddr = 0x0018 ; Serial Transfer Complete
14
.equ URXCaddr = 0x001a ; USART, Rx Complete
15
.equ UDREaddr = 0x001c ; USART Data Register Empty
16
.equ UTXCaddr = 0x001e ; USART, Tx Complete
17
.equ ADCCaddr = 0x0020 ; ADC Conversion Complete
18
.equ ERDYaddr = 0x0022 ; EEPROM Ready
19
.equ ACIaddr = 0x0024 ; Analog Comparator
20
.equ TWIaddr = 0x0026 ; 2-wire Serial Interface
21
.equ SPMRaddr = 0x0028 ; Store Program Memory Ready
und jetzt vergleichst du mal die Zahlen, mit den Zahlen und den
Kommentaren, die du hier benutzt hast:
1
.org 0x0000 ;Interrupt-Vektor für RESET
2
rjmp Progstart
3
4
5
.org 0x0018 ;Interrupt-Vektor T/C-1-Interrupt
6
rjmp TastTimerISR
7
8
9
.org 0x002a ;Interrupt-Vektor ADC
10
;rjmp ADCISR
11
12
.org 0x0034 ;Interrupt-Vektor T/C-3-Interrupt
13
;rjmp MotorTimerISR
Bis auf den (trivialen) Reset, stimmt KEINE EINZIGE überein!
Man schreibt keine Zahlen direkt in den Code, wenn man nicht muss.
NIE! NIEMALS! UNTER KEINEN UMSTÄNDEN!
Denn genau deswegen gibt es dieses Include File, damit du nicht mit
Zahlen hantieren musst, sondern lesbare Namen dafür verwenden kannst,
die dann auch noch auf unterschiedlichen Prozessoren gleich heißen, wo
aber andere Zahlen dahinter stehen.
1
.org 0x0000 ;Interrupt-Vektor für RESET
2
rjmp Progstart
3
4
5
.org OC1Aaddr ;Interrupt-Vektor T/C-1-Interrupt
6
rjmp TastTimerISR
7
8
9
.org ADCCaddr ;Interrupt-Vektor ADC
10
;rjmp ADCISR
11
12
.org 0x0034 ;Interrupt-Vektor T/C-3-Interrupt
13
;rjmp MotorTimerISR
und beim letzten konnte ich nicht rausfinden, was das für ein Interrupt
sein soll. Der Mega32 hat keinen Timer 3
Ganz ehrlich:
Dein Programm ist so dermassen unübersichtlich, dass man gar nicht weiß,
wo man mit Fehlersuche anfangen soll.
Fang ein neues an. Aber achte diesmal von Anfang an auf eine vernünftige
Form! Achte darauf, dass es übersichtlich ist.
Du kannst ja mit meinem da oben erst mal loslegen.
Und dann kopierst du dir kleine Teile in diesen Code rüber, die in sich
vollständig sind und die du testen kannst. Wenn du den Code übernimmst,
überarbeitest du ihn gleich mal. Du achtest darauf, ob du
Zahlenkonstante durch was anderes ersetzen kannst und du achtest darauf,
dass zb Einrückungen sauber sind, ob viele Leerzeilen hintereinander
stehen (denn die ziehen den Code nur in die Länge und bewirken ansonst
überhaupt nichts, vor allen Dingen machen sie den Code nicht
übersichtlicher).
spess53 schrieb:> Hi>>>Der Mega32 hat keinen Timer 3>> Das kommt von hier:>>>.include "m32def.inc" Definitionen für ATmega128 einbinden> ^^^^^^^^^>
Ich hab mir schon so was gedacht.
Und ich hege auch den Verdacht, dass sein AVR-Studio bzw. der Simulator
noch immer auf den 128-er eingestellt ist. Denn sonst könnte er nicht
das Interrupt Flag im Simulator händisch setzen und die ISR wird
angesprungen.
Da ist komplettes Chaos drinnen. Am einfachstebn sortiert man das aus,
in dem man neu anfängt. Das heisst ja nicht, dass man alles komplett neu
tippen muss. Man kann ja Codeteile umkopieren.
nicht MINDESTENS das SREG am Anfang sichert und zum SChluss wieder
herstellt, dem sollte man mit dem nassen Fetzen eine überbraten, damit
er sichs merkt.
Das ist ungefähr so, als ob ein Chirurg das Skalpell verkehrt rum halten
würde.
ja hab vorher mit nem 128 programmiert...^^
naja gut dann werd ich mal ordnung machen.
danke erstmal für die leicht angenervten aber wohl angebrachten
zurechtweisungen ;P
Karl-Heinz schrob:
>Das ist ungefähr so, als ob ein Chirurg das Skalpell verkehrt rum halten>würde.
Mit so einer Idee würde er sich in's eigene Fleisch schneiden.
;-)
MfG Paul
Karl Heinz Buchegger schrieb:> spess53 schrieb:>> Hi>>>>>Der Mega32 hat keinen Timer 3>>>> Das kommt von hier:>>>>>.include "m32def.inc" Definitionen für ATmega128 einbinden>> ^^^^^^^^^>>>> Ich hab mir schon so was gedacht.> Und ich hege auch den Verdacht, dass sein AVR-Studio bzw. der Simulator> noch immer auf den 128-er eingestellt ist. Denn sonst könnte er nicht> das Interrupt Flag im Simulator händisch setzen und die ISR wird> angesprungen.>
der simulator ist definitiv richtig eingestellt (;
ich debugge ja auch mit nem dragon..
Belz Heining schrieb:> danke erstmal für die leicht angenervten aber wohl angebrachten> zurechtweisungen ;P
Für das angenervt sein entschuldige ich mich.
Aber es ist frustrierend, wenn man ein Programm sieht, welches schon
nicht mehr trivial ist und wenn man es dann mal genauer studiert dann
sieht man da haufenweise Anfängerfehler aus der 2. Unterrichtseinheit
Programmieren.
Es ist, wie wenn du bei BMW unbedingt den neuesten 5-er BMW testfahren
willst und nachdem du eingestiegen bist fragst du erst mal welches Pedal
noch mal schnell das Gaspedal ist.
schon ok.. kann ich nachvollziehen. hab mich auch ehrlich gesagt geziert
hier zu fragen, weil es einige beiträge gibt, von leuten die mit
löchrigem hintergrund wissen, etwas zum laufen bringen wollen.
das ist für erfahrene leute sicher mühsehlig und undankbar sich dann in
soetwas reinzudenken, von jemanden der es euch dann auch noch extra
schwer macht mit unsauberen code.
Da bin ich dann wohl einer von.. aber die arschtrittchen haben wir auf
jeden fall schonmal weitergeholfen. auch sauberkeit muss man sich erst
angewöhnen.. der nächste beitrag(code) wird also sinniger (;
eine frage hätte ich da allerdings noch.. ich weiß nicht ob man die
allgemein beantworten kann aber:
woran kann es liegen, dass nur beim ersten überlauf ein flag gesetzt
wird?
das zählregister macht was es soll.. es zählt. Aber nur wenn ich das
Programm neustarte also alles neu initialisiert ist, zählt es in meinem
fall bis 0x78 und hält am breakpoint bei "reti". sag ich dem debugger
nun "run" bleibt er in der schleife hängen. es wird kein interrupt mehr
ausgelöst..
ich kann allerdings wenn ich das prog anhalte über "break" sehen dass
sich die timer werte weiter bzw. ständig ändern...
Hast du lang genug laufen lassen?
Bis die Simulation bei einem Vorteiler von 1024 den Timer 1 einmal
rundum getaktet hat, vergeht schon seine Zeit. Das dauert.
(Wenn dir die Simlationszeit egal ist, dann kannst du ja auch mal den
Prescaler auf 1 setzen. Dann gehts schneller)
Und PS: deine 10ms erreichst du so nicht.
Was du wahrscheinlich wolltest: den CTC Modus, in dem der Timer mit
erreichen des Compare Match Wertes auf 0 zurück gesetzt wird. Nur: den
hast du nicht eingestellt.