Newsgroup: it.hobby.elettronica.digitale
Titolo: dubbio interrupt 16F84

Vorrei che al termine della routine di interrupt il programma non 
riprendesse da dove era stato interrotto, bensì da un'altra istruzione del 
programma principale.
E' lecito?

 ha scritto nel messaggio 
news:Kkqaf.15950$hC1....@tornado.fastwebnet.it...

L'istruzione retfie preleva dallo stack l'indirizzo del program counter 
salvato quando il programma salta alla routine di interrupt.
Non credo quindi sia possibile fare quello che chiedi.
Sicuramente però ci possono essere delle soluzioni alternative che ti 
possono consentire di gestire in altro modo il ciclo del tuo programma, 
servono però altre info, 

>E' lecito?
Considerazione generale: tenendo conto che lo stato del program counter
immediatamente precedente l'invocazione della ISR viene di norma
salvato in uno stack (dedicato o in memoria centrale), a seconda del
microprocessore/microcontroller utilizzato *potrebbe* essere possibile
modificare l'indirizzo di ritorno sfruttando apposite istruzioni e/o
metodi di indirizzamento, ma la cosa *non* e' affatto sana:
o) Come fai a sapere quale porzione di codice del tuo sistema e' stata
    interrotta dall'interrupt (scusa il gioco di parole...)?
o) Coma fai ad essere certo che il non completare suddetta
    porzione di codice non porti il sistema in uno stato instabile?
Ergo: lascia perdere!
Con ogni probabilita' se analizzi meglio il problema trovi
una soluzione piu' "pulita" e *soprattutto* piu' sicura.
Ciao
Roberto


Sto mettendo insieme un antifurto per casa: vengono scanditi in sequenza 
tutti i sensori e, in caso di allarme, il PIC dovrà fungere da combinatore 
telefonico occupandosi della generazione dei toni DTMF e della gestione 
delle sirene.
L'interrupt viene generato dall'introduzione di una chiave elettronica che 
deve, al termine della routine di riconoscimento,  cambiare lo stato di 
funzionamento dell'allarme: da acceso a stby. Se introduco la chiave per 
bloccare un allarme partito erroneamente, non posso al termine 
dell'interrupt riprendere il programma da dove era: stava compilando dei 
numeri di telefono! 

 ha scritto nel messaggio 
news:Hwuaf.17193$hC1....@tornado.fastwebnet.it...

Io farei così:
invece di prevedere un funzionamento lineare del programma, che è bloccante, 
dovresti introdurre la gestione di una macchina a stati.
Ovvero prevedere tutti i possibili stati di funzionamento del tuo sistema 
(on,off,allarme,combinazione,...).
Crei un ciclo principale che non fa altro che scansionare continuamente i 
vari stati, eseguendo quello corrispondente a quello attuale, per poi 
uscirne immediatamente con un nuovo stato che sarà eseguito il ciclo 
successivo.
I lunghi ritardi devono diventare piccoli ritardi eseguiti molte volte, 
restituendo il prima possibile il controllo al ciclo principale, che potrà 
così interrompere l'azione corrente per passare alla gestione del nuovo 
stato.
In questo modo il programma è eseguito molto rapidamente e non è bloccante, 
simuli praticamente un multitasking cooperativo.
Anche se lavori a 4MHz il ciclo principale si riduce a pochi us. 

 E' lecito?
E' tutt'altro che elegante ma in linea di principio niente
vieta di fare un jump dove vuoi tu. Lo stack restera'
caricato ma essendo un buffer circolare non comprometti
niente a non fare un regolare return dall'interrupt.
Pero' considera che un programma strutturato in questo
modo e' osceno.

 Anche se lavori a 4MHz il ciclo principale si riduce a pochi us.
Forse non ho capito bene, ma a me sembra cosě:
Se ogni telefonata dura 2 minuti tra composizione numero, composizione del 
codice corrispondente al sensore e controllo audio dell'ambiente, e le 
telefonate sono 6, il ciclo di allarme dura 12 minuti. Se al primo minuto 
inserisco la chiave per annullare un allarme partito erroneamente, non 
vorrei che alla fine della routine si continuasse per altri 11 minuti.
Mi sembra che l'unico modo per uscirne sia quello di ripartire da un punto 
diverso.
Cosa ne pensi? 

 modo e' osceno.
Fino alla call o all'interrupt successivo, poi avviene il caos ;-(
Il pic ha spazio per allocare nello stack 8 indirizzi, se esaurisci lo stack 
perdi il controllo del programma.
Per un corretto funzionamento è obbligatorio utilizzare return dopo ogni 
call e retfie dopo l'interrupt. 

 ha scritto nel messaggio 
news:niwaf.17370$hC1....@tornado.fastwebnet.it...

Penso che forse non mi sono spiegato bene.
Non puoi pensare di rimanere per ben 12 minuti in una parte secondaria del 
programma.
Devi prevedere un ciclo principale (loop infinito), dal quale 
dipendentemente dallo stato attuale, esegui chiamate alle routines di 
gestione opportune.
Non so che linguaggio usi, ma io farei qualcosa del tipo:
while (1) {
  controlla_chiave();
  statosensori=leggi_sensori();
  allarme = controlla_allarme(statosensori);
  if allarme {
    if dial_not_complete componi(cifra++);
   else manage_dial_cycle();
  }
}
dove:
controlla_chiave gestisce la chiave per attivazione/disattivazione
leggi_sensori gestisce gli input con relative temporizzazioni e antirimbalzi
controlla_allarme controlla le temporizzazioni per l'attivazione 
dell'allarme
componi(cifra) esegue la composizione di una singola cifra e poi ritorna
managedialcycle conta il tempo fra le chiamate e gestisce l'eventuale 
riconoscimento linea occupata.
Ognuna di queste funzioni deve durare il minimo tempo possibile, per potere 
ritornare al ciclo principale e controllare e gestire gli altri eventi. 

 telefonate sono 6, il ciclo di allarme dura 12 minuti. 
Se devi fare un antifurto (ma in realta' e' una considerazione valida
in generale!) non e' molto saggio avere dei sottosistemi che mantengono
il controllo per 12 minuti!
Ad ogni ciclo fai una singola telefonata ed il tuo sottosistema di
dialing deve mantenere uno stato interno per specificare se e'
in fase di composizione numeri e a che punto e' arrivato con la lista
delle chiamate.
In questo modo, quando arriva l'interrupt di disattivazione, la ISR si
puo' limitare a notificare l'evento al sottosistema di dialing che
interrompera' (lui!) il ciclo delle telefonate.
Nessun bisogno di "accrocchiare" lo stack!
Ciao
Roberto

 call e retfie dopo l'interrupt.
Sapendo che cosa si sta facendo, non e' obbligatorio eseguire un return
dopo un call o interrupt. Ovvio che si devono avere dei buoni motivi per
usare uno stile di programmazione cosi' anticonformista :-)
Ma di per se' il fatto non causa problemi.

 Ma di per se' il fatto non causa problemi.
Metti di avere 2 call nidificate ed entri in interrupt, fai le tue 
elaborazioni e ne esci con un goto.
Poi come fai a ritornare alle  routine chiamanti originali, visto che lo 
stack non è leggibile e neanche modificabile manualmente ?
Utilizzando l'asm, puoi cercare di verificare anche le call, ma se utilizzi 
un linguaggio ad alto livello (che fa spesso uso di call) non puoi prevedere 
niente.
Imho meglio evitare 

Tutte osservazioni giuste e condivisibili che portano ad uno stile di 
programmazione più snello e ad un aggiramento, più che ad una soluzione, del 
problema.
grazie a tutti
Franco

 Imho meglio evitare
Concordo. Ma a volte puo' essere utile usare un interrupt senza
return per esempio per abbandonare una parte del programma
e saltare a un altra piu' velocemente.

 problema.
A mio avviso "aggirare" il problema e' proprio l'andare a "scardinare"
in modo potenzialmente pericoloso lo stack di sistema: il tuo problema
lo si risolve a livello di design complessivo dell'applicazione.
Di soluzioni te ne sono state abbozzate diverse: il codice te lo
devi scrivere tu... ;)
Ciao!
Roberto

 ripartire da un punto diverso. Cosa ne pensi?
L'interrupt della chiave deve solo settare opportunamente una cella di
memoria con un codice che vuoi tu, (chiamiamolo "stop"). La routine di
chiamata telefonica va a leggersi quella cella periodicamente, se trova il
valore "stop" termina.
Claudio F

 aggiramento, più che ad una soluzione, del problema.
E' che con uno stile di programmazione differente quello non e' affatto un
problema...
Claudio F