vezzo Inserito: 1 febbraio 2009 Segnala Inserito: 1 febbraio 2009 (modificato) 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.... 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: 1 febbraio 2009 da vezzo
accacca Inserita: 1 febbraio 2009 Segnala Inserita: 1 febbraio 2009 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.
Livio Orsini Inserita: 1 febbraio 2009 Segnala Inserita: 1 febbraio 2009 Quello che scrive accacca è corretto, però quella che vuoi fare è un porcata da evitarsi nel modo più assoluto!
vezzo Inserita: 2 febbraio 2009 Autore Segnala Inserita: 2 febbraio 2009 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
Livio Orsini Inserita: 2 febbraio 2009 Segnala Inserita: 2 febbraio 2009 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
ludo69 Inserita: 2 febbraio 2009 Segnala Inserita: 2 febbraio 2009 (modificato) 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: 2 febbraio 2009 da ludo69
vezzo Inserita: 2 febbraio 2009 Autore Segnala Inserita: 2 febbraio 2009 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 vi mostrerò il sw completo pronto ad ogni critica costruttiva...
crmsistemi Inserita: 2 febbraio 2009 Segnala Inserita: 2 febbraio 2009 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.
vezzo Inserita: 2 febbraio 2009 Autore Segnala Inserita: 2 febbraio 2009 crmsistemi+2/02/2009, 17:08--> (crmsistemi @ 2/02/2009, 17:08) Ti spiego subito.....cosi:(sintassi incompleta detta anche fatta al volo... )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
Livio Orsini Inserita: 2 febbraio 2009 Segnala Inserita: 2 febbraio 2009 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; ....
vezzo Inserita: 2 febbraio 2009 Autore Segnala Inserita: 2 febbraio 2009 (modificato) 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... /*****************************\ * 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: 2 febbraio 2009 da vezzo
crmsistemi Inserita: 3 febbraio 2009 Segnala Inserita: 3 febbraio 2009 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
vezzo Inserita: 3 febbraio 2009 Autore Segnala Inserita: 3 febbraio 2009 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' ora vado in C conosciendo visual basic mi viene molto piu semplice....senza parlare dell'ottimizzazione e della lunghezza dei SW...
Livio Orsini Inserita: 4 febbraio 2009 Segnala Inserita: 4 febbraio 2009 Che compilatore stai usando?
vezzo Inserita: 4 febbraio 2009 Autore Segnala Inserita: 4 febbraio 2009 Utilizzo MPLAB con PICC della HI-TECH Software....ho risposto alla tua domanda? Grazie
Livio Orsini Inserita: 4 febbraio 2009 Segnala Inserita: 4 febbraio 2009 (modificato) 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: 4 febbraio 2009 da Livio Orsini
vezzo Inserita: 4 febbraio 2009 Autore Segnala Inserita: 4 febbraio 2009 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!...
Livio Orsini Inserita: 4 febbraio 2009 Segnala Inserita: 4 febbraio 2009 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.
Messaggi consigliati
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 accountAccedi
Hai già un account? Accedi qui.
Accedi ora