Forum: Mikrocontroller und Digitale Elektronik ATmega32 Timer-Overflow (Assembler)


von Thomas N. (tonevi)


Angehängte Dateien:

Lesenswert?

Hallo allerseits,

obwohl ich die hier im Forum vorzufindenden Tutorials und das ATMega32 
Datenblatt zu Rate gezogen habe, gelingt es mir einfach nicht, einen 
Timer-Overflow für den ATMega32 in Assembler zu erzeugen. Im 
beiliegenden Code wird nach der Initialisierung der Ports und Variablen 
eine LED eingeschaltet (das funktioniert noch). Dann soll ein 
Timer2-Overflow nach 4ms eine Zählvariable bis 250 hochzählen und so 
nach 1s die LED wieder löschen. Das funktioniert leider nicht mehr. 
Irgendwas muss ich noch übersehen haben, sonst würde es funtionieren. 
Hat jemand eine Idee?

Thomas

von Karl H. (kbuchegg)


Lesenswert?

OHne jetzt alle Pfade verfolgt zu haben, fehlt dir auf jeden Fall hier
1
  clr msCount      ; Schleifenzähler löschen
2
;
3
  sei          ; Interrupt enable
4
;
5
TIM2_OVF:            ; sollte alle 4ms erfolgen
6
  push TEMP
erst mal die Hauptschleife, in der der Prozessor die Zeit über Däumchen 
dreht, bis der Interrupt kommt
1
  clr msCount      ; Schleifenzähler löschen
2
;
3
  sei          ; Interrupt enable
4
5
loop:                ; * Hauptschleife
6
  rjmp loop          ; *
7
8
;
9
TIM2_OVF:            ; sollte alle 4ms erfolgen
10
  push TEMP

von der alte Hanns (Gast)


Lesenswert?

Der Interrupt läuft auf ein reti, da dort alle Adressen falsch sind - 
Faktor 2.

von Karl H. (kbuchegg)


Lesenswert?

1
.equ TIMERwert  = 256-250  ; für 4ms Timer bei 16MHz Takt und internem Prescaler 1/256

die Berechnung stimmt nicht. Das geht sich nie aus.


Bei 16000000Mhz und einem Vorteiler von 1 würde der Timer in 1 Sekunde 
16000000 Zählvorgänge machen.
Bei einem Vorteiler von 256 logischerweise dann nur noch 1/256-tel 
davon.
Wieviel ist das? Nun, das ist 16000000/256 gleich 62500 Zählvorgänge in 
der Sekunde. D.h. für 1 Zählvorgang braucht der Timer daher 0.000016 
Sekunden. Für 6 Zählvorgänge (von 250 bis 256) braucht er daher 6 mal so 
lange. Das sind 0.000096 Sekunden. Das sind aber nicht 4ms sondern das 
sind 0.096 Millisekunden. Wenn alle 0.096 Millisekunden ein ISR Aufruf 
statt findet, dann dauert es daher 250 mal so lange, bis dein 
Zählregister den Wert 250 erreicht hat. Das ist daher nicht nach 1 
Sekunde der Fall, sondern nach 0.024 Sekunden - etwas mehr als 2 
Hunderstelsekunden.

Immer unter der Voraussetzung, dass der Rest des Programms stimmt 
(nachdem du die Sache mit der Hauptschleife korrigiert hast).
Hast du es mal unter Simulator-Kontrolle laufen lassen? Da kann man die 
Register wunderbar verfolgen und zusehen, was passiert.


Ausserdem: Meag32 und Progbleme mit dem Port C.
Da lautet die Standardfrage sofort: hast du das JTAG abgeschaltet?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

die Interrupt Tabelle ist IMHO auch falsch
1
;
2
; Interrupt-Sprungleiste für ATMeag32
3
;
4
rjmp RESET          ; Reset Handler
5
reti ;rjmp EXT_INT0      ; IRQ0 Handler
6
reti ;rjmp EXT_INT1      ; IRQ1 Handler
7
reti ;rjmp EXT_INT2      ; IRQ2 Handler
8
reti ;rjmp TIM2_COMP    ; Timer2 Compare Handler
9
rjmp TIM2_OVF        ; Timer2 Overflow Handler (8 Bit Zähler)
10
reti ;rjmp TIM1_CAPT    ; Timer1 Capture Handler
11
reti ;rjmp TIM1_COMPA    ; Timer1 CompareA Handler
12
reti ;rjmp TIM1_COMPB    ; Timer1 CompareB Handler
13
reti ;rjmp TIM1_OVF        ; Timer1 Overflow Handler (16 Bit Zähler)
14
reti ;rjmp TIM0_COMP    ; Timer0 Compare Handler
15
reti ;rjmp TIM0_OVF        ; Timer0 Overflow Handler ( 8 Bit Zähler)
16
reti ;rjmp SPI_STC      ; SPI Transfer Complete Handler
17
reti ;rjmp USART_RXC    ; USART RX Complete Handler
18
reti ;rjmp USART_UDRE    ; UDR Empty Handler
19
reti ;rjmp USART_TXC    ; USART TX Complete Handler
20
reti ;rjmp ADC        ; ADC Conversion Complete Handler
21
reti ;rjmp EE_RDY      ; EEPROM Ready Handler
22
reti ;rjmp ANA_COMP      ; Analog Comparator Handler
23
reti ;rjmp TWSI        ; Two-wire Serial Interface Handler
24
reti ;rjmp SPM_RDY      ; Store Program Memory Ready Handler
25
;
auf einem Mega32 liegen die Interrupt Vektoren, nicht wie auf einem 
Mega8 auf aufeinanderfolgenden Adressen, sondern auf jeweils geraden 
Adressen.

Du kannst dir selbst das Leben um einiges einfacher machen, wenn du dich 
nicht auf die implizite Adressvergabe aufgrund der Anzahl der reti 
Befehle verlässt, sondern indem du dem Assembler die jeweilige Adresse, 
an der der reti zu positionieren ist, explizit mit einem .org angibst. 
Dazu hat Atmel jeweils passende Namen in das inc-File eingefügt
1
;
2
; Interrupt-Sprungleiste für ATMeag32
3
;
4
     rjmp RESET          ; Reset Handler
5
.org INT0Addr
6
     reti ;rjmp EXT_INT0      ; IRQ0 Handler
7
.org INT1Addr
8
     reti ;rjmp EXT_INT1      ; IRQ1 Handler
9
.org INT2Addr
10
     reti ;rjmp EXT_INT2      ; IRQ2 Handler
11
.org ...

Ich weiss jetzt die Namen aller Interrupt Vektoren auch nicht auswenig. 
Aber du kannst dir das "m32def.inc" File aufmachen und dort reinschauen. 
Die müssen da drinnen alle irgendwo gesammelt vorkommen. Verwende sie in 
der angegebenen Art und Weise und du hast weniger Probleme.

von Thomas N. (tonevi)


Lesenswert?

Vielen Dank an alle für die schnelle und kompetente Hilfe. Es 
funktioniert jetzt!

Neben der fehlenden Leerschleife war wohl die Interrupt-Sprungleiste die 
Ursache für das beschriebene Problem. Ich hatte bisher schon etwas mit 
dem ATmega8 experimentiert, und mir war auch aufgefallen, dass der 
ATMega32 mehr Interrupts als der ATmega8 hat, dass diese aber nur auf 
geraden Adressen liegen hatte ich übersehen.

Die Timerkonstanten gemäß meiner Initialisierung scheinen aber zu 
stimmen, denn der Timer zählt doch nicht 6x 0,000016 Sekunden, sondern 
250x 0,000016 Sekunden = 4ms; wenn ich den Timer mit 256-250 = 6 lade, 
zählt er doch bis 256 hoch und das sind 250 Impulse. Jedenfalls geht die 
LED erst sichtbar verzögert aus.

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.