Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  6 1411
Noken som har litt erfaring med programmering av mikrokontrollere i assambler?

Har en AVR ATS901200 som eg skal bruke med en timerfunksjon. Denne skal telle i tilnærma 10sec før den hopper ein plass.

Eg får den til å fylle opp ett register med å bruke klokkepuls / 1024. Eg regner med eg må få den til å telle opp fleire register om eg skal kunne bruke den til å telle oppmot 10sec, men finner ingen god måte å gjøre det på.

Noken som har litt tips?
Sist endret av Kripos; 15. mars 2006 kl. 12:26.
Hva med å bruke en ekstern timer/teller?
Kripos's Avatar
Trådstarter
Mja, det kunne jo sjølvsagt fungert. Men problemet er jo at det skal kunne gjørest uten alt for mykje bry internet, og eg gjerne vil ha eit par peikepinner på korleis det kan gjørest
Generelt sett:
Finn instruksjonen som ikke gjør noe, skal jeg tippe hva den heter så må det bli "do nothing" eller noe sånt.. Det er en instruksjon som tar X antall klokkepulser, men som ikke gjør noe annet enn det. Kjør den i en loop og regn ut hvor mange klokkepulser hele loopen tar. Deretter finner du ut hvor mange looper du må kjøre for at det skal ta 10 sek å fullføre.

Kode

x  = 0
Goto Vent10Sekunder

start:
x = 0
LagEnLyd
Goto Vent10Sekunder

Vent10Sekunder:
x = x + 1
DoNothing
DoNothing
DoNothing
DoNothing
DoNothing
DoNothing
If X = 250 then Goto Vent10Sekunder else Goto start
La oss si at en loop med Vent10Sekunder tar 40 klokkepulser, og mikrokontrolleren din er på 1 KHz.
Da greier den 25 looper per sekund (1000 / 40 = 25)
og da må vi kjøre loopen 250 ganger for at det skal ta 10 sekunder (10 * 25 = 250). Vi må med andre ord kjøre loopen til X = 250

Edit: Var NOP, som rahim nevnte, jeg tenkte på. DoNothing = NOP
Sist endret av sputch; 19. mars 2006 kl. 16:17.
Sjekk http://paul.graysonfamily.org/thoughts/avrlinux/
Ikke samme kontroller, men NOP er ganske universell. Eksemplet hans er i C, men ser ut til å bruke inline assembler for å lage en delay-prosedyre som brukes når han skrur en LED på og av.
Du kan jo lage en tidssløyfe:


Kode

wait_10sec:

ldi i ,1000
loopi:
ldi j,1000
loopj:
ldi k,1320
look:
dec k
brne loopk
dec j
brne loopj
dec i
brne loopi
ret
For å få en AVR mikrokontrollen (uansett type) til å gjøre noe hvert 10sec er det 2 måter å gjøre dette på.

1. Du lager en tidsløkke vha nop's og regner ut hvor mange nop's du trenger for at løkken skal ta 10 sec. Dette er den mest tungvindte metoden og ikke noe sørlig å bruke da den okkuperer unødig prosesseringskraft.

2. Du benytter deg av timer-interrupts. En AVR mikrokontroller har fra 2 til 4 timer-interupts du kan benytte deg av. I manualen til din type kontroller finner du ut hvilken program.minne adresse som aksesseres når du får en timer interrupt, og på denne adressen setter du bare en rjmp til en metode du vil at skal utføres. NB: Husk stakken og returner med reti-kommandoen.

For å enable timer-interrupten på din kontroller, så ser du på interrupt seksjonen i manualen.

Et eksempel på bruk av timer interrupts på en AVR mega128 mikrokontroller:

Kode

.include "m128def.inc"
	.def temp  = r16

; ====== variable i SRAM ============== 
	.dseg
	.org 0x100
teller: .byte 1

; ====== Interrupt vektorer ===========
	.cseg
	.org 0
	rjmp init			
	.org 0x20
	rjmp timer_0_overflow

; ====== Initialisering ==============
	.org 0x46
init:
; initialiser stakkpeker
	ldi temp, low(ramend) ;ramend definert i inc fil
	out SPL, temp
	ldi temp, high(ramend)
	out SPH, temp

; initialiser porter
	call init_io

; initialiser timer 0
	; sett prescaler til 1/1024 og start timeren
	ldi r16, 0x07
	out TCCR0, r16

; enable interrupt
	ldi r16, (1<<TOIE0)
	out TIMSK, r16
	sei

; initialiser teller
	clr temp
	sts teller, temp

; ======== Hovedprogram =============
loop:
; Skriv teller på lamper
	lds r0, teller
	call skriv_lamper
	rjmp loop

; ======== Interrupt rutine =============
timer_0_overflow:
	push r16
	in r16, sreg
	push r16
	
	; oppdater teller
	lds r16, teller
	inc r16
	sts teller, r16
	
	pop r16
	out sreg, r16
	pop r16
	reti