PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATtiny25 Timer0 läuft nicht



maximat
01.02.2008, 14:23
Guten Tag, ich bin neu hier im Forum und neu mit dem Attiny 25 und bitte um Hilfe (und nachsicht)
Ich möchte den Timer 0 bentzen und wenn ich ihn mit
ldi mp,0x05 ; teiler 1024
out TCCR0B,mp
und port b aus ausgang setze
;port b setzen
ldi mp,0b11111111
out DDRB,mp
und dann mit
loop:
in mp,TCNT0
cpi mp,0
brnq loop
abfrage, dann bleibt er in dieser Schleife hängen, im Simulator und wohl auch im Cpip läuft der Timer nicht los.
Muss ich den Timer noch irgendwie anders initialisieren?
Vielen Dank schon mal im Voraus

albundy
01.02.2008, 16:11
Muss ich den Timer noch irgendwie anders initialisieren?

ja, in TIMSK das Bit OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable) oder TOIE0 (Timer/Counter0 Overflow Interrupt Enable)
setzen.

maximat
01.02.2008, 16:17
Sorry, der Timer läuft das Proplem lag in der Auswertung

So blinkt schön vor sich hin

.NOLIST
.INCLUDE "c:/Atmel/tn25def.inc"
.LIST
.DEF mp = R16
.DEF z1 = R17
rjmp main
main:
ldi mp,0
ldi z1,0

;timer starten
ldi mp,0x05
out TCCR0B,mp
;port b setzen
ldi mp,0b11111111
out DDRB,mp
loop:
in mp,TCNT0
cpi mp,0
brne loop
loop2:
in mp,TCNT0
cpi mp,0
breq loop2
com z1
out PORTB,z1
rjmp loop

izaseba
01.02.2008, 17:13
ja, in TIMSK das Bit OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable) oder TOIE0 (Timer/Counter0 Overflow Interrupt Enable)
setzen.

Warum ?
Muß man immer ein Interrupt nutzen ?
Und wenn Du sowas schreibst, solltest Du noch dabei schreiben, daß man noch die Interrupts erlauben soll, einen Vektor schreiben muß, außerdem noch den Stackpointer usw.
Wie ich sehe willst Du PortB invertieren, mach das so:


loop:
in mp,TIFR
sbrs mp,TOV0
rjmp loop
ldi mp,(1<<TOV0)
out TIFR,mp
com z1
out PORTB,z1
rjmp loop

Und zwar ohne Interrupt ;-)

Schau im Dattenblatt, was TIFR und TOVO zu sagen haben und wenn Du das verstanden hast, kannst Du Dich mit der Interruptversion auseinander setzen.

Gruß Sebastian

maximat
01.02.2008, 19:08
Vielen Dank für die Hinweise, ich bin mit meinem erstenVersuch ganz zufrieden, letzlich ist es ja nicht sinnvoll, die Timer im Polling Modus nur mit Zählen zu beschäftigen, meine nächste lektion sind die Interrupts

Herzlich
Klaus

izaseba
01.02.2008, 21:57
letzlich ist es ja nicht sinnvoll, die Timer im Polling Modus nur mit Zählen zu beschäftigen

Sag das nicht, manchmal ist es sinnvoller zu warten, als den Interrupt zuzulassen ;-)

Gruß Sebastian

maximat
02.02.2008, 12:14
Hallo Sebastian, hier isnd meine Schularbeiten, war nicht leicht aber sehr interessant
loop:
in mp,TIFR ; holt interrupt Flag Register in mp
sbrs mp,TOV0 ; prüft ob TOV0 gesetzt ist
rjmp loop ; wenn ja überspringe den nächsten Befehl sonst loop
ldi mp,(1<<TOV0) ; setze TOV0 in mp auf 1 was TOV0 klärt
out TIFR,mp ; out in Interrupt flag reg
com z1
out PORTB,z1
rjmp loop

wenn ich das so nachrechne, komme ich mit dem Vorteiler 1024
auf eine Blinkfrequenz von 0,38 Hertz
Heißt das dass der Controller mit 1 Mhz die Befehle abarbeitet
0,3814 X 256 X 1024 = 1Mhz
Der Resonator hat 8 Mhz, geht es auch schneller als 1 Mhz?
Danke
Klaus

izaseba
02.02.2008, 13:32
Hallo Klaus,


ldi mp,(1<<TOV0) ; setze TOV0 in mp auf 1 was TOV0 klärt

Ich weiß nicht...
Hier wird TOV0 nicht 1 gesetzt, sondern durch schreiben einer 1 in TOVO (und Achtung, nur TOV0 sonst keinen anderen Bit) wird TOV0 gelöscht.

Schau mal auf meiner HP rein (http://izaseba.roboterbastler.de/index.php?popup=Tutorial&section=Lektion10) Da habe ich das alles (hoffentlich) verständlich beschrieben ;-)

Deine Rechnerei ist soweit richtig alle 262 mS wird PORTB umgeschaltet.

Was den Takt angeht, ja Tiny 25 wird mit 8MHz getaktet aber standardmäßig ist auch CLKDIV8 Fuse gesetzt, wo der Takt natürlich auf 1MHz runtergesetzt wird.

Arbeitest Du mit Studio?

Schau Dir dann die Fuses an CLKDIV8 müsste programmiert sein(Achtung
programmiert -> 0 unprogrammiert -> 1)
So ist es in der Hardware und im Studio bis 4.13.571 war es auch so (programmiert kein Häckchen unprogrammiert Häckchen).

In Studio 4.13.571 haben sie die Logik gedreht #-o

Alles was Du jetzt machst, machst Du auf eigene Verantwortung...

Fuses mit Read auslesen,
bei CLKDIV8 Häckchen machen, oder entfernen je nach Version(Sonst nichts ändern)
Fuses mit write schreiben.

Aber pass auf, je nachdem was Du sonst alles bei Fuses verstellst, kannst Dich ausperen und Dein µC läßt sich nicht mehr ansprechen.

So, was jetzt noch interessant ist, Du kannst Den Clockprescaller (genauso wie bei Timer) zwischen 1-256 verstellen .
\:D/
Das ist sehr praktisch bei Batteriebetrieb und vor allem, wenn man den Powerdownsleepmodus nicht nutzen kann.
Aber schau mal selbst im Dattenblatt nach Register CLKPR da wird alles erklärt.

Gruß Sebastian

maximat
02.02.2008, 20:00
Hallo Sebastian,
vielen Dank, das mit der Clockrate lasse ich ersteinmal, mit 1 Mhz ist gut rechnen.
Ich war auf deiner HP und habe mich über die Beispiele gefreut. Habe das Interruptprogramm abgetippt und versucht die Register an den Tiny 25 anzupassen, leider ohne Erfolg, trotz intensiver Suche im Datenblatt
Kannst du mir die entsprechen Register nennen
.org OC2addr -- der 25 hat Timer 0 und 1, ich finde keinen Restevoektor hierfür (im Datenblatt S. 50)
OCR2 könnte OCR0A sein es gibt auch OCR0B
TCCR2 könnte TCCR0B sein (dort wir prescaler eingestellt
OCIE2 könnte OCIE0A sein dazu gibt es im Datenblatt keinen Hinweis auf den dazugehörenden Interruptvektor
Ich hoffe, du kannst nachvollziehen , wo ich hänge

so ganz für dummies ist deine Seite ja nicht - wenn man nicht nur abtippt sondern auch mitdenken will
Herzlich Klaus

izaseba
02.02.2008, 21:35
Ja,ja, die Vektoren, die machen die Assemblerprogramme leider nicht 100% kompatibel :-(

Es gibt aber eine einfache Abhilfe:
Man macht sich im Falle von tn25 die tn25def.inc Datei auf, sie liegt unter Atmel/Assembler2/Appnotes und scrollt ganz zum Ende.
Jetzt sieht man sowas:


; ***** INTERRUPT VECTORS ************************************************
.equ INT0addr = 0x0001 ; External Interrupt 0
.equ PCI0addr = 0x0002 ; Pin change Interrupt Request 0
.equ OC1Aaddr = 0x0003 ; Timer/Counter1 Compare Match 1A
.equ OVF1addr = 0x0004 ; Timer/Counter1 Overflow
.equ OVF0addr = 0x0005 ; Timer/Counter0 Overflow
.equ ERDYaddr = 0x0006 ; EEPROM Ready
.equ ACIaddr = 0x0007 ; Analog comparator
.equ ADCCaddr = 0x0008 ; ADC Conversion ready
.equ OC1Baddr = 0x0009 ; Timer/Counter1 Compare Match B
.equ OC0Aaddr = 0x000a ; Timer/Counter0 Compare Match A
.equ OC0Baddr = 0x000b ; Timer/Counter0 Compare Match B
.equ WDTaddr = 0x000c ; Watchdog Time-out
.equ USI_STARTaddr = 0x000d ; USI START
.equ USI_OVFaddr = 0x000e ; USI Overflow

.equ INT_VECTORS_SIZE = 15 ; size in words


Was einem auffält, es gibt für Timer 0 direkt 2 Compare Match Kanäle, die auch mit 2 verschiedenen Pins verbunden werden können PB0 und PB1.
Das ist aber für den Fall egal.
Du suchst Dir einfach einen aus und nimmst entweder den OC0Aaddr oder den OC0Baddr Vektor.
Dann aber anstatt von OCR2 OCR0A bzw. OCR0B und der Rest genauso ;-)

Du kannst es auch im Simulator durchspielen...

Tja, die Sache mit Dummies he,he
Ich wollte was einfaches schreiben,was jeder versteht, mit anderen Tutorials haben manche Leute Probleme, und wenn man versucht irgendwas auf eine lockere Weise zu übermitteln wird das eher verstanden.

Ob es mir gelungen ist weiß ich nicht so recht, dafür gibt es zu wenig Feedback, leider wollen immer weniger Leute was mit Assembler zu tun haben :-(
Es soll ja nicht heißen, daß man nur noch Assembler macht, ich programmiere öfter auch in C, aber so ein Crashkurs von sag ich mal 2 Wochen würde sehr vielen Leuten gut tun...

Gruß Sebastian

P.S.
Wie ich sehe hast Du doch schon einiges selber rausgefunden ;-)

maximat
04.02.2008, 11:35
Hallo, es läuft alles ganz gut mit den Timern und den Interrupts, die Nutzung des Vergleichsregisters schafft eine Feinabstimmung der Zeit, die man im normalen Timerüberlauf Interrupt damit erreicht, dass man in der IR Routine den Timerinhalt neu setzt. So bekomme ich bei Teilerfaktor 1024 und 3x 162 (162 in TCNT0) ziemlich genaue 2 Hertz, die ich haben wollte.

Ich habe ein weiteres Problem mit der indirekten Adressierung, vielleicht müsste ich dazu ein neues Thema aufmachen?
Frage: Wie bekomme ich in R16 den Inhalt des Registers, dessen Adresse in R0 steht?

oder im Flash stehen 10 Daten z.B an hex10, die in beliebiger Wahl über das Register ZL/ZH ausgelesen werden sollen, mal das vierte mal das siebente usw. (nicht mit ADIW, da dies das ZL verändert)
herzlich Klaus

maximat
04.02.2008, 12:42
Die letzte Frage hätte ich mir sparen können:
ich halte die Adresse in zwei Registern R1=ZL, R2=ZH und den Offset in R3 dann die Adresse in ZL/holen und Offset zu ZL hinzuaddieren, mit lpm abholen...
kennt jemand eine Lösung für die erste Frage?

izaseba
05.02.2008, 21:19
Frage: Wie bekomme ich in R16 den Inhalt des Registers, dessen Adresse in R0 steht?

Hmmm welche Adresse steht den in R0 ?
Gemappte SRAM Adresse ?

Hmmm,was mir spontan einfällt ist sowas:



ldi r16,16
mov r0,r16 ;in r0 landet die Adresse von Register r17
ldi XL,0 ;X Zeiger auf SRAM 0 -> r0
ldi XH,0 ;dito
ldi r17,0x80 ;Schreibe irgendwas in Zielregister
add XL,r0 ;addiere den inhalt von r0(Adresse von r17)
ld r16,X ; in r16 steht jetzt 0x80


Es ist zwar blöd über einen Zeiger zu gehen, was besseres fällt mir im Moment aber nicht ein :-(

Im Simulator klappt es aber ;-)

Gruß Sebastian

maximat
06.02.2008, 15:48
Vielen Dank, das ist noch mehr als über das ZRegister mit Offset. dann bin ich mit meiner Lösung über das Flash oder Sram zufrieden.
Hier noch ein Feedback zu deiner HP: Beim Thema interupt hätte es mir geholfen, erst etwas über das grundlegenede Interruptverfahren zu erfahren, laso erst den entspechen Interrupt im z.B. Timerregister feigeben und dann sei. Damit gibt es mehrere Möglichkeiten IRs freizugeben. Auch mit welchen Flags Ergebnisse gepollt werden können.
Wenn mans erstmal geschnallt hat ist es einfach und logisch
herzlich Klaus

izaseba
06.02.2008, 18:17
Hallo Klaus,

Beim Thema interupt hätte es mir geholfen, erst etwas über das grundlegenede Interruptverfahren zu erfahren, laso erst den entspechen Interrupt im z.B. Timerregister feigeben und dann sei. Damit gibt es mehrere Möglichkeiten IRs freizugeben. Auch mit welchen Flags Ergebnisse gepollt werden können.

Hmm, da bin ich mit bei 'Timer Teil I' eingestiegen also ohne Interrupt, sondern den TOV* pollen :-k ist das zu knapp ?

Ich muß darüber nachdenken, danke

Gruß Sebastian