 |
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Tor Mar 04, 2008 10:25 pm Naslov sporočila: LPC2378 in prekinitve |
|
|
Živjo
Želel sem narediti timer, ki bi po določenem času izvedel prekinitveno rutino. Delam z KEIL uVision (RealView compiler).
Program ni nič drugega kot LED chaser. Vmes beremo tipke in spreminjamo hitrost utripanja/premikanja diod. Če imam enostavno while zanko v delay funkciji, potem v tem času ne morem brati tipk. Zato sem se odločil, da zadevo rešim s prekinitvijo.
Program sem preizkusil na Borisovi razvojni plošči in LPC2378. Program pride do main, saj se LED prižgejo. Prižgejo se pa samo tiste, ki so nastavljene že na začetku programa (definicija spremenljivk). V prekinitveni rutini, bi se morale aktivne LED spremeniti, pa se ne. Torej program do te rutine sploh ne pride.
Poizkusil tudi sem tudi z debugerjem. Na zacetku vse lepo in prav - pridemo do main funkcije, klicemo ostale funkcije, ko pa pride do prekinitve se mi program "zacikla" v LPC2300.s datoteki. Prebral sem si podobne teme na forumu, vendar nisem našel rešitve.
Ko pride do prekinitve, mi program skoči na vrstico
Koda: |
LDR PC, [PC, #-0x0FF0] |
Od tam gre na začetek vektorjev, torej na
Koda: |
Vectors LDR PC, Reset_Addr |
In začne se ponoven startup (ura itd.). Tako da do prekinitvene rutine sploh ne pride! Mislim si, da bi moral popraviti LPC2300.s datoteko, pa ne vem kako. Ob prekinitvi gre na pravo lokacijo v .s datoteki, vendar pa tam ne dobi pravega naslova! Če namesto naslova dam:
pa se ustavi v zanki
Koda: |
IRQ_Handler B IRQ_Handler |
Spodaj so pripeti deli kode LPC2300.s
Koda: |
; Exception Vectors
; Mapped to Address 0.
; Absolute addressing mode must be used.
; Dummy Handlers are implemented as infinite loops which can be modified.
Vectors LDR PC, Reset_Addr
LDR PC, Undef_Addr
LDR PC, SWI_Addr
LDR PC, PAbt_Addr
LDR PC, DAbt_Addr
NOP ; Reserved Vector
; LDR PC, IRQ_Addr
LDR PC, [PC, #-0x0FF0] ; Vector from VicVectAddr
LDR PC, FIQ_Addr
Reset_Addr DCD Reset_Handler
Undef_Addr DCD Undef_Handler
SWI_Addr DCD SWI_Handler
PAbt_Addr DCD PAbt_Handler
DAbt_Addr DCD DAbt_Handler
DCD 0 ; Reserved Address
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
IRQ_Handler B IRQ_Handler
FIQ_Handler B FIQ_Handler
; Reset Handler
EXPORT Reset_Handler
Reset_Handler |
Moj program:
Koda: |
#include <LPC23xx.H>
void Timer0_ISR(void) __irq; // Dolocimo naslov prekinitvene rutine
int main(void)
{
/* Inicializacija za prekinitve */
VICIntEnable |= (1<<4);
VICIntSelect = 0;
VICVectAddr0 = (unsigned)Timer0_ISR; // naslov kamor gremo ko pride do prekinitve
VICVectPriority0 = 0;
/* Inicializacija casovnika TIMER0 */
T0TCR = 0;
T0PR = 12000; // stejemo milisekunde; preipheral clock = 12MHz
T0TC = 0;
T0MCR = 0x00000003; // Vklopimo Interrupt za TIMER0; pri prekinitvi resetiramo TC (T0TC=0)
T0MR0 = hitrost; // Do prekinitve pride, ko je TC enak MR0, torej ko mine dolocen cas (hitrost)
T0TCR = 1;
while(1)
{
FIO2SET = LED; // vrednost LED postavimo na izhodone pine - prizgemo diode
hitrost = tipke(hitrost); // klicemo funkcijo tipke in spreminjamo hitrost
inc = hitrost/2; // na vsak pritisk tipke se hitrost za polovico poveca ali zmanjsa
}
}
/* Prekinitven rutina zaradi TIMER0 */
void Timer0_ISR(void) __irq
{
T0TCR = 0; // ustavimo timer
T0IR |= (1<<0); // resetiramo match 0 prekinitev
/* Izvedemo operacije za premikanje/utripanje LED diod */
/* Preden zapustimo rutino */
T0MR0 = hitrost; // "hitrost" lahko spreminjamo in morebiti spremenjeno vrednost zapisemo v match register
T0TCR = 1; // vklopimo timer
VICVectAddr = 0x00000000; //koncamo prekinitev
} |
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
alessio Član

Pridružen-a: Pon 04 Dec 2006 8:39 Prispevkov: 363 Aktiv.: 1.60 Kraj: Ljubljana
|
Objavljeno: Tor Mar 04, 2008 11:02 pm Naslov sporočila: |
|
|
Najprej vrstico
Koda: |
LDR PC, [PC, #-0x0FF0] ; Vector from VicVectAddr |
zamenjaj z
Koda: |
LDR PC, [PC, #-0x0120] ; Vector from VicVectAddr |
LPC23xx ima namreč drugačen VIC kot LPC21xx in LPC22xx.
Aleš
|
|
Nazaj na vrh |
|
 |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Tor Mar 04, 2008 11:23 pm Naslov sporočila: |
|
|
Hvala za hiter odgovor. Sem pozabil napisat - v originalu je bil 0x0120 Ko pa sem začel eksperimentirat, sem med drugim spremenil tudi ta naslov na 0x0FF0. Zadeva še vedno dela enako oz. ne dela....
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Čet Mar 06, 2008 12:14 am Naslov sporočila: |
|
|
No, nekaj se premika....
Če v zgornjo vrstico namesto 0x0FF0 ali 0x0120 zapišem 0x0F00, potem prekinitev nekako dela. Zadeva ni stabilna in se, če uporabljam tipke, zopet nekje zacikla. Pri vsem skupaj pa je še najbolj čudno to, da moram uporabit nek določen VICVectAddr. Npr. VICVectAddr0 ne dela, medtem ko VICVectAddr8 "dela".
Ima kdo kako idejo?
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
RokO Član

Pridružen-a: Čet 23 Nov 2006 11:14 Prispevkov: 120 Aktiv.: 0.53 Kraj: Kranj
|
Objavljeno: Čet Mar 06, 2008 11:34 am Naslov sporočila: |
|
|
Na ZS ti bom poslal kratek uVision program, ki sem ga na hitro spisal. V njem ti preizkušeno deluje Timer0 prekinitev in sicer na vsake 3 sekunde. Vse skupaj teče na LPC2368 in plati MCB2300.
Upam, da ti bo kaj pomagalo...
|
|
Nazaj na vrh |
|
 |
smartgsm Član

Pridružen-a: Sob 10 Apr 2004 11:54 Prispevkov: 364 Aktiv.: 1.53
|
Objavljeno: Čet Mar 06, 2008 5:26 pm Naslov sporočila: |
|
|
RokO je napisal/a: |
Na ZS ti bom poslal kratek uVision program, ki sem ga na hitro spisal. V njem ti preizkušeno deluje Timer0 prekinitev in sicer na vsake 3 sekunde. Vse skupaj teče na LPC2368 in plati MCB2300.
Upam, da ti bo kaj pomagalo... |
Lahko prilozeš primer?
Jaz imam podoben problem.
S to razliko da jaz dinamično prilagajam hitrost proženja IRQ od cca 100 hz do 50 KHZ. Pri določeni frekvenci enostavno IRQ procedura pade ven in se ne proži. Main procedura pa deluje normalno.
lp
Grega
|
|
Nazaj na vrh |
|
 |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Čet Mar 06, 2008 5:45 pm Naslov sporočila: |
|
|
Hvala za pomoč. Mislim da mi je stvar zdaj bolj jasna Gre pa samo za pomankljivo znanje VIC-a (Vectored Interrupt Controller). Nekako sem imel pomešane pojme, kako zadeva deluje. Zdaj mislim, da mi je bolj jasno...
Mislil sem, da za prekinititev samo določiš source (VICIntSelect - posamezen bit vklopi/izklopi interrupt za timerje, uart itd.). Temu pa nato sledi še zapis naslova ISR v VICVectAddr0 do VICVectAddr32. Nekako sem si predstavljal da naslov ISR pač vpisuješ po vrstnem redu v VICVectAddr - torej za eno prekinitev zapišeš v VICVectAddr0, za drugo v VICVectAddr1 itd.
No, stvari ni tako enostavna, hehe Stvar je še bolj enostavna...
Hočeš prekinitev zaradi TIMER0? Pogledaš kateri bit v VICVectSelect moraš postaviti na 1 (v mojem primeru je to bit 4). Nato pa naslov prekinitvene rutine vpišeš pod isto zaporedno mesto v VICVectAddr, torej v VICVectAddr4
Kar se tiče pa startup datoteke - 0x0120 je prava vrednost!
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Čet Mar 06, 2008 5:49 pm Naslov sporočila: |
|
|
Zdaj imam pa drugačen problem....
Kot sem rekel gre za LED chaser in programu lahko preko tipk spreminjamo hitrost "premikanja" LEDic.
Prekinitev je narejena tako, da mi šteje milisekunde in v prekinitveni rutini se spreminja samo nek "števec".
V glavnem programu opazujemo ta števec in ko doseže določeno vrednost "čas", se LEDice spremenijo oz. premaknejo. Prav tako se "števec"zopet postavi na 0. Vmes pa tudi opazujemo tipke, s katerimi spreminjamo vrednost "čas".
Če program prevedem in preizkusim na krmilniku mi zadeva dela! Problem je, ko začnem pritiskati tipke, saj mi LEDice zmrznejo!! To je popolnoma naključno - enkrat lahko na tipke pritisnem 1x pa zmrzne, drugič pa 100x...
Ima mogoče za to kdo kako idejo?
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Čet Mar 06, 2008 8:39 pm Naslov sporočila: |
|
|
Sem našel napako tudi za drugi problem - napaka v if stavku. Primerjal sem števec in čas in sicer "števec == čas".
Ko sem čas povečeval ni bilo problema. Če pa sem čas zmanjševal, je bil lahko števec v tistem trenutku že večji od vrednosti čas. Zato se je zadeva ustavila. Ni zmrznila, ampak je štela milisekunde naprej. In ker gre za 32bitni števec, bi moral čakati 2^32 milisekund, da bi števec prišel do konca in zopet začel z nule....
Popravek na "števec >= čas" je popravil program.
Se zahvaljujem vsem za pomoč in opravičujem za temo, ki sem jo očitno odprl zaradi malomarnosti...
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
RokO Član

Pridružen-a: Čet 23 Nov 2006 11:14 Prispevkov: 120 Aktiv.: 0.53 Kraj: Kranj
|
|
Nazaj na vrh |
|
 |
SimonS Član



Pridružen-a: Čet 01 Jul 2004 11:18 Prispevkov: 4770 Aktiv.: 20.09 Kraj: Kobarid
|
Objavljeno: Čet Mar 20, 2008 12:39 am Naslov sporočila: |
|
|
Pozdrav
Nastavil sem si timer, ki mi vsake 3 minute generira prekinitev.
Hec pa je v tem. Prvic mi res na 3. minute generira. Drugic in vsakik naslednjic pa mi gre v prekinitev na 4. minute. To mi nikakor ni jasno. Primir moje kode
Koda: |
T0PR = 900000000; // 1 minuta
T0MR0 = 3; // Generiraj na 3. minute
T0MCR = 0x00000003; // On match, raise interrupt and reset T0TC
T0TCR = 0x00000002; // Reset counter and prescaler
T0CTCR &= 0xfffffffc; // Timer mode
T0TCR = 0x00000001; // Enable timer
|
prekinitvena rutina pa izgleda tako:
Koda: |
if(VICIRQStatus&0x00000010) //TIMER 0
{
IOSET0 = led_n;
T0IR = 0x00000001; //resetiramo prekinitev timer 0
}
|
_________________ Lep dan
Simon |
|
Nazaj na vrh |
|
 |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Čet Mar 20, 2008 1:21 am Naslov sporočila: |
|
|
Kako imaš inicializirano prekinitev (registri VICIntEnable, VICIntSelect, VICVectAddr0 itd.)?
Tvoj zapis prekinitvene rutine mi ni znan. "if" stavka za prekinitveno rutino še nisem videl. Je pa res da se s programiranjem ne ukvarjam tako dolgo
Bi poizkusil z (meni) bolj znano obliko:
Koda: |
void Timer0_ISR(void) __irq; // Dolocimo naslov prekinitvene rutine
/* Prekinitven rutina zaradi TIMER0 */
void Timer0_ISR(void) __irq
{
/* Program, ki se naj izvede ob prekinitvi */
VICVectAddr = 0x00000000; //koncamo prekinitev
}
int main(void)
{ /* Inicializacija za prekinitve */
VICIntEnable |= (1<<4);
VICIntSelect = 0;
VICVectAddr0 = (unsigned)Timer0_ISR; // naslov kamor gremo ko pride do prekinitve
VICVectPriority0 = 0;
while(1)
{
/* program */
}
} |
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
RokO Član

Pridružen-a: Čet 23 Nov 2006 11:14 Prispevkov: 120 Aktiv.: 0.53 Kraj: Kranj
|
Objavljeno: Čet Mar 20, 2008 1:31 am Naslov sporočila: |
|
|
Ne primi me za besedo, vendar mi nekje zadaj odzvanja, da mora biti register MR nastevljen na način (n-1).
Tako, da probaj z
T0MR0 = 2; // Generiraj na 3. minute
V tem premeru bi moralo delati, ker se una "ničla" tudi upošteva...takrat gre pač oni števec na nič ali kako je že...
|
|
Nazaj na vrh |
|
 |
SimonS Član



Pridružen-a: Čet 01 Jul 2004 11:18 Prispevkov: 4770 Aktiv.: 20.09 Kraj: Kobarid
|
Objavljeno: Čet Mar 20, 2008 12:17 pm Naslov sporočila: |
|
|
Olaf
Prekinitvena rutina deluje OK. Pac ne uporabljam FIQ.
RokO
Ja to ze razumem. Samo ce napravim tako, potem mi bo prvo prekinitev se vedno napravilo krajso kot ostale, kar pa ni prav....
_________________ Lep dan
Simon |
|
Nazaj na vrh |
|
 |
Olaf Član

Pridružen-a: Tor 14 Nov 2006 20:09 Prispevkov: 127 Aktiv.: 0.56 Kraj: Ljubljana
|
Objavljeno: Čet Mar 20, 2008 1:51 pm Naslov sporočila: |
|
|
Sem se malo igral - napaka je v resetiranju števca TC. Čeprav je v MCR zapisano naj ob prekinitvi resetira tudi TC (T0MCR = 0x00000003), se to očitno zgodi šele ob naslednjem povečanju TC-ja. Zakaj je tako pa ne vem...
Če sem v prekinitveni rutini "na roke" resetiral counter (torej T0TC = 0), je zadeva delala tako kot je treba prvi in vsak naslednji krog!
Pri tem je match register je štel od 1 naprej. Torej če imaš T0MR0 = 3, je štel 1-2-3 in ne 0-1-2-3. Vsaj tako je se je izkazalo na praktičnem primeru.
_________________ To mi deli! |
|
Nazaj na vrh |
|
 |
|
|
Ne, ne moreš dodajati novih tem v tem forumu Ne, ne moreš odgovarjati na teme v tem forumu Ne, ne moreš urejati svojih prispevkov v tem forumu Ne, ne moreš brisati svojih prispevkov v tem forumu Ne ne moreš glasovati v anketi v tem forumu Ne, ne moreš pripeti datotek v tem forumu Ne, ne moreš povleči datotek v tem forumu
|
Uptime: 6 dni
Powered by phpBB © 2001, 2005 phpBB Group
|