Forum: Mikrocontroller und Digitale Elektronik Atmega16 TCNT1H Problem


von Eric Barmeyer (Gast)


Lesenswert?

Hallo,

ich bin relativ neu in der Welt der AVR und versuche momentan mittels 
Assembler Timer1 meines ATmega16 beizubringen im Sekundentakt einen 
Overflow zu generieren. In C hat das ganze bereits wunderbar geklappt, 
allerdings klappt folgender ASM-Code nicht so, wie ich es mir erhofft 
habe:
1
.INCLUDE <m16def.inc>
2
3
reset:
4
RJMP main
5
6
.org OVF1addr
7
RJMP timer1_overflow
8
9
10
.DEF tmp = r22
11
12
main:
13
LDI tmp,high(RAMEND)
14
OUT SPH,tmp
15
LDI tmp,low(RAMEND)
16
OUT SPL,tmp
17
18
LDI tmp, (1<<CS10) | (1<<CS12) // Timer1 Prescaler 1024
19
OUT TCCR1A, tmp
20
21
LDI tmp, (1<<TOIE1) // Timer1 Overflow Handler aktivieren
22
OUT TIMSK, tmp
23
24
LDI tmp, 0xE3
25
OUT TCNT1H,tmp  // Bis hier klappt alles wunderbar, TCNTH1 ist 0xE3...
26
LDI tmp, 0xE0   // ...aber ab hier ist TCNT1H laut Simulation wieder 0x00
27
OUT TCNT1L,tmp
28
29
SEI
30
31
32
timer1_overflow:
33
// hier versuch ich das selbe Spiel wie oben, ebenfalls erfolglos
34
RETI

TCNT1H lässt sich einfach nicht ändern. Ich hab auch die Routinen aus 
dem Manual versucht, jedoch blieb auch dies erfolglos.

Ich hoffe jemand weiß Rat :)

von crazy horse (Gast)


Lesenswert?

sehr bekannter Anfängerfehler, schau mal ins Datenblatt, wie 
16bit-Register zu schreiben/lesen sind :-)

von Eric Barmeyer (Gast)


Lesenswert?

Danke für die schnelle Antwort, auch wenn mich das nicht sofort weiter 
bringt, muss ich wohl weiter das Manual wälzen ;(

von Johannes M. (johnny-m)


Lesenswert?

crazy horse wrote:
> sehr bekannter Anfängerfehler, schau mal ins Datenblatt, wie
> 16bit-Register zu schreiben/lesen sind :-)
Nö. Das ist schon OK so (vielleicht auch zufällig...?). Beim Schreiben 
erst das High-Byte, beim Lesen erst das Low-Byte. Das Low-Byte triggert 
den jeweiligen Vorgang.

Das Problem in diesem Fall ist vermutlich eher der Simulator und nicht 
das Programm. Der AVRStudio-Simulator ist an der Stelle ein wenig buggy.

Zitat AVRStudio-Hilfe:
"Some simulator modules do not properly simulate the register buffering 
and write order requirement of register pairs such as TCNT1H/TCNT1L. The 
value of the high byte register is immediately set when written to.

Some register bits that should be cleared by setting them (writing 1) 
will be cleared if they are written to 0."

Einen Workaround bietet die Hilfe in diesem Fall nicht (ich hab 
zumindest jetzt keinen gefunden).

Die Frage ist allerdings, ob es tatsächlich erforderlich ist, das TCNT1 
zu schreiben. Das ist nämlich in den seltensten Fällen wirklich nötig. 
Wenn es ein Timer-Nachladen geht, um nach einer bestimmten Zeit einen 
Overflow zu erhalten, ist es bei den AVRs eigentlich üblich, das mit 
einer Compare-Einheit zu machen (z.B. im CTC-Modus) und dann den 
Compare-Interrupt auszuwerten. Schau Dir im Datenblatt und/oder im 
AVR-Tutorial vielleicht mal die Abschnitte zu den Compare-Einheiten 
an.

von Johannes M. (johnny-m)


Lesenswert?

BTW: Welche AVRStudio-Version hast Du? ich meine mich erinnern zu 
können, dass das Problem in älteren Versionen (ich selber habe 4.13 und 
daraus ist auch obiges Zitat) noch größer war.

von Eric Barmeyer (Gast)


Lesenswert?

Danke für die Hilfe. Dachte schon ich hätte was im Manual überlesen bzw. 
falsch gemacht.

@AVR-Version:
1
AVR Studio    4.13.528  
2
GUI Version    4, 13, 0, 528
3
AVR Simulator    1, 0, 2, 0


Das mit den Compare-Einheiten hatte ich auch bereits gelesen, danke für 
den Tipp.

von Eric B. (zaron)


Lesenswert?

So, mittlerweile hab ich das Ganze zum laufen gekriegt. Es war unter 
anderem falsch, im Register TCCR1A das erste und dritte Bit zu setzen 
(CS10 u. CS12), da diese nämlich in TCCR1B gesetzt werden müssen. 
Zusätzlich läuft's jetzt im CTC-Modus, wie's mir empfohlen wurde. Vielen 
Dank nochmals :)

Hier der Code:
1
.INCLUDE <m16def.inc>
2
3
reset:
4
RJMP main           ; Reset Handler
5
6
.org OVF1addr
7
RJMP timer1_overflow
8
9
.def tmp = r22
10
.def leds = r23
11
12
13
main:
14
LDI tmp,high(RAMEND)
15
OUT SPH,tmp
16
LDI tmp,low(RAMEND)
17
OUT SPL,tmp
18
19
SER leds
20
21
SER tmp
22
OUT DDRB, tmp
23
24
LDI tmp, (1<<CS10) | (1<<CS12) | (1<<WGM12) // Timer1 Prescaler 1024 und CTC-Mode
25
OUT TCCR1B, tmp
26
27
LDI tmp, (1<<FOC1A) // Force Output Compare
28
OUT TCCR1A, tmp
29
30
LDI tmp, (1<<OCIE1A) 
31
OUT TIMSK, tmp
32
33
LDI tmp, 0x1C
34
OUT OCR1AH,tmp
35
LDI tmp, 0x20
36
OUT OCR1AL,tmp
37
38
SEI
39
40
loop:
41
RJMP loop
42
43
timer1_overflow:
44
  OUT PORTB, leds
45
  COM leds
46
RETI
Mein Testboard hat nen 7,3728MHz Quarz und der AVR erzeugt mit diesem 
Code jede Sekunde einen Overflow. Vielleicht hilft es jemandem weiter :)

von Johannes M. (johnny-m)


Lesenswert?

Eric Barmeyer wrote:
> So, mittlerweile hab ich das Ganze zum laufen gekriegt. Es war unter
> anderem falsch, im Register TCCR1A das erste und dritte Bit zu setzen
> (CS10 u. CS12), da diese nämlich in TCCR1B gesetzt werden müssen.
Aha, da hab ich z.B. gar nicht drauf geachtet. Schön, dass es läuft...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.