8-bits räknare och Interrupt i ATmega16

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Mattias
Inlägg: 37
Blev medlem: 4 juli 2003, 22:45:18

8-bits räknare och Interrupt i ATmega16

Inlägg av Mattias »

Tjupp

Var o köpte en ATmega16 för några dagar sedan och har suttit o lekt med den lite fram och tillbaks. Dock har jag trillat på ett litet problem som jag inte lyckas lösa, hoppas någon här kan hjälpa mig.
Jag hade tänkt använda ett interrupt som triggar på en räknare då räknarens värde är det samma som värdet i OCR0 - registret, dvs TIMO_COMP. Från denna interrupthandteraren ville jag skicka ett värde till huvudprogrammet genom att spara det i ett register som jag dedicerade för ändamålen, kanske inte den bästa lösningen, men det hade funkat smidigt här.
I alla fall. Detta fungerade inte och jag undrar varför. Istället får jag skriva till minnet i interrupthandteraren och därefter läsa ut värdet i huvudprogrammet. Detta funkar hur bra som helst.

Tyckte att fenomenet var intressant, så jag startade en tråd här och bifogar ett exempel, troligen har jag gjort något tokigt och då lär ni väl smälla mig på fingrarna hoppas jag :roll: :roll: . Jag jobbar förövrigt med avr-gcc samt de tillhörande verktygen där (inkl avrdude), ifall det finns något tok bland dessa som jag ej känner till.För att förtydliga allt, lägger jag ut mina konstanter i slutet. Hoppas någon kan hjälpa :roll:

På analogt sätt har jag provat att låta interruptrutinen skriva i io-registerna direkt. Värdet hålls bara giltigt så länge som interruptrutitnen exekverar. Känns skummt. Antingen har kretsen gått delvis trasig eller så börjar jag bli halvt tokig, eller så är allt som det ska.


Min kod ser ut som följer (hoppas jag skrev av rätt nu och fått med allt):
.org 0x000
intsetup:
rjmp main

.org 0x026
rjmp tim01

tim01:
push r0
ldi r23, c5 ; skriv värde till huvudprocessen
pop r0
reti

main:
ldi r30, 0 ; initiera stacken till något fungerande värde
ldi r17, 0x00
out SPH, r17
ldi r17, 0xFF
out SPL, r17
call init
sei
ldi r23, 0xFF

loop:
; här tydker jag värdet cU borde skrivas ut på porten när interruptet
; har exekverats eller ??
; istället tycker jag mig få ut värdet 0xFF. Om jag däremot sparar
; i minnet i interruptrutinen och läser minnet här funkar allt väl.
out PORTC, r23
jmp loop

init: ; den del av det som sätter upp räknaren,
;känns onödigt att lägga ut allt
"pusha alla register jag tänker använda"
"initiera lite IO-portar"

ldi r16, 0xFF ; Make the PORTC output
out DDRC, r16
ldi r16, 0xFF ; Dark all leds
out PORTC, r16

ldi r18, 0b00011101
out TCCR0, r18
ldi r17, 0
out TCNT0, r17
ldi r17, 0xE0
out OCR0, r17
ldi r16, 0x02
out TIMSK, r16
out TIFR, r16

....
"pop alla register jag användt"
ret

;; ligger egentligen först i filen, men lade det nedest här....

.lsym TIMSK, 0x39
.lsym TIFR, 0x38
.lsym OCR0, 0x3C
.lsym TCCR0, 0x33
.lsym TCNT0, 0x32
.lsym PORTC, 0x15
.lsym cU, 0xC8
.lsym SPH, 0x3E
.lsym SPL, 0x3D
Användarvisningsbild
v_jocke
Inlägg: 80
Blev medlem: 27 maj 2003, 17:10:22
Ort: Göteborg
Kontakt:

Inlägg av v_jocke »

En del MCUer sparar undan alla register vid interrupt och läser tillbaka innehållet när interruptrutinen är färdig. Jag vet inget om ATmega16 men det verkar ju nästan som ditt register blir överskrivet på nåt sätt.
Mattias
Inlägg: 37
Blev medlem: 4 juli 2003, 22:45:18

Inlägg av Mattias »

Tack.
Det verkar ju som en trolig förklaring. Tyvärr är databladet lite halvdåligt och behandlar just inte den biten, mer än i fallet att det explicit säger att register r0 inte sparas. Hur det är med övriga förtäljer icke databladet (iaf inte vad jag lyckats hitta än).
/Mattias
henkebenke
Inlägg: 515
Blev medlem: 31 maj 2003, 10:42:37
Ort: Helsingborg

Inlägg av henkebenke »

Det finns inga MCUer som sparar undan registren automatiskt vad jag vet. Detta sker dock i alla högnivåspråk utan att man behöver tänka på det. Du måste själv spara undan alla register som du använder i interruptrutinen. Däremot behöver du inte spara de du inte använder som r0 i tim01-rutinen.

Hur har du initierat TCCR0 rätt? Hur genererar du pulserna utifrån?
Mattias
Inlägg: 37
Blev medlem: 4 juli 2003, 22:45:18

Inlägg av Mattias »

Precis som koden visar, klockar jag räknaren med en neddelad systemklocka. Dvs sätter CS02:CS00 = 101, samt sätter WGM01 = 1 och COM00 = 1 för att OC0 utgången skall toggla samt att CTC skall vara tillslaget.

Precis som jag trodde måste jag själv "pusha" samtliga register som jag använder. (hehe känner lite kraslig i assember, har inte jobbat med det på ett par år).

Vad jag försökte göra var följande (har överenseende med min konstruktion, bara ett experiment). Jag tog ett register som jag dedicerade som databärare mellan interruptrutin och huvudprogram, precis som koden visar ovan. Detta register pushas eller popas aldrigt. Jag är dock väldigt nyfiken på ifall detta skall fungera i en AVR eller icke ?? Utifrån vad jag lyckats läsa om kretsen borde det fungera, så jag kan då inte förklara varför det inte fungerade som jag tänkt mig *skomt*..

Jaja, ett experiment som sagt.
/Mattias
Skriv svar