1 di 9 05/03/2012 18:06 There are no pending text suggestions from your readers Gestire l'interrupt in MikroBasic Didasknol - Elettronica Quando è come utilizzare l'interrupt Contents Che cos'è l'interrupt Registri Come gestire l'interrupt in MiKrobasic Esempio Impostare TMR0 e il prescaler Realizzazione di un orologio tramite TMR0 Che cos'è l'interrupt L'interrupt è una modalità operativa gestibile da un microprocessore o da un microcontrollore che permette l'interruzione dell'esecuzione di un normale flusso di istruzioni per eseguire un altra sequenza di istruzioni (con priorità più alta), al termine del interrupt il programma riprende il flusso normale. fig.01 funzionamento dell'interrupt [1] Il Mikrobasic permette la gestione di tutti gli interrupt generati dal CPU scelta. Per vedere quali sono gli interrupt possibili per ogni singolo PIC microchip possiamo fare riferimento al datasheet, in particolare noi ci occuperemo del 16F887. Registri Per la gestione dell'interrupt è necessario settare i due registri INTCON e OPTION vediamo in dettaglio questi due registri. fig.02 Registro INTCON [2] Il registro INTCON contiene i bit di abilitazione e segnalazione dei vari interrupt gestibili dal PIC. GIE - Global Interrupt Enable bit - questo bit abilita tutti gli interrupt selezionati dai bit 3-6. 1 - abilita tutti gli interrupt selezionati interrupts. 0 - disabilita tutti gli interrupts. PEIE - Peripheral Interrupt Enable bit - funzione come GIE, ma controlla solo gli interrupt originati dalle periferiche (che vanno attivate tramite il registro PIE1). questo significa che non ha alcuna azione su TMR0 ne sul cambiamento di stato del PORTB ne su RB0/INT 1 - abilita tutti gli interrupt selezionati interrupts.
2 di 9 05/03/2012 18:06 0 - disabilita tutti gli interrupts. T0IE - TMR0 Overflow Interrupt Enable bit abilita l'interrupt sull'overflow di TMR0. 1 - Abilta l'interrupt su TMR0. 0 - Disbilta l'interrupt su TMR0. INTE - RB0/INT External Interrupt Enable bit attiva l'interrupt sul cambiamento di stato del PIN RB0/INT (interrupt esterno) 1 - Abilita l'interrupt esterno su RB0/INT. 0 - Disbilita l'interrupt esterno su RB0/INT. RBIE - RB Port Change Interrupt Enable bit. attiva l'interrupt sul cambiamento di stato del portb, sia da alto a basso che viceversa 1 - Abilita l'interrupt esterno su PORTB. 0 - disabilita l'interrupt esterno PORTB. T0IF - TMR0 Overflow Interrupt Flag bit - registro l'overflow su TMRO. 1 - Il registro TMR0 è andato in overflow register has overflowed (il bit deve essere azzerato via software). 0 - Il registro TMR0 non è andato in overflow. INTF - RB0/INT External Interrupt Flag bit - segnala il cambiamento di stato su RB0/INT pin. 1 - l'interrupt esterno su INT è avvenuto (il bit deve essere azzerato via software). 0 - l'interrupt esterno su INT non è avvenuto RBIF - RB Port Change Interrupt Flag bit - registra il cambiamento di stato sul portb. 1 -almeno uno dei PIN del PORTB ha cambiato stato (il bit deve essere azzerato via software). 0 - nessuno dei PIN del PORTB ha cambiato stato. fig.03 Registro Option [2] RBPU - PORTB Pull-up enable bit 1 - PORTB le resistenze di pull-up sono disabilitate; 0 - PORTB i pin possono essere collegate alle resistenze di pull-up. INTEDG - Interrupt Edge Select bit 1 - Interrupt sul fronte di salita del PIN INT(0-1); 0 - Interrupt sul fronte di discesa del PIN INT(1-0). T0CS - TMR0 Clock Select bit 1 - gli impulsi di conteggio del TMR0 sono le transizioni sul PIN RA4; 0 - gli inpulsi di conteggio sono quelli del clock interno (Fosc/4). T0SE - TMR0 Source Edge Select bit (Funziona quando TOCS è settato a 1) 1 - incrementa TMR0 sul fronte di discesa (da1 a 0) 0 - Incrementa TMR0 sul fronte di salita (da0 a 1). PSA - Prescaler Assignment bit 0 - Il prescaler viene assegnato TMR0 1 - Il prescaler viene assegnato WDT. PS2, PS1, PS0 - Prescaler Rate Select bit il prescaler viene regolato secondo quanto previsto nella tabella 4-1. PS2 PS1 PS0 TMR0 WDT 0 0 0 1:2 1:1 0 0 1 1:4 1:2 0 1 0 1:8 1:4 0 1 1 1:16 1:8 1 0 0 1:32 1:16 1 0 1 1:64 1:32 1 1 0 1:128 1:64 1 1 1 1:256 1:128 Table 4-1 Prescaler Rate Se si decide di utlizzare gli interrupt esterni (bisogna porre a 1 il bit PEIE del registro INTCON) bisogna settare anche i registri PIE1
3 di 9 05/03/2012 18:06 Register, PIE2 Register, PIR1 Register le cui informazioni sono reperibili sul datasheet[3] Come gestire l'interrupt in MiKrobasic Una volta attivato uno dei possibili interrupt è indispensabile gestirlo. Per far ciò in mikrobasic occorre creare una procedura chiamata appunto interrupt che si occuperà di svolgere le procedure desiderate. fig.03 creare un procedura [1] Esempio programma qui presentato non è altro che il programma di esempio che potete trovare dentro la cartella di istallazione del mikrobasic tra gli esempi. Il programma al trascorrere di un secondo accende e spegne un led, a partire da questo programma possiamo realizzare precisi sistemi per la misurazione del tempo all'interno delle nostre applicazioni. program TMR0 dim cnt as word sub procedure interrupt Inc(cnt) ' incrementa la varibile cnt ad ogni interrupt TMR0 = 96 INTCON = $20 ' Setta T0IE, azzero T0IF end sub main: OPTION_REG = $84 ' assegna il prescaler a TMR0... '..scegliendo un prescaler 1:32 ANSEL = 0 ' configura tutti i pin AN... ANSELH = 0 '...in I/O digitali TRISB = 0 ' configura PORTB in uscita PORTB = $FF ' inizializza PORTB TMR0 = 96 ' valore iniziale per TMR0 INTCON = $A0 ' abilita l'interrupt TMRO cnt = 0 ' inizializza cnt while TRUE if (cnt = 200) then PORTB = not PORTB cnt = 0 end if ' inverte PORTB ' Reset cnt
4 di 9 05/03/2012 18:06 wend end. effettuare il calcolo del tempo è abbastanza semplice la formula da utilizzare è la seguente T=(256-T0)*(1/((fclock/4)(PSS))) dove T è il tempo misurato in secondi, T0 è il valore iniziale assegnato a TMR0 (nell' esempio 96), fclock è la frequenza di clock in Hz e PSS è il valore assegnato al prescaler (nel nostro esempio 1/32), l'esempio è perfettamente funzionante con fclock pari a 4,096 MHz. Impostare TMR0 e il prescaler Poiché non sempre il clock utilizzato ha una frequenza che è una potenza del 2 (come nel caso 4,096MHz) ma più facilmente avrà un valore intero quale ad esempio 4 MHz, 8 MHz, 12 MHz e cosi via, il calcolo in questo caso è più complicato, infatti non sempre è possibile ottenere il tempo desiderato tramite un numero intero di interrupt, potrebbe essere infatti necessario eseguire un certo numero di interrupt tutti uguali(cioè con lo stesso TMR0 e lo stesso prescaler) ed eseguire un ultimo ciclo con un valore diverso di TMR0 per regolare correttamente il ritardo desiderato, a tale scopo ho realizzato un foglio excel che può semplificare le cose Calcoli TMR0 Realizzazione di un orologio tramite TMR0 Proponiamo ora un esempio di un orologio realizzato col PIC 16F628A sfruttandando il TMR0. Il circuito è il seguente notiamo il quarzo da 8 MHz collegato tra i PIN 15 e 16, il PIN 4 (MCLR) collegato alla Vdd, il portb collegato al display LCD come mostrato in un knol dedicato, in fine i PIN RA0, RA1 e RA2 sono collegati a degli interruttori per il settaggio dell'orologio. vediamo il codice: ' Il programma qui proposto realizza un orologio realizzato col PIC16F628A ' utilizzando il registro TMR0 la cui precisione è garantita dal quarzo ' 8MHz ' l'ora è visualizzata su un display LCD 2x16 collegato al portb ' i tra PIN RA0, RA1 e RA2 sono utilizzati per l'impostazione dell' ora program orologiotmr0 '-----dichiarazione delle variabili relative all'ora --------------------------- DIM MINUTI,ORE,SECONDI,ATTESA,CONT_INTERRUPT,PROVA AS BYTE DIM VISMIN,VISORE,VISSEC AS CHAR[3] 'Subroutine per la gestione dell'interrupt DI OVERFLOW (62 volte OGNI SECONDO)
5 di 9 05/03/2012 18:06 sub procedure Interrupt IF INTCON.T0IF=1 THEN IF ATTESA>cont_interrupt THEN' se attesa è maggiore di 62 prova=1 'ATTIVA LA VARIABILE DI CONTROLLO (UNA VOLTA AL SECONDO) ATTESA=0 IF ATTESA<cont_interrupt THEN 'se attesa e minore di 62 viene incrementata di 1 ATTESA=ATTESA+1 INTCON.T0IF=0 'azzera il flag di segnalazione overflow di TMR0 IF ATTESA=cont_interrupt THEN 'se attesa è uguale a 62 esegue un ciclo residuo ATTESA=ATTESA+1 TMR0=%11110111 INTCON.T0IF=0 'azzera il flag di segnalazione overflow di TMR0 INTCON.T0IF=0 'azzera il flag di segnalazione overflow di TMR0 END SUB MAIN: CMCON=7 'azzera i moduli comparatori vedi datasheet OPTION_REG=%00000110 'viene assegnato il prescaler a TMR0 a 1/128 INTCON=%10100000 'viene attivato l'interrupt su TMR0 TRISA.0=1 TRISA.1=1 TRISA.2=1 TRISB=0 portb=0 'RA0 è impostato come ingresso per settaggio orologio 'RA0 è impostato come ingresso per settaggio orologio 'RA0 è impostato come ingresso per settaggio orologio 'tutto il portb è impostato come uscita per il display LCD 'il portb viene inizzializzato a zero (display) MINUTI=0 'inizializza la variabile MINUTI ORE=0 'inizializza la variabile ORE SECONDI=0 'inizializza la variabile SECONDI cont_interrupt=62 'impostazione degli interupt a 62 del TMR0 Lcd_Config(PORTB,3,2,1,0,PORTB,4,7,5) 'configuro il display LCD LCD_CMD(LCD_CLEAR) 'cancello l'lcd LCD_CMD(LCD_CURSOR_OFF) 'il cursore viene spento LCD_OUT( 1, 1, "Orologio by F.O.") WHILE TRUE 'ciclo infinito '--------------conteggio tempo--------------------------- while prova=1 'INCREMENTA SECONDI SE MINORI DI 60 IF SECONDI<60 THEN SECONDI=SECONDI+1 INTCON.T0IF=0 'AZZERA SECONDI E INCREMENTA MINUTI IF (SECONDI=60) OR (SECONDI>60) AND (MINUTI<60) THEN SECONDI=0 MINUTI=MINUTI+1 INTCON.T0IF=0 'INCREMENTA ORE IF (ORE<24) AND (MINUTI=60) THEN ORE=ORE+1 MINUTI=0 SECONDI=0 INTCON.T0IF=0 'AZZERA ORE MINUTI E SECONDI IF (ORE=24) OR (ORE>24 )THEN ORE=0 MINUTI=0 SECONDI=0 INTCON.T0IF=0 '-----------------fine conteggio tempo--------------------------------- '-------------------Visualizza ora------------------------------------- BYTETOSTR(ORE, VISORE) 'converte ORE (byte) in VISORE (STR) LCD_OUT(2, 1, VISORE) 'visualizza la stringa VISORE LCD_OUT(2, 4, ":") 'visualizza il : al 4 caratt 2 riga
6 di 9 05/03/2012 18:06 BYTETOSTR(MINUTI, VISMIN) 'converte MINUTI (byte) in VISMIN (STR) LCD_OUT(2, 5, VISMIN) 'visualiza la stringa VISMIN LCD_OUT(2, 8, ":") 'visualizza il : all'8 caratt 2 riga BYTETOSTR(SECONDI, VISSEC)'converte SECONDI (byte) in VISSEC (STR) LCD_OUT(2, 9, VISSEC) 'visualizza VISSEC al 9 caratt 2 riga '-----------------fine visualizza ora-------------------------------- '-------------------impostazione orario--------------------- while BUTTON(PORTA, 0, 1, 1) 'inizia ciclo finché RC3 viene mant premuto LCD_CMD(LCD_CLEAR) 'cancella l'lcd LCD_OUT( 1, 1, "IMPOST OROLOGIO") 'visualizza l'info Impost orol SECONDI=0 'impostazione secondi a zero BYTETOSTR(SECONDI, VISSEC) 'converte SECONDI (Byte) a VISSEC (STR) LCD_OUT( 2, 9, VISSEC) 'visualizza VISSEC su LCD IF BUTTON(PORTA, 2, 1, 1) THEN '-------------IMPOSTAZIONE MINUTI IF MINUTI<59 THEN MINUTI=MINUTI+1 'incrementa MINUTI BYTETOSTR(MINUTI, VISMIN)'converte MINUTI (byte) a VISMIN (STR) LCD_OUT(2, 5, VISMIN) 'visualizza VISMIN su LCD LCD_OUT(2, 8, ":") 'visualizza i : DELAY_MS(200) 'ritardo anti rimbalzo pulsante ELSE MINUTI=0 BYTETOSTR(MINUTI, VISMIN)'converte MINUTI (byte) a VISMIN (STR) LCD_OUT(2, 5, VISMIN) 'visualizza VISMIN su LCD LCD_OUT(2, 8, ":") 'visualizza i : DELAY_MS(200) 'ritardo anti rimbalzo pulsante IF BUTTON(PORTA, 1, 1, 1) THEN '------------IMPOSTAZIONE ORE IF ORE<23 THEN ORE=ORE+1 'incrementa ORE BYTETOSTR(ORE, VISORE) 'converte ORE (byte) a VISORE (STR) LCD_OUT(2, 1, VISORE) 'visualizza VISORE su LCD LCD_OUT(2, 4, ":") 'visualizza i : DELAY_MS(200) 'ritardo anti rimbalzo pulsante ELSE ORE=0 BYTETOSTR(ORE, VISORE) 'converte ORE (byte) a VISORE (STR) LCD_OUT(2, 1, VISORE) 'visualizza VISORE su LCD LCD_OUT(2, 4, ":") 'visualizza i : DELAY_MS(200) 'ritardo anti rimbalzo pulsante LCD_OUT( 1, 1, "Orologio by F.O.")'viene riscritta la prima riga INTCON=%10100000 'viene riattivato l'interrupt su TMR0 WEND '---------------- FINE impostazione orario ----------------- prova=0 wend wend end. Il programma è ampiamente commentato ma vediamo di chiarire alcuni aspetti fondamentali: Per prima cosa vengono definite tutte le variabili subito dopo parte la procedura interrupt per prima cosa controlliamo se è scattato l'interrupt su TMR0 controllando il flag INTCON.TOIF poi effettuiamo l'incremento della variabile ATTESA che serve appunto a contare il giusto numero di interrupt per contare un secondo se ATTESA è minore di 62 (variabile cont_interrupt) incremento ATTESA se ATTESA è uguale a 62 eseguo un ciclo residuo impostando TMR0 a 247 se ATTESA è maggiore di 62 metto ad 1 la variabile prova e azzero ATTESA(ricomincio il conteggio) finita la procedura interrupt comincia il main, per prima cosa disattiviamo tutti i comparatori del 16F628A tramite l'istruzione CMCON=7 (vedi datasheet) settiamo il prescaler a 1:128 e lo assegniamo a TMR0 tramite il registro OPTION_REG attiviamo l'interrupt su TMR0 tramite il registro INTCON setto ingressi e uscite inizializzo le variabili inizializzo il display creo un ciclo infinito al interno del ciclo infinito realizzo un ciclo che viene eseguito quando la variabile prova vale 1 (cioè una volta al secondo) alla fine
7 di 9 05/03/2012 18:06 del ciclo azzero prova tramite una serie di cicli if regolo l'ora che verrà visualizzata incrementando in modo opportuno secondi minuti e ore una porzione di codice è dedicata alla visualizzazione dell'ora, effettuando una conversione da byte a stringa delle tre variabili SECONDI, MINUTI e ORE. un ultima porzione di codice e dedicata alla regolazione dell'orario, viene utilizzata in particolare la funzione Button molto utile quando si lavora con i tasti per chiarimenti vedi L'immagine seguente mostra la simulazione dell'orologio effettuata tramite proteus Indice corso E' gradita la segnalazione di eventuali errori, o anche la richiesta di ulteriori approfondimenti. References 1. 2. 3. http://www.farelettronica.com/articolo.asp?aid=3001 http://www.mikroe.com/en/books/picmcubook/ http://www.microchip.com/wwwproducts/devices.aspx?ddocname=en026561 Stellaris MCUs da TI Fino a 100 MHz, 256 KB Flash,96 KB SRAM & USB, CAN, Ethernet & C/CC++ www.ti.com/stellaris Comments Write New Comment
8 di 9 05/03/2012 18:06 Anonymous Invite as author Ottimo knol, qualche errore html Ottimo questo knol Segnale però qualche errore di battitura Non si vedono le immagini dei registri e la formula T=(256-T0)*(1/((fclock/4)(PSS) è sbagliata, ci sono 5 parentesi aperte e 3 chiuse Peccato perchè mi interessava Per il resto spero di vedere presto gli altri capitoli del corso Ciao Last edited Jan 31, 2012 9:55 AM DeleteBlock this userreport abusive comment 0 Post reply to this comment Anonymous Invite as author problema con 16f84a ciao francesco volevo farti una domanda riguardante questo pic, in effetti volevo sapere se posso fargli leggere dei toni a bassa frequenza( da 67 a 250 hz) in ingresso per poi attivare delle uscite, e possibile? puoi darmi una dritta sui comandi da utilizzare. ti ringrazio ciao salvatore la mia mail e la seguente iz8ifl@gmail.com Last edited Dec 2, 2011 3:43 PM DeleteBlock this userreport abusive comment 0 Post reply to this comment Alex Max Invite as author tranne una puo spiegarmi una cosa: se io scrivo trisa=15 mi apre tutte le porte tranne RA4 a cosa e dovuto grz anticipatamente Last edited Jul 31, 2010 5:33 AM DeleteBlock this userreport abusive comment +1 View/post replies (1) to this comment Silverio Carugo Invite as author Splendido Francesco,
9 di 9 05/03/2012 18:06 il tuo didasknol è davvero esemplare. Complimenti! Last edited Jan 25, 2009 11:33 AM DeleteBlock this userreport abusive comment +1 Post reply to this comment