Vai al contenuto
PLC Forum


Interrupt


vezzo

Messaggi consigliati

Ciao a tutti...ho un problema mettiamo il caso che io volessi con un PIC 16F84 attivare un ciclo che sta in una routine apposita....che però alla pressione dal tasto di "STOP" si fermi....ho programmato il pin RB0 come interrupt, il problema è che dal main() ho il salto alla ipotetica routine() è il compilatore si incaz....perchè io dopo l'interrupt non voglio che lui ritorni ad eseguire il punto in cui era....non è che devo agire sullo stack o qualche cosa del genere??? non sò dove picchiare la testa.... wallbash.gif

ex (con sintassi non corretta)

main()

{

if bla bla bla

{

ciclo();

}

}

void interrupt prv_int(void)

{

if(INTF)

{

RB3 = 0;

INTF = 0;

}

}

void ciclo()

{

RB3 = 1;

}

Spero di essermi spiegato....

Grazie grazie grazie

Modificato: da vezzo
Link al commento
Condividi su altri siti


sì lo stack è il punto giusto il micro prima di entrare nell'interrupt salva autmoaticamente nello stack il punto di ritorno (registro program counter)

Nulla ti vieta di modificare il registro per "ingannare" il micro e farlo uscire dall'interrupt in un altro punto. Penso sia più facile realizzare il tutto in assembler anche perchè con il C non sai cosa ci mette il compilatore di suo e rischi di avere un sacco di problemi.

Link al commento
Condividi su altri siti

Quello che scrive accacca è corretto, però quella che vuoi fare è un porcata da evitarsi nel modo più assoluto!

Link al commento
Condividi su altri siti

Be effettivamente è una porcata....però come faccio allora ad interromperè una routine che è in esecuzione con un interrupt...???? non farò mica premere il tasto di reset del pic....grazie grazie

Link al commento
Condividi su altri siti

Se hai scritto in "C" la funzione di servizio dell'interrupt, la funzione termina automaticamente, a meno che non sia entrata in un loop infinito, ma questo è un errore di programamzione.

Se hai scritto in asm l'ultima istruzione è un RETURN.

Se ci devono essere delle condozioni per terminare la funzione/routin in asm fai un salto alla fine, in "C" ci sono dei percorsi condizionati per pterminare/uscire.

Se la routine deve abilitare l'esecuzione di particolari funzioni, si alza un flag, si esce, poi sarà un'altra parte di programam che eseguirà la funzione abilitata

Link al commento
Condividi su altri siti

Mi ricordo che succedeva anche a me il dover cercare di usare delle "porcate" sui SW, ma spesso ripensando la strategia dell'algoritmo e rimodulando le funzioni main program/interrupt rutine spesso riuscivo a venirne a capo in maniera più elegante....

Interrompere senza ritorno (nel senso che poi prosegui altrove) un main program non è molto cauto, si lasciano appese variabili/lavori in maniera indeterminata.

Ricordo che anche io, come ti hanno già indicato, quando non ne potei fare a meno usai questa tattica: nella routin di i nterrupt settavo/resettavo dei bit in una locazione che chiamavo "Flags" in cui memorizzavo lo stato dei controlli effettuati sotto interrupt in modo che in punti chiave del main program potevo accedere a questi Flags e decidere come cambiare il flusso del programma in base agli "aggiornamenti dal mondo esterno" che attraverso i Flags mi passava la routin di interrupt.

Non sarà il massimo, ma almeno il flusso di scorrimento del programma è determinato.

Modificato: da ludo69
Link al commento
Condividi su altri siti

Questa sera mi ci metto e faccio ancora qualche prova....comunque il tutto è in C è loop infiniti o "ricorsioni" non ce ne sono il sw va liscio liscio....l'interrupt crea si un intteruzione della rutina, ma una volta eseguite le istruzioni vi ritorna....questa sera mi cimento poi vi faccio sapere....per ora grazie worthy.gif vi mostrerò il sw completo pronto ad ogni critica costruttiva... sad.gif

Link al commento
Condividi su altri siti

Sicuramente avrai le tue buone ragioni, ma perchè un interrupt ? se vuoi uscire da un ciclo alla pressione di un tasto è sufficiente che ad ogni inizio o fine ciclo testi se il pulsante è chiuso o meno.

In pratica un semplice ciclo di while condizionato dalla pressione del tasto.

Unica cosa importante che il ciclo sia molto breve altrimenti la pressione del tasto potrebbe non essere vista, ma anche se fosse potresti ripetere il test durante il ciclo e uscire dal while.

Link al commento
Condividi su altri siti

