PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kummer mit CTC (mode 4)



robocat
29.08.2006, 15:12
liebe assembler gemeinde,
seit tagen plage ich mich mit meinem atmega8 (1MHz takt) und folgendem problem herum:
der CTC Timer soll ein 33kHz rechteck an PB1 erzeugen, gleichzeitig sollen in der hauptschleife im 1s takt PB0, PD7 und PD5, PD6 abwechselnd geschalten werden.
beides funktioniert für sich genommen ganz prima, aber alles zusammen will partout nicht klappen.


.NOLIST
.INCLUDE <m8def.inc>
.LIST
.CSEG

RESET:
rjmp init
rjmp DUMMY
rjmp DUMMY
rjmp DUMMY
rjmp DUMMY
rjmp DUMMY
rjmp MYINT
rjmp init
rjmp MYINT

.ORG INT_VECTORS_SIZE

init:
ldi R16,HIGH(RAMEND)
out SPH,R16
ldi R16,LOW(RAMEND)
out SPL,R16

; CTC klarmachen
ldi r17,0;
ldi r16,(1<<WGM12)|(1<<CS10)
out TCCR1A,r17
out TCCR1B,r16

; port b und d als ausgang
LDI r24,255
OUT DDRB,r24
LDI r24,255
OUT DDRD,r24

; interrupt
ldi r16,(1<<OCIE1A)|TIMSK;
out TIMSK,r16

; zaehler laden
ldi r16,0
out OCR1AH,r16
ldi r16,255 ;29 (mit 29 sind es ca 33kHz, mit 255 ca 3,8kHz)
out OCR1AL,r16

; PB1 ist anfangs HIGH
ldi r18,2
out portb,r18

sei ; Interrupts aktivieren

; hauptschleife
loop:
ldi r24,32
out portd,r24

; delay loop, 1Hz
ldi r17,$09
WGLOOP0: ldi r18,$BC
WGLOOP1: ldi r19,$C4
WGLOOP2: dec r19
brne WGLOOP2
dec r18
brne WGLOOP1
dec r17
brne WGLOOP0
nop

ldi r24,192
out portd,r24; PD5+6 auf HIGH

; delay loop, 1Hz
ldi r17,$09
WGLOOP3: ldi r18,$BC
WGLOOP4: ldi r19,$C4
WGLOOP5: dec r19
brne WGLOOP5
dec r18
brne WGLOOP4
dec r17
brne WGLOOP3
nop

; immer wiederholen
rjmp loop

; isr, klappt nicht mit meinen pushes..
MYINT:
;push r16
;push r17
;push r18
;push r19
;ldi r20,SREG
;push r20
;push r23
;push r24

; toggle funktion:
; "wenn portb=0 ist, wird portb=2"
; "wenn portb=2 ist, wird portb=0"

ldi r20,0
ldi r21,portb
cp r21,r20
breq setport
out portb,r20
rjmp intend

setport:
ldi r21,2
;ldi r22,portb
;or r21,r22
out portb,r21

intend: ; auch diese pops taugen nicht
;pop r24
;pop r23
;pop r20
;out SREG,r20
;pop r19
;pop r18
;pop r17
;pop r16

reti

DUMMY:
reti


vielleicht ist der atmel mit 1MHz auch zu langsam für das, was ich erreichen will? dann würde ich ein 16MHz quarz dranbasteln. aber auch mit erheblich niedrigerer CTC frequenz geht es nicht.

ausserdem komme ich mit push und pop nicht zurecht. im code sind diese befehle auskommentiert, da ansonsten gar keine 33kHz zustande kommen. aber eigentlich ist es doch ein LIFO, also warum sollte das nicht gehen?

entschuldigt die vielleicht dummen fragen, ich bin noch kein ASM experte, und habe mich bemüht, es alleine (mit datenblatt und forum-suche) zu schaffen. nur langsam verzweifle ich.

bin dankbar für jede hilfe!

eure katze

Hanni
30.08.2006, 15:51
Oha ...

Die push & pop Dinger müssen sein. Ohne die bringst du dein Programm total durcheinnder.
heisst es: in r20, SREG und nicht ldi r20, SREG
Hast du bei den Werten für das OCR1A Register einen Denkfehler drin. Da du bei einem Überlauf des Timers einen Pin togglest, musst du schon mit der doppelten Frequenz rechnen. daher wären 33 kHz = 14 für das OCR1A Register.
In den verfügbaren 15 Takten kann deine ISR aber niemals abgearbeitet werden.


Lösungsmöglichkeiten:

den Takt erhöhen. Damit ergibt sich natürlich auch ein anderer Wert für das OCR1A
oder dem µC das togglen komplett überlassen. d.H. COM1A0 im TCCR1A setzen und die ISR komlett wegfallen lassen (siehe Datenblatt Seite 97)


Im übrigen haste hier schonmal einen sortierten Code für die 2te Version.



.NOLIST
.INCLUDE <m8def.inc>
.LIST


; MCU Takt für diverse Berechnungen festlegen
.equ tosc = 1000000

; Ausgabefreq festlegen
.equ fout = 33000

; Timer 1 Ladewert
.equ ladewert = (tosc / (2 * fout)) - 1

.CSEG
.org 0


; Interupt Vektoren
rjmp init ; Reset Handler
reti ; IRQ0 Handler
reti ; IRQ1 Handler
reti ; Timer2 Compare Handler
reti ; Timer2 Overflow Handler
reti ; Timer1 Capture Handler
reti ; Timer1 CompareA Handler
reti ; Timer1 CompareB Handler
reti ; Timer1 Overflow Handler
reti ; Timer0 Overflow Handler
reti ; SPI Transfer Complete Handler
reti ; USART RX Complete Handler
reti ; UDR Empty Handler
reti ; USART TX Complete Handler
reti ; ADC Conversion Complete Handler
reti ; EEPROM Ready Handler
reti ; Analog Comparator Handler
reti ; Two-wire Serial Interface Handler
reti ; Store Program Memory Ready Handler



init:
ldi r16, high(RAMEND); Stackpointer initialisieren
out SPH, R16
ldi r16, low(RAMEND)
out SPL, R16

ldi r24, 255
out DDRB, r24 ; Port B als Ausgang
out DDRD, r24 ; Port D auch
out PORTC, r24 ; Pullups von Port C aktivieren
; (-> damit hat dieser einen definierten Pegel
; und nicht osziliert sinnfrei rum)




ldi r17, (1<<COM1A0) ; Timer 1 konfigurieren (Mode 4 -> CTC)
ldi r16, (1<<WGM12)|(1<<CS10)
out TCCR1A, r17
out TCCR1B, r16

ldi r16, high(ladewert)
out OCR1AH,r16
ldi r16, low(ladewert)
out OCR1AL,r16


; in r16, TIMSK ; Diese auskommentierten Zeilen sind hier unnötig,
; ori r16, (1<<OCIE1A) ; ich habe sie nur drinne gelasen um zu zeigen,
; out TIMSK, r16 ; wie ich es machen würde

sei ; Interrupts aktivieren


loop: ; hauptschleife
ldi r24, 32
out PORTD, r24

ldi r17, 0x09 ; delay loop, 1Hz
WGLOOP0:
ldi r18, 0xBC
WGLOOP1:
ldi r19, 0xC4
WGLOOP2:
dec r19
brne WGLOOP2
dec r18
brne WGLOOP1
dec r17
brne WGLOOP0
nop

ldi r24, 192
out portd, r24 ; PD5+6 auf HIGH

ldi r17, 0x09 ; delay loop, 1Hz
WGLOOP3:
ldi r18, 0xBC
WGLOOP4:
ldi r19, 0xC4
WGLOOP5:
dec r19
brne WGLOOP5
dec r18
brne WGLOOP4
dec r17
brne WGLOOP3
nop

rjmp loop



Ich hoffe dir damit geholfen zu haben.

Grüße,
da Hanni.

robocat
30.08.2006, 20:36
danke! ja, ich denke das hilft mir um einiges weiter. danke auch für den code, das ist sehr freundlich von dir, dass du dir die mühe gemacht hast O:)
ich werde das dann gleich einmal testen. ich dachte mir fast, dass der toggle interrupt unnötig ist, aber ich habe es nicht anders hinbekommen.

nochmal danke und gruesse von der katz

Hanni
30.08.2006, 20:53
Gern geschehen :D