PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Attiny861A - Timer1 läuft viel zu schnell



dj_cyborg
29.07.2013, 09:58
Hallo,

Ich seh momentan das Problem nicht, evtl. kann mir mal jemand die Augen öffnen.

Ich habe einen Attiny861A mit 8MHz, ich benutze den Timer1 um eine Frequenz von 1 Hz zu erzeugen.

Leider läuft der Timer viel zu schnell. Was habe ich falsch gemacht?

-der Attiny861A wird von meinen mySmartUSB MK2 -Programmer als Attiny861 erkannt. (ohne A, lässt sich aber trotzdem beschreiben)
-im Chip habe ich 8Mhz ohne Teiler durch 8
-Timerwerte habe ich mit rnAVR berechnet. "Const Timervorgabe = 34286" will er nicht, ich muß die Timervorgabe als Word dimensionieren. (hatte ich auch noch nicht)
-mit Wait 1 passt das Timing Augenscheinlich
-macht BASCOM einen unterschied zwischen Attiny861 und Attiny861A?

Hier mal mein Testcode:


$regfile = "attiny861.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32


Config Timer1 = Timer , Prescale = 256

Config Pinb.4 = Output
Led3 Alias Portb.4
Led3 = 1

On Timer1 Timer_irq

'Const Timervorgabe = 34286 'Fehler: Value doesn't fit into Byte
Dim Timervorgabe As Word
Timervorgabe = 34286

Enable Timer1
Enable Interrupts


Do

Loop

Timer_irq:
Timer1 = Timervorgabe

Toggle Led3
'Wait 1
Return

Danke für Eure Hilfe

mfG
Mario

askazo
29.07.2013, 10:14
Timer1 ist ein 10-Bit Timer/Counter, kann also bis maximal 1023 zählen...
Entweder Du setzt den Prescaler höher oder Du benutzt den 16-Bit Timer0.

Gruß,
askazo

dj_cyborg
29.07.2013, 10:29
Hallo askazo,

danke für deine Antwort.

mmmmh... ich dachte Timer1 ist der 16Bit Timer und Timer0 ein 8Bit Timer.

Hab im Datenblatt nur folgendes gefunden.


• Peripheral Features
– One 8/16-bit Timer/Counter with Prescaler
– One 8/10-bit High Speed Timer/Counter with Prescaler
• 3 High Frequency PWM Outputs with Separate Output Compare Registers
• Programmable Dead Time Generator

Also ist dann Timer0 der 16Bit Timer?

mfG
Mario


Edit: mit Timer0 nimmt Bascom schonmal "Const Timervorgabe = 34286". Läuft aber immernoch viel zu schnell. :(


$regfile = "attiny861.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 32


Config Timer0 = Timer , Prescale = 256

Config Pinb.4 = Output
Led3 Alias Portb.4
Led3 = 0
Enable Timer0
On Timer0 Timer_irq

Const Timervorgabe = 34286

Enable Interrupts

Do

Loop

Timer_irq:
Timer0 = Timervorgabe

Toggle Led3
'Wait 1
Return

oberallgeier
29.07.2013, 10:49
... ich dachte Timer1 ist der 16Bit Timer und Timer0 ein 8Bit Timer ... im Datenblatt nur folgendes gefunden ...Kann es sein, dass Du nur das 22-seitige Datenblatt hast? Nimm mal die volle Prise (klick da). (http://www.atmel.com/images/doc8197.pdf) Und lies bei Kapitel 11 und 12.

DanielSan
29.07.2013, 11:06
Deine Timerberechnung ist erstmal korrekt. Deine IRQ wird alle 1.09 sec aufgerufen. Jedenfalls theoretisch...

Was heisst denn der Timer läuft zu schnell? Wie schnell wird die IRQ aufgerufen?

dj_cyborg
29.07.2013, 11:14
Hallo oberallgeier,

vielen Dank für deine Antwort und deinen Link.

Also wenn ich das richtig verstanden habe muß ich den Timer0 vom 8Bit-Mode auf 16Bit-Mode umschalten?!

Sowas hatte ich bis jetzt leider noch nicht. Es sind ja Codeschnipsel in C aufgeführt aber wie mache ich das in Bascom?

Danke

mfG
Mario

- - - Aktualisiert - - -

Hallo DanielSan,

Danke für deine Antwort.

also die ToggleLed leuchtet fast durchgehend. Bei 1Hz sollte sie ja gemütlich Blinken.
Der Timer0 scheint wohl beim Attiny861A ein paar Eigenheiten zu haben.

mfG
Mario

oberallgeier
29.07.2013, 11:25
Hi Mario,

gern geschehen. Leider kann ich Dir mit Bascom nicht (weiter) helfen, ich schreibe meine Programme in C und Spuren von Assembler. Aber es wird sich schon jemand finden. Ich würde halt (in Bascom) versuchen, die Befehle von C nach B zu "übersetzten" - das MUSS gehen.


... muß ich den Timer0 vom 8Bit-Mode auf 16Bit-Mode umschalten ...Ich will jetzt nicht für Dich die beiden Timerabschnitte durcharbeiten, aber es gibt sicher einen Timer der "per default" läuft. Und den könntest Du ja dann nehmen . . . . OHNE Verrenkungen.

Übrigens: hast Du die CKDIV8-Fuse ausgeschaltet? ABER - bitte unbedingt davor den Abschnitt 6.2.7 Default Clock Source lesen - denn der tiny861A hat da ein paar Unartigkeiten eingebaut (wozu MUSST Du denn unbedingt diesen nehmen??)

dj_cyborg
29.07.2013, 11:51
Nein, brauchst nicht durcharbeiten ;) hast mir schon sehr geholfen.
Ich werde jetzt wohl den 8Bit Timer nehmen, mal sehen ob er zu schnell für meinen Schrittmotor ist.

Bisher hatte ich nur MC's bei denen der Timer0 = 8Bit und der Timer1 = 16Bit waren, deswegen hatte ich mir darüber gar keine Gedanken gemacht.

Den Teiler hatte ich schon rausgenommen, das overclocking spielt denke ich nur bei niedriger Betriebsspannung eine Rolle. (<2,7V).

Da ich nicht im Besitz eines Oszilloskop bin, stelle ich gern zum Test den Timer auf 1Hz, um zusehen ob der grundsetzlich erstmal richtig arbeitet.

Danke nochmal

mfG
Mario

DanielSan
29.07.2013, 11:56
Im Datenblatt (S.76) stehen ja die Modes von Timer0. Der ist schonmal der richtige der kann auch 16-bit. Du musst das Register TCW0 auf 1 setzen. Wie man das in Bascom macht? Ehrlich gesagt gaaanz sicher bin ich mir nicht aber versuchs mal so:



$regfile = "attiny861.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 32

Config Timer0 = Timer , Prescale = 256
' Timer0 konfigurieren
Tccr0a = &B1000_0000
Tccr0b = &B0000_0101

Config Pinb.4 = Output
Led3 Alias Portb.4
Led3 = 0
Enable Timer0
On Timer0 Timer_irq
Const Timervorgabe = 34286
Enable Interrupts

Do

Loop

Timer_irq:
Timer0 = Timervorgabe
Toggle Led3
'Wait 1
Return

Das rote hab ich hinzugefügt. Damit setzt du die Register manuell. Bascom kennt egtl nur Timer0 = 8bit, Timer1 = 16bit und Timer2 = 8bit.

Ich übernehme aber keine Verantwortung falls was schief geht!

Gruß Daniel

dj_cyborg
29.07.2013, 12:10
Tausend Dank Daniel,

Jetzt Blinkt die Led deutlich langsamer ;).

Nur leider zu langsam die Led toggelt etwa im 5sekunden Takt :confused:

mfG

Mario

DanielSan
29.07.2013, 12:18
Wenn du sie bei genau 1 sec blinken lassen willst solltest du die Timervorgabe auf "31250" setzen.

Im 5sec Takt? Da stimmt doch noch irgendwas nicht.

Edit: Ich weiss auch was nicht stimmt! XD Im Code wird der Prescaler 2 mal gestetzt. Nimm mal die Zeile "Tccr0b = &B0000_0101" raus oder änder sie in "Tccr0b = &B0000_0100". Dann sollte es passen. Guck dir mal auf Seite 84 das Register an.

dj_cyborg
29.07.2013, 12:50
Ich muß mich revidieren... genau 8 Sekunden.

Ich versteh jetzt gar nichts mehr, ich hab den $crystal = 8000000 auf $crystal = 1000000 geändert.

Er blinkt mit selben Geschwindigkeit weiter. Sowas...

Das gleiche wenn ich den Teiler durch 8 wieder einschalte.

mfG

Mario

- - - Aktualisiert - - -

Vielen Dank für deine Hilfe.

Es blinkt jetzt etwa im 2 Sekunden Takt.

mfG

Mario

DanielSan
29.07.2013, 13:09
Meinst du 1 sec Led = AN und 1 sec Led = AUS? Falls ja, das ist auch genau das was dein Code machen soll. Wenn das insgesamt 1 sec dauern soll musst du die Timervorgabe halbieren.

Gruß Daniel

oberallgeier
29.07.2013, 13:19
... $crystal = 8000000 auf $crystal = 1000000 ... selben Geschwindigkeit ... Teiler durch 8 wieder einschalte ...Schön, dass es jetzt klappt. Mario ich hoffe, dass Du die Compileranweisung $crystal und eine gesetzte/gelöschte Fuse - in diesem Fall CKDIV8 - nicht verwechselst. Das wären ZWEI grundverschiedene Aktionen - die übrigens nicht dasselbe bewirken. Aber ich vermute, dass Dir das klar ist.

dj_cyborg
29.07.2013, 13:58
Nein, Leider nicht ganz, 2 Sek LED an und 2 Sek LED aus.

Mit den Einstellungen:
-$crystal = 8000000
-8Mhz gefused
-Teiler aus

@oberallgeier
wenn ich 8Mhz und den Teiler 8 reinnehme muß ich ja auch $crystal = 1000000 schreiben und den Timer am neuen Systemtakt anpassen. Ist doch Richtig oder?

Ich muss leider erstmal bissl Arbeiten gehen.

Ich melde mich Morgen dann nochmal.

Tausend Dank euch Beiden.

mfG

Mario

oberallgeier
29.07.2013, 14:26
... 8Mhz und den Teiler 8 reinnehme muß ich ja auch $crystal = 1000000 schreiben ... Timer am neuen Systemtakt anpassen. ...Genau, nichts für ungut dass ich nachfragte. War ja eigentlich schon sicher, dass Du es so machst.

peterfido
29.07.2013, 15:49
Den Timer sollte die Crystal-Angabe nicht interessieren. Der arbeitet stur nach seinen Registern.

dj_cyborg
29.07.2013, 22:04
So, mir hat es keine Ruhe gelassen...

Der Fehler liegt an "Timer0 = Timervorgabe". Timer0 (TCNT0) ist für Bascom ein 8Bit Timer. Nachdem ich diesen aber als 16Bit schalte kann ich aber nicht mehr auf Timer0-Wert zugreifen/setzen.
Für Timer1 funktioniert das, da Bascom die 2 8Bit Register (TCNT1H und TCNT1L) als ein pseudoregister Timer1 (TCNT0) bereit stellt. Das ist aber für Timer0 nicht vorgesehen.

Eine schöne Beschreibung die mir auf die Sprünge geholfen hat: http://halvar.at/elektronik/kleiner_bascom_avr_kurs/timer_counter/

Und das gleiche Thema schonmal diskutiert: http://www.avr-praxis.de/forum/showthread.php?557-16-Bit-Mode-f%FCr-Timer0

Da die Timervorgabe ignoriert wurde hatte ich eine Frequenz von 0,47684Hz also 2Sekunden Blinkfrequenz.

Da das Pseudoregister nicht mehr angesprochen werden kann (evtl. gibts eine neuere "attiny861.dat"), muß der Vorgabewert direkt in die beiden 8Bit-Register TCNT1H und TCNT1L (beim attiny861:TCNT0H und TCNT0L) geschrieben werden.

Ich bin mir nur noch nicht ganz sicher wie ich die 16Bit-Timervorgabe auf die beiden 8Bit-Register aufteilen muss, um auf 1Hz Timerfrequenz zu kommen.
Evtl. kann mir das noch jemand erklären? (Mit Timervorgabe*4 sieht es zumindest Augenscheinlich wie 1Hz aus)


$regfile = "attiny861.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 32
$framesize = 32



'Config Timer0 = Timer , Prescale = 256

Tccr0a = &B1000_0000 '16Bit Mode einschalten
Tccr0b = &B0000_0100 'Prescale=256

Config Pinb.4 = Output
Led3 Alias Portb.4
Led3 = 0
Enable Timer0
On Timer0 Timer_irq

Const Timervorgabe = 34286

Enable Interrupts

Do

Loop

Timer_irq:
'Timer0 = Timervorgabe 'Bascom kennt Timer0 nicht als 16Bit Timer
Tcnt0h = Timervorgabe * 4 '
Tcnt0l = Timervorgabe * 4
Toggle Led3
'Wait 1
Return

Danke für Eure Hilfe

mfG
Mario

DanielSan
29.07.2013, 23:09
Versuchs mal so:

Tcnt0h = &b0111_1010
Tcnt0l = &b0001_0010

Anstelle von Timervorgabe.

31250 = 0111101000010010 als 16bit. Das sollte als Erklärung für dich reichen! So weit wie du schon gekommen bist ;-)
Ich weiss ja nicht wie du auf 34286 gekommen bist aber wenn du genau 1 sec willst musst du 31250 nehmen.

dj_cyborg
30.07.2013, 07:49
Guten Morgen,

ja, spitze so klappt es. :rolleyes:

tausend Dank

zum Thema Timervorgabe:
Ich habe den Timer mit dem rnAVR von Roboternetz gerechnet. (siehe Bild)26109
Es kommt da exakt 1-Sekunden-Takt raus.

nachgerechnet:
Von meinen 8Mhz wird nur jeder 256 Takt gezählt also 31250 Takte/sek. Um aber einen Überlauf bei 65535 zu erreichen, muß ich schon ab 34286 anfangen zu zählen.
Oder habe ich einen Denkfehler?

mfG
Mario

DanielSan
30.07.2013, 12:35
Ups der Denkfehler liegt bei mir! So wie du es geschrieben hast ist es richtig sry!

askazo
30.07.2013, 13:05
Kann man in Bascom eigentlich nicht den CTC-Mode benutzen?
Dann braucht man nicht jedesmal in der ISR den Timer neu zu setzen...

Gruß,
askazo

DanielSan
30.07.2013, 13:33
Doch müsste gehen indem man die Register passend setzt. Wie das geht steht hier ja schon mehr oder weniger.