crmsistemi+2/02/2009, 17:08--> (crmsistemi @ 2/02/2009, 17:08)

Ti spiego subito.....cosi:

(sintassi incompleta detta anche fatta al volo... smile.gif )

mani()

{

ciao();

}

void ciao()

{

char x;

mia_out=1;

for(x=0;x<100;x++) DelayMs(250);

mia_out=0;

}

se premi un tasto nel bel mezzo del for......non sarà visto da nessuno mentre con l'interupt su rb0 (pic 16f84) metto a 0 la mia uscita il problema è che poi riprenderà da dove l'ho interrotto.... spero di essermi spiegato

Link al commento
Condividi su altri siti

Puoi benissimo usare l'interrupt sulla pressione del tasto. Nella routine di interrupt alzi un flag. Al ritorno il flag alto ti farà uscire dal loop. Come? Nell'esempio basta fare:

....
    if flag = true x = 100;
....

Link al commento
Condividi su altri siti

Ok ci sono...cosi il for è al termine è ok però mi troverei a riavere lo stesso problema..che posso ovviare nel main mettendo prima di ogni richiamo di routine una condizione che dipenda dal flag e poi dal resto di codice che devo ancora fare.....ecco il codice....non è finito... biggrin.gif

/*****************************\
*       by VeZzO    *
*        *
*     Lavaggio Frigo       *
*        *
*  	data    *
\*****************************/
#include<pic1684.h>
#include<delay.c>  //routine per i ritardi
//output
#define ev_fredda  	RB2//valvola acqua fredda
#define ev_calda  	RB3//valvola acqua calda 
#define ev_calda_sapone RB4//valvola acqua calda con sapone
#define ev_scarico  	RB5//valvola scarico
#define m_pompa  	RB6//motore pompa
#define m_mixer  	RB7//motore mixer
#define esc_frigo  RA3//esclusione frigorifero
//input
#define p_start  	RB1//pulsante start
#define p_stop  	RB0//pulsante stop
#define p_lavaggio  RA0//selettore lavaggio
#define p_frigo  	RA1//selettore frigo
#define p_sing_lavaggio RA2//pulsante singolo lavaggio
//----------------------------------------------------
//tempi acqua fredda
#define caricoA  1  //tenpo catico acqua fredda
#define pompaA  1  //tempo pompa acqua fredda
#define mixerA  1  //tempo mixer acqua fredda
#define scaricoA	1  //tempo scarico acqua fredda
//tempi acqua calda
#define caricoB  1  //tenpo catico acqua calda
#define pompaB  1  //tempo pompa acqua calda
#define mixerB  1  //tempo mixer acqua calda
#define scaricoB	1  //tempo scarico acqua calda
//tempi acqua calda saponata
#define caricoC  1  //tenpo catico acqua calda saponata
#define pompaC  1  //tempo pompa acqua calda saponata
#define mixerC  1  //tempo mixer acqua calda saponata
#define scaricoC	1  //tempo scarico acqua calda saponata
//tempi acqua fredda risciacquo
#define caricoD  1  //tenpo catico acqua fredda risciacquo
#define pompaD  1  //tempo pompa acqua fredda risciacquo
#define mixerD  1  //tempo mixer acqua fredda risciacquo
#define scaricoD	1  //tempo scarico acqua fredda risciacquo
//-------------------------------------------------------------------
//parametri
#define msec_base	1  //base tempi routine DelayMs(???)
#define mul_msec	2  //moltiplicatore msec
//sobrutine
void ciclo_fredda();
void ciclo_calda();
void ciclo_calda_sapone();
void ciclo_fredda_risciacquo();
void ciclo_fredda_rip_risciacquo(char ripeti);
//void interrupt prv_int();

main()
{
TRISB=0b00000011;  //settaggio porta b
TRISA=0b11111111;  //settaggio porta a
GIE=1;INTE=1;  	//settaggio interupt
if(p_lavaggio==1 & p_frigo==0 & p_start==1 & p_stop==0)
	{
	esc_frigo = 1;  //fermo il frigorifero
	ciclo_fredda();
	ciclo_calda();
	ciclo_calda_sapone();
	ciclo_fredda_rip_risciacquo(2);
	}
}
void 
interrupt prv_int(void)
{	
	if(INTF)
	{
	ev_fredda=0;ev_calda=0;ev_calda_sapone=0;m_pompa=0;m_mixer=0;
	INTF=0;  //Riabilita linterrupt flag porta RB0,altrimenti non
	//main();
	}  	
}    





//fredda
void
ciclo_fredda()
{
char x;
ev_fredda = 1;
for(x=0;x<caricoA*mul_msec;x++) DelayMs(msec_base);
ev_fredda = 0;
m_pompa = 1;m_mixer = 1;
for(x=0;x<pompaA*mul_msec;x++) DelayMs(msec_base);
m_pompa = 0;m_mixer = 0;
ev_scarico = 1;
for(x=0;x<scaricoA*mul_msec;x++) DelayMs(msec_base);
ev_scarico = 0;
}
//calda
void
ciclo_calda()
{
char x;
ev_calda = 1;
for(x=0;x<caricoB*mul_msec;x++) DelayMs(msec_base);
ev_calda = 0;
m_pompa = 1;m_mixer = 1;
for(x=0;x<pompaB*mul_msec;x++) DelayMs(msec_base);
m_pompa = 0;m_mixer = 0;
ev_scarico = 1;
for(x=0;x<scaricoB*mul_msec;x++) DelayMs(msec_base);
ev_scarico = 0;
}
//calda con sapone
void
ciclo_calda_sapone()
{
char x;
ev_calda_sapone = 1;
for(x=0;x<caricoC*mul_msec;x++) DelayMs(msec_base);
ev_calda_sapone = 0;
m_pompa = 1;m_mixer = 1;
for(x=0;x<pompaC*mul_msec;x++) DelayMs(msec_base);
m_pompa = 0;m_mixer = 0;
ev_scarico = 1;
for(x=0;x<scaricoC*mul_msec;x++) DelayMs(msec_base);
ev_scarico = 0;
}
//fredda risciacquo
void
ciclo_fredda_risciacquo()
{
	char x;
	ev_fredda = 1;
	for(x=0;x<caricoD*mul_msec;x++) DelayMs(msec_base);
	ev_fredda = 0;
	m_pompa = 1; m_mixer = 1;
	for(x=0;x<pompaD*mul_msec;x++) DelayMs(msec_base);
	m_pompa = 0; m_mixer = 0;
	ev_scarico = 1;
	for(x=0;x<scaricoD*mul_msec;x++) DelayMs(msec_base);
	ev_scarico = 0;
}
//ripetizione risciacquo
void
ciclo_fredda_rip_risciacquo(char ripeti)
{
char y;
for(y=0;y<ripeti;y++)
ciclo_fredda_risciacquo();
}

Modificato: da vezzo
Link al commento
Condividi su altri siti

Se ho capito bene il tuo problema è quello di interrompere i cicli di attesa alla pressione di un tasto.

Allora fai una unica sub di attesa a cui passi come parametro il tempo (invece di scrivere numerose volte un ciclo di for) ed usa il metodo del flag indicato da Orsini in questa sub oppure includi nel ciclo di for il test del pulsante senza usare interrupt.

lo scrivi una volta sola e vale per tuttti i punti del programma

Link al commento
Condividi su altri siti

OK perfetto hai ragione cosi è ancora più ottimizzato!!...l'ho appena fatto e va bene...grazie...problema intterupt risolto...però ho una domandina....

quante altre funzioni ci sono del tipo interrupt prv_int(void) come si definiscono? private? l'interrupt l'ho trovato su internet altrimenti....ero rimasto ad org h'0004' tongue.gif ora vado in C conosciendo visual basic mi viene molto piu semplice....senza parlare dell'ottimizzazione e della lunghezza dei SW...

Link al commento
Condividi su altri siti

Con quel compilatore (io però uso CCS) le built in fuinctions dovrebbero essere già dichiarate nel file *.h che devi includere all'inizio. Nel manuale del compilatore, o nell'help in linea, dovresti avere l'elenco completo delle built in functions, con spiegazione ed eventuali esempi.

Modificato: da Livio Orsini
Link al commento
Condividi su altri siti

Livio Orsini+4/02/2009, 14:33--> (Livio Orsini @ 4/02/2009, 14:33)

OK grazie...c'é un motivo particolare per cui usi ccs? è migliore....è free?... quello che utilizzo io può andare?

Provo a vedere nell'. quindi sono built functions grazie!...

Link al commento
Condividi su altri siti

No, è qualificato da Microchip come lo è Hi-Tech. Non è gratis, anzi forse costa un poco di più Hi-Tech. Solo che ho inizato con quello, mi trovo bene e non vedo ragione per cambiare.

Comunque si assomigliano abbastanza, come si assomiglia anche MicroC, che dicono sia abbastanza valido.

Quello che "fa buono" un compilatore è il grado ottimizzazione, cioè l'efficienza del codice dopo la compilazione.

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...