Tutorial PIC - Dai registri agli interrupt

Prova Il Nostro Strumento Per Eliminare I Problemi





Prima di entrare nei minimi dettagli della programmazione PIC, sarebbe importante imparare alcuni buoni metodi di programmazione.

Comprensione dei registri

Per cominciare, supponiamo di digitare un (punto e virgola) in qualsiasi punto del programma, tutto ciò che viene dopo questo punto e virgola verrebbe ignorato dal compilatore, fino a quando, naturalmente, il carrello non torna nella posizione.



La funzione di cui sopra ci consente di aggiungere commenti o osservazioni in modo tale che non diventino parte del programma ma ci facilita l'identificazione del programma con l'aiuto dei commenti accanto ad esso. Inserire commenti è una pratica consigliata durante la programmazione di qualsiasi IC.

La prossima cosa importante nel corso è assegnare nomi alle varie costanti (le imparerai in seguito in modo elaborato). Ciò inoltre rende più semplice capire cosa si sta scrivendo o riguardo ai valori coinvolti, invece di confondersi con i numeri inclusi.



Quanto sopra deve essere fatto sotto forma di nomi effettivi per il riconoscimento immediato, ad esempio COUNT, sarebbe importante notare che qui vengono utilizzate tutte le lettere maiuscole per distinguerlo e indicare anche che si tratta di un valore costante.


Come possiamo vedere, quanto sopra è fatto sotto forma di una casella fatta di punti e virgola, questo lo fa sembrare più pulito. Inoltre, prova a documentare il programma anche su carta, questa pratica ti aiuterà a capire le cose in modo saggio.

2. I registri.

Il registro all'interno di un PIC è un'area che accetta dettagli scritti e ne consente la lettura. Puoi confrontarlo con un foglio di carta in cui puoi visualizzare i contenuti e anche aggiungere scrivendoci sopra.

La figura seguente mostra una tipica mappa di file di registro incorporata in un PIC16F84. Il formato non è qualcosa che è effettivamente impostato all'interno del PIC, è semplicemente per indicare come i bit possono essere disposti all'interno del chip e per comprendere alcuni dei comandi coinvolti.

Puoi vedere che è fondamentalmente diviso in Banco 0 e Banco 1. Il Banco 1 è responsabile del controllo dell'effettivo funzionamento del PIC, ad esempio comunica al PIC quali bit sulla Porta A sono assegnati come ingressi e quali sono come uscite.

La banca 2 serve solo per manipolare le informazioni.

Comprendiamo questo attraverso il seguente esempio:

Supponiamo di voler assegnare un bit a PortA alto. Per questo dovremmo prima andare al banco 1 per impostare il bit o il pin specificato sulla porta A sotto forma di uscita. Dopodiché torniamo al banco 0 e forniamo un 1 logico (bit 1) a quel pin specifico.

I registri più comuni che vorremmo utilizzare nella Banca 1 sono STATUS, TRISA e TRISB.

STATUS ci aiuta a tornare al banco 0, TRISA ci permette di scegliere quali pin sulla porta A sono uscite e quali possono essere ingressi, mentre TRISB facilita la selezione tra uscita e pin di ingresso sulla porta B. Il registro SELECT in BANCO 0 lo consente all'utente per passare al banco 1.

Riassumiamo l'intero concetto con la seguente descrizione:

STATO:

Per passare dal banco 0 al banco 1, comandiamo il registro STATUS. Ciò viene implementato impostando il bit # 5 del registro STATUS a 1. Per tornare al banco 0, assegniamo il bit 5 del registro STATUS a 0. Il registro STATUS è posizionato all'indirizzo 03h, qui h significa tat il numero può essere in esadecimale.

TRISA e TRISB:

Questi si trovano all'indirizzo 85h e 86h corrispondentemente. Per programmare un pin come uscita o ingresso, forniamo solo uno zero o uno al bit particolare nel registro. Ora questo può essere fatto in due modi, tramite binario o esadecimale. Nel caso in cui uno non sia in grado di convertire il parametro, può rivolgersi a una calcolatrice scientifica per implementare i valori.

Ora abbiamo 5 pin sulla porta A, che corrisponde a 5 pin. Se intendiamo fissare uno dei pin come ingressi, forniamo un '1' al bit particolare.

Nel caso in cui volessimo assegnare uno dei pin come uscite, dovremmo impostare il pin specifico a '0'. I bit sono aiuti giù esattamente corrispondenti ai bit, o più precisamente il bit 0 è RA0, il bit 1 sarebbe RA1, il bit 2 = RA2 e così via. Vediamolo in questo modo:

Supponi di voler correggere RA0, RA3 e RA4 come uscite, mentre RA1 / RA2 come i / ps, dovresti farlo inviando 00110 (06h). Controlla che il bit 0 sia verso destra come indicato qui:

Porta A Pin RA4 RA3 RA2 RA1 RA0

Numero bit 4 3 2 1 0

Binario 0 0 1 1 0

Lo stesso vale per TRISB.

PORTA and PORTB

Per portare uno dei pin di uscita in alto, offriamo solo un '1' al rispettivo bit nel nostro registro PORTA o PORTB. Una procedura identica può essere seguita anche per i registri TRISA e TRISB. Prima di passare al nostro primo esempio di codifica, capiamo solo un coupé di più registri, vale a dire: w e f.

W e F

Il registro W è un registro ordinario che consente di assegnare qualsiasi valore a scelta. Non appena si assegna una grandezza a W, è possibile procedere aggiungendola a un altro valore o semplicemente spostandola. Con un altro valore assegnato, i dettagli vengono semplicemente sovrascritti su W.

Il registro F inoltra la sua materia scritta a un registro. Richiediamo a questo registro F di assegnare un valore su un registro, potrebbe essere sui registri STATUS o TRISA, poiché questi non ci consentono di inserire i valori direttamente su di essi. Un programma di esempio

Esaminiamo il seguente codice di esempio che ci mostrerà come vengono implementate le istruzioni di cui sopra e testimonierebbe anche alcune delle istruzioni del corso.

Iniziamo riparando la porta A come discusso sopra.

Per questo dobbiamo passare da Bank 0 a Bank1, questo viene fatto impostando il registro STATUS situato all'indirizzo 03h, bit 5 a 1.

BSF 03h, 5

Il BSF significa Bit Set F. Stiamo usando due numeri dopo questa istruzione - 03h, che è l'indirizzo del registro STATUS, e il numero 5 che corrisponde al numero di bit.

Quindi, quello che stiamo dicendo è 'Imposta il bit 5 nell'indirizzo 03h a 1'.

Ora siamo in Bank 1.

MOVLW 00110b

Stiamo inserendo il valore binario 00110 (la lettera b significa che il numero è in binario) nel nostro registro generico W. Avrei potuto ovviamente farlo in esadecimale, nel qual caso la nostra istruzione sarebbe:

MOVLW 06h

O funziona. MOVLW significa 'Move Literal Value Into W', che in inglese significa inserire il valore che segue direttamente nel registro W.

Ora dobbiamo mettere questo valore nel nostro registro TRISA per impostare la porta:

MOVWF 85h

Questa istruzione indica 'Sposta il contenuto di W nell'indirizzo di registro che segue', in questo caso l'indirizzo si riferisce a TRISA.

Il nostro registro TRISA a questo punto porta la figura 00110, oppure presentato graficamente:

Porta A Pin RA4 RA3 RA2 RA1 RA0

Binario 0 0 1 1 0

Ingresso / Uscita O O I I O

Quindi ora che possediamo i nostri pin della porta A, dobbiamo tornare al banco 0 per regolare una delle informazioni.

BCF 03h, 5

Questa istruzione esegue il contrario di BSF. Implica 'Bit Clear F'. La coppia di numeri a che corrispondono sono l'indirizzo del registro, qui il registro STATUS, così come la cifra del bit, in questo caso il bit cinque. Quello che esattamente abbiamo completato al momento è, definito bit cinque sul nostro

STATUS registra a 0

A questo punto siamo tornati in Bank 0.
Quello che segue è il codice tutto in un blocco:

BSF 03h, 5 Vai alla banca 1
MOVLW 06h Metti 00110 in W
MOVWF 85h Sposta 00110 su TRISA
BCF 03h, 5 Torna alla banca 0

Nell'ultima istruzione, ti abbiamo confermato come stabilire i pin della porta IO sul PIC in modo che possano essere eventualmente input o output.

Attraverso questo corso, lascia che ti aiuti a inviare dati alle porte.

Invio di dati alle porte

Nel tutorial successivo, lo completeremo facendo lampeggiare un LED acceso e spento che consiste in un programma completo che dettaglia e in uno schema circuitale semplice in modo che tu possa vedere il PIC che esegue esattamente ciò che ci aspettiamo.

Non tentare di mettere insieme e programmare il tuo PIC con i risultati seguenti, poiché sono solo illustrazioni. Inizialmente, stabiliremo la porta A bit 2 come uscita:

Questo potrebbe essere riconoscibile dalla precedente istruzione. L'unica distinzione potrebbe essere che abbiamo corretto ogni bit dei pin su A come output, fornendo 0h al registro a tre stati. Quindi quello che ora deve fare è accendere un LED.

Lo facciamo programmando uno dei pin (quello con il LED ad esso collegato) alto. Per dirla in modo diverso, applichiamo un '1' al pin. Questo è esattamente esattamente come viene eseguito (osservare i commenti per un chiarimento per ogni riga):

Pertanto, ciò che ora abbiamo ottenuto è accendere il LED e poi spegnerlo una volta. Quello che desideriamo è che il LED si accenda successivamente e si spenga continuamente.

Otteniamo questo ottenendo il programma per tornare all'inizio. Otteniamo ciò stabilendo inizialmente un tag all'inizio del nostro programma, quindi informando il programma di tornare lì. Specifichiamo un tag in modo abbastanza semplice.

Digitiamo un termine, diciamo START, quindi digitiamo il codice:

Come dimostrato, inizialmente abbiamo menzionato l'espressione 'Start' immediatamente all'inizio del programma.

Successivamente, alla fine del programma abbiamo chiaramente menzionato 'goto Start'. L'istruzione 'goto' esegue esattamente ciò che dichiara.

Questo programma accende e spegne costantemente il LED ogni volta che accendiamo il circuito, tendendo a spegnersi una volta rimossa l'elettricità. Forse dovremmo controllare ancora una volta il nostro programma:

Sicuramente abbiamo omesso i commenti, tuttavia possiamo ancora osservare le istruzioni ei numeri.

Questo può essere un po 'sconcertante in seguito nel caso in cui provi a risolvere i problemi del programma e mentre scrivi il codice hai memorizzato tutti gli indirizzi.

Sebbene i commenti possano essere ancora inseriti, potrebbe diventare un po 'disordinato. Ciò richiederà la denominazione dei numeri e potrebbe essere ottenuto da un'istruzione aggiuntiva: 'equ' L'istruzione 'equ' suggerisce che alcune cose potrebbero essere uguali a altre cose.

Potrebbe non essere un'istruzione per PIC, piuttosto per l'assemblatore. Questa istruzione facilita l'assegnazione del nome a una posizione dell'indirizzo di registro o di una costante a un termine di programmazione.

Stabiliremo alcune costanti per il nostro programma e testimonieremo anche quanto sia semplice leggere il programma.

Fin da ora abbiamo fissato i valori costanti possiamo procedere impostandoli nel nostro programma. I valori costanti devono essere designati prima di utilizzarli.

quindi assicurati di posizionarli sempre all'inizio del programma. Riscriveremo nuovamente il programma escludendo i commenti, in modo da confrontare l'etichettatura precedente con quella più recente.

Potresti notare che le costanti stanno consentendo una comprensione leggermente più semplice del programma, tuttavia siamo ancora senza commenti, non preoccuparti, dato che non abbiamo ancora finito.

Potrebbe esserci un piccolo svantaggio del nostro programma LED lampeggiante.
Ogni istruzione necessita di 1 sequenza di clock per terminare. Nel caso in cui stiamo utilizzando un cristallo da 4 MHz, ogni istruzione richiede 1 / 4MHz o 1uS per finire.

Dato che abbiamo utilizzato solo cinque istruzioni, il LED si sarebbe attivato e poi spento in 5uS. Questo potrebbe essere troppo rapido perché la gente lo noti, inoltre, sembrerà che il LED sia completamente acceso.

Quello che invece dovremmo ottenere è produrre un'inibizione tra l'accensione del LED e lo spegnimento del LED. La teoria dell'inibizione è che eseguiamo il conto alla rovescia da una quantità precedente, quindi quando arriva a zero, smettiamo di contare.

Il valore zero indica la conclusione del ritardo e continuiamo a lavorare sul nostro processo durante tutto il programma. Pertanto, la prima cosa che dobbiamo fare è determinare una costante da utilizzare come nostro contatore.

Chiamiamo questa costante CONTE. Dopodiché, dobbiamo determinare quanto sia significativo un numero da cui iniziare a contare. Sicuramente, la cifra più grande che potremmo includere è 255, o FFh in esadecimale., Come ho detto nel tutorial precedente, l'istruzione equ assegna un'espressione a una situazione di registro.

Ciò implica che non importa quale quantità assegniamo il nostro COUNT, corrisponderebbe agli elementi di un registro. Nel caso in cui proviamo a designare il valore FFh, faremo un errore una volta che avremo compilato il programma.

Il motivo è che la posizione FFh è, quindi non possiamo accedervi. Quindi, come dobbiamo designare un numero autentico? Certamente, richiederà una piccola quantità di riflessione laterale.

Se forse designiamo il nostro COUNT all'indirizzo 08h, ad esempio, ciò indicherebbe una destinazione di registro obiettivo di base. Per impostazione predefinita, le aree non toccate sono impostate su FFh. Di conseguenza, se COUNT porta a 08h, incontrerai il valore di FFh durante la prima accensione. Tuttavia, io tu, come possiamo fissare COUNT a un altro numero ?, tutto ciò che applichiamo è 'spostare' prima una valutazione a questa destinazione.

A titolo illustrativo, supponiamo di voler che COUNT possieda un valore di 85h, non possiamo menzionare COUNT equ 85h poiché questa è la posizione del registro Tri-State per il porto A. Esattamente quello che otteniamo è il seguente: movlw 85h il valore di 85h nel registro W movwf 08h

Ora spostalo nel nostro registro delle 08h. Successivamente, nel caso in cui esprimiamo COUNT equ 08h, COUNT corrisponderà al valore 85h. Delicato, non è vero! Pertanto, inizialmente determiniamo la nostra costante: COUNT equ 08h Successivamente dobbiamo ridurre questo COUNT di uno finché non diventa zero.

Accade semplicemente che esista un'istruzione progettata per eseguire ciò per noi, utilizzando un 'goto' e un tag.

L'istruzione che applicheremo è: DECFSZ COUNT, 1 Questa istruzione afferma 'Decrementa il registro (qui è COUNT) del numero che tiene traccia della virgola. Se raggiungiamo lo zero, saltiamo avanti di due posti. 'Troviamolo in azione prima, prima di inserirlo nella nostra rotta.

Quello che abbiamo eseguito è stato inizialmente stabilire la nostra costante COUNT a 255. Il segmento successivo posiziona un tag, chiamato LABEL vicino alla nostra istruzione decfsz.

Il decfsz COUNT, 1 riduce il valore di COUNT di uno e mantiene il risultato finale direttamente in COUNT. Inoltre verifica per controllare se COUNT possiede un valore di 0.

In caso contrario, in tal caso attiva il programma per passare alla riga successiva. Ora abbiamo una dichiarazione 'goto' che ci riporta alla nostra istruzione decfsz.

Nel caso in cui il valore di COUNT sia uguale, l'istruzione decfsz fa sì che il nostro programma salti di 2 posizioni in avanti e viene inviato a dove abbiamo affermato 'Continua qui'.

Pertanto, poiché puoi osservare, abbiamo fatto in modo che il programma si sieda in un punto per un tempo predestinato prima di procedere. Questo potrebbe essere chiamato un ciclo di ritardo.

Capire i loop di ritardo

Nel caso in cui richiedessimo un ritardo più sostanziale, potremmo seguire un ciclo per il successivo. I loop extra, il ritardo esteso. Facciamo almeno due, supponendo di voler osservare il LED lampeggiante .. Inseriremo questi cicli di ritardo nel nostro programma e lo faremo rendendolo un programma autentico introducendo commenti:

È possibile compilare questo programma dopodiché programmare il PIC. Ovviamente, assicurati di provare il circuito per verificare se funziona davvero. Quello che segue è uno schema del circuito che dovresti costruire non appena hai programmato il PIC.


Ben fatto, avresti potuto effettivamente comporre il tuo primo programma PIC, oltre a costruire un circuito per accendere e spegnere un LED. Fino ad ora, nel caso in cui tu abbia seguito questi corsi, potresti aver imparato un totale di sette istruzioni su 35, ma senza dubbio finora potresti controllare le porte I / O!

Provereste a cambiare i loop di ritardo per rendere il flash LED più veloce - qual è il valore minimo di COUNT per vedere essenzialmente il flash LED? O forse, vorrai includere un 3 ° loop di ritardo o supplementare dopo quello iniziale per stabilizzare il LED verso il basso. una costante univoca per ogni ciclo di ritardo.

Potresti quindi potenzialmente giocherellare con i tuoi loop di ritardo per rendere il flash LED a una velocità specifica, ad esempio dopo un secondo. Nella prossima istruzione vediamo come siamo in grado di utilizzare qualcosa noto come una subroutine per mantenere il programma compatto e di base. Una subroutine è parte integrante del codice, o programma, che può essere indicato come e quando potrebbe essere necessario. Le subroutine vengono utilizzate nei casi in cui si esegue frequentemente la stessa funzione.

Cosa sono le subroutine

I vantaggi dell'utilizzo di una subroutine sono che probabilmente sarà più semplice modificare il valore una volta all'interno di una subroutine invece di, diciamo, dieci volte per tutto il programma, così come contribuisce notevolmente a diminuire il livello di memoria che il programma consuma all'interno del PIC. Verificheremo una subroutine:

Inizialmente, dobbiamo fornire una designazione alla nostra subroutine e in questa situazione abbiamo selezionato ROUTINE. Dopo di che digitiamo il codice che vorremmo condurre normalmente. Ecco perché, abbiamo selezionato il ritardo nel nostro programma con led lampeggianti. Infine, concludiamo la subroutine digitando l'istruzione RETURN.

Per iniziare la subroutine da qualsiasi punto del nostro programma, digitiamo rapidamente l'istruzione CALL e quindi la designazione della subroutine.

Lo considereremo un po 'più in profondità. Una volta arrivati ​​alla sezione del nostro programma CHIAMATA xxx, in cui xxx è il nome della nostra subroutine, il programma salta ovunque sia installata la subroutine xxx. Vengono eseguite le istruzioni all'interno della subroutine.

Ogni volta che viene eseguita l'istruzione RETURN, il programma salta tornando al nostro programma principale all'istruzione successiva alla nostra istruzione CALL xxx.

È possibile richiamare la subroutine simile più volte come si desidera, il che spiega perché l'utilizzo di subroutine riduce la durata generale del nostro programma.

Tuttavia, ci sono un paio di fattori che dovresti conoscere. Inizialmente, come con il nostro programma principale, tutte le costanti specifiche devono essere riconosciute prima di poterle utilizzare.

Questi possono essere eventualmente riconosciuti all'interno della subroutine stessa, o direttamente all'inizio del programma principale. Vi propongo di riconoscere tutto all'inizio del vostro programma principale, da allora riconoscete che le cose sono in una posizione identica. Successivamente, è necessario assicurarsi che il programma principale salti la subroutine.

Ciò che intendo dire è che dovresti posizionare la subroutine direttamente alla conclusione del tuo programma principale, tranne se utilizzi una dichiarazione 'Goto' per saltare da dove si trova la subroutine, il programma continuerà e implementerà la subroutine indipendentemente dal fatto che tu richiederlo o altro.

Il PIC non distingue tra una subroutine e il programma principale. Verificheremo il nostro programma led lampeggiante, tuttavia questa volta utilizzeremo una subroutine per il ciclo di ritardo. Idealmente, scoprirai quanto appare meno complicato il programma, così come potresti scoprire come la subroutine si applica praticamente.

Alla fine, puoi osservare che utilizzando una subroutine per il nostro ciclo di ritardo, potremmo aver ridimensionato le dimensioni del programma.

Ogni volta che desideriamo un ritardo, possibilmente quando il LED è acceso o spento, chiamiamo fondamentalmente la subroutine del ritardo. Al termine del sottoprogramma, il programma riconduce alla riga che segue la nostra istruzione 'Chiama'. Nell'illustrazione sopra, accendiamo il LED.

Dopodiché contattiamo la subroutine. Il programma ritorna quindi in modo da poter spegnere il LED. Chiamiamo di nuovo la subroutine, nel caso in cui la subroutine potrebbe essere stata completata, il programma ritorna e l'istruzione successiva che riconosce è 'goto Start'. Per chiunque possa essere incuriosito, il nostro primo programma era lungo 120 byte.

Attraverso l'uso della subroutine, potremmo ridurre la dimensione del nostro programma fino a 103 byte. Questo non potrebbe sembrare fantastico, tuttavia considerando il fatto che abbiamo solo 1024 byte complessivi all'interno del PIC, ogni piccola quantità ne beneficia.

Entro la prossima istruzione, controlliamo la lettura dai porti.

Finora abbiamo composto sulla porta A in modo da poter accendere e spegnere un LED. A questo punto, vedremo come leggeremo i pin di I / O sulle porte.

Lettura delle porte di ingresso / uscita

Questo è esattamente per garantire che siamo in grado di collegare un circuito esterno e influenzare eventuali uscite specifiche che offre.

Se si memorizza dai nostri corsi precedenti, se si desidera stabilire le porte I / O, è necessario passare dal banco 0 al banco 1. Inizialmente lo faremo:

A questo punto abbiamo fissato il bit 0 della porta A in ingresso. dobbiamo ora esaminare se il pin è alto o basso. Per ottenere ciò, è possibile utilizzare solo una delle due istruzioni:

BTFSC e BTFSS.

L'istruzione BTFSC significa 'Fai un test di bit sul registro così come il bit designato.

Nel caso sia uno 0, in tal caso omettiamo l'istruzione successiva '. BTFSS implica 'Fai un po 'di test nel registro e il bit viene stabilito. Nel caso in cui sia impostato su 1, ignoriamo l'istruzione successiva.

Quello che utilizziamo è determinato esattamente dal modo in cui desideriamo che il nostro programma risponda mentre studiamo l'input. A titolo illustrativo, nel caso in cui stiamo solo aspettando che l'input sia un 1, potremmo essere in grado di utilizzare l'istruzione BTFSS nel modo seguente:

Codice qui:

BTFSS PortA, 0Goto start Continua qui:
:

Il programma passerebbe semplicemente a 'Continua qui' a condizione che il bit 0 su PortA sia programmato su 1.

Al momento scriveremo un programma che potrebbe richiedere un LED a una velocità, tuttavia se un interruttore è limitato, il LED lampeggerà due volte più lentamente.

È possibile forse esercitare questo programma per conto proprio, tuttavia abbiamo incorporato l'elenco in qualche modo.

Potresti provare e creare l'intero programma, per verificare se hai compreso i principi. Useremo il circuito equivalente come prima, con l'inclusione di un interruttore collegato RA0 del PIC e il rail positivo della nostra fornitura.

Quello che abbiamo realizzato qui è accendere il LED. Successivamente determino se l'interruttore è chiuso.

Nel caso sia confinato, successivamente mi collego alla nostra subroutine di ritardo. Questo ci fornisce il ritardo equivalente a prima, tuttavia a questo punto lo stiamo contattando due volte.

La stessa cosa vale ogni volta che il LED è spento. Nel caso in cui l'interruttore non sia chiuso, abbiamo i nostri periodi di accensione e spegnimento registrati in precedenza.

Hai seguito queste lezioni dall'inizio, forse stai cercando di capire che hai attualmente scoperto dieci delle 35 istruzioni per il PIC 16F84! E tutto questo può essere appreso semplicemente accendendo e spegnendo un LED.

Fino ad ora, abbiamo composto il PIC lampeggiante un LED acceso e spento.

Successivamente siamo riusciti con il nostro PIC inserendo un interruttore, variando quindi la velocità del flash.

Utilizzo efficiente dello spazio di memoria

L'unico problema è che il programma è piuttosto lungo e piuttosto inefficiente di spazio di memoria. Sembrava ok mentre includevo i comandi per la prima volta, tuttavia dovrebbe esserci un modo più semplice per eseguirlo. Di positivo c'è, analizzeremo come stavamo letteralmente accendendo e spegnendo il LED.

movlw 02hmovwf PORTAmovlw 00hmovlw PORTA

All'inizio abbiamo riempito il nostro registro w con 02h, dopo di che lo abbiamo trasferito al nostro registro PortA per accendere il LED. Per spegnerlo, abbiamo impacchettato w con 00h, dopodiché lo abbiamo spostato nel nostro registro PortA.

Tra tutte queste routine siamo stati costretti a entrare in contatto con una subroutine per assicurarci di poter osservare il LED lampeggiante.

Pertanto, abbiamo dovuto trasferire due set di informazioni un paio di volte (una volta nel registro w e poi a PORTA) e chiamare una subroutine due volte (una volta per acceso e poi una volta per spento). Quindi, come possiamo ottenere questo risultato con maggiore efficienza? Molto semplice.

Utilizziamo un'istruzione diversa nota come XORF. L'istruzione XORF opera una funzione OR esclusiva sul registro che stipuliamo con le informazioni che forniamo. Credo di dover chiarire cosa nel mondo sia una sala operatoria esclusiva prima di continuare. Nel caso in cui abbiamo due ingressi e un'uscita, l'ingresso può essere solo 1 se e fintanto che i due ingressi differiscono. Sebbene siano gli stessi, l'output sarà probabilmente 0. La seguente è una tabella della verità, per le persone che scelgono di controllare questi:

A B F0 0 00 1 11 0 11 1 0

A questo punto controlleremo cosa succede se rendiamo B esattamente come il nostro output precedente, e semplicemente alterando il valore di A:

A B F
0 0 0
0 0 0
1 0 1
1 1 0
1 0 1

Se manteniamo il valore di A uguale a 1 e lo escludiamo in OR esclusivo con l'output, l'output cambierebbe. Nel caso in cui non riesci a notare questo dalla tabella della verità, di seguito puoi vederlo utilizzando il binario:

0 Uscita in corrente
EX-OR con 1 1 nuova uscita
EX-OR con 1 0 Nuova uscita

Forse puoi scoprire che eseguendo l'OR esclusivo dell'output con 1, ora cambieremo l'uscita da 0 a 1 a 0.
Quindi, per accendere e spegnere il nostro LED, sono necessarie solo un paio di frasi:

MOVLW 02h
XORWF PORTA,1

Quello che faremo precisamente è aggiungere il nostro registro w con 02h. In questo caso, stiamo eseguendo l'OR esclusivo di questo numero indipendentemente da ciò che è presente sul nostro PortA. Nel caso in cui il bit 1 sia un 1, cambierà in 0. Nel caso il bit 1 sia uno 0, cambierà in 1. Esaminiamo questo codice una o due volte, per visualizzare come sta eseguendo binario:

PORTA
00010
xorwf 00000
xorwf 00010
xorwf 00000
xorwf 00010

In realtà non dobbiamo caricare ogni volta lo stesso valore nel nostro registro w, quindi è possibile eseguire questa operazione all'inizio e tornare semplicemente al nostro comando di commutazione. Inoltre, non dovremmo fissare un valore sul nostro registro PortA. La ragione? Sicuramente, poiché in caso di accensione è un 1, possiamo facilmente attivarlo. Io, in alternativa uno 0 all'accensione, lo faremmo anche adesso.

Quindi vorresti vedere il nostro codice appena formato. Il primo rappresenta il nostro codice LED lampeggiante, mentre il secondo mostra quello con l'aggiunta dell'interruttore:

Speriamo che tu possa scoprire che semplicemente facendo uso di una semplice istruzione, ora abbiamo ridotto la scala del nostro programma. La verità è che, al fine di mostrare quanto potremmo ridurre i nostri programmi, abbiamo dimostrato i due programmi, esattamente cosa sono stati composti e le loro dimensioni nella tabella seguente:

Programma Alter Dimensions (Bytes)
LED lampeggiante Originale 120
Subroutine LED lampeggiante aggiunta 103
Funzione XOR LED lampeggiante utilizzata 91
LED con interruttore originale 132
LED con interruttore Funzione XOR utilizzata 124.

Pertanto, non solo abbiamo scoperto alcune nuove istruzioni, ma abbiamo sicuramente anche ridotto le dimensioni del nostro scripting!

Di seguito analizzeremo come è possibile muovere singoli bit, eseguire determinate operazioni aritmetiche e tabelle di dati.

Gestori logici

Nell'ultimo tutorial ho presentato l'operazione Exclusive OR. La funzione ExOR è intesa come un operatore logico.

All'interno di questo tutorial illustrerò gli operatori logici aggiuntivi che il PIC promuove. Non ci sarà alcun tipo di caso nei programmi a punti, tuttavia impareremo metodi semplici per utilizzare gli operatori applicando piccole aree di codice.

AND La funzione AND fondamentalmente analizza due bit e fornisce un 1 se sono uguali e uno 0 se sono distintivi. Ad esempio, se abbiamo menzionato 1 AND 1, il risultato è 1, mentre nel caso in cui abbiamo dichiarato 1 AND 0 la conseguenza sarebbe 0.

Inutile dire che siamo in grado di valutare anche le parole, così come tutta la funzione AND esegue è rivedere i due termini un po 'alla volta. L'istanza seguente mostra due parole a 8 bit che diventano AND insieme al prodotto:

11001011
E 10110011
È uguale a 10000011

Spero che tu sia d'accordo, il risultato avrà semplicemente un 1 ogni volta che 2 1 si mano nella mano l'uno con l'altro in un paio di parole. Siamo in grado di utilizzare la funzione AND per verificare le porte, ad esempio.

Nel caso in cui stiamo controllando alcuni pin I / O che sono collegati a un circuito, e dovremmo tenere d'occhio una situazione particolare in cui solo pochi dei pin sono alti, in quel caso siamo in grado di leggere praticamente il port, dopo di che AND il risultato con la condizione che abbiamo esaminato, identico all'istanza sopra.

Il PIC ci fornisce due ingredienti per AND.
Sono ANDLW e ANDWF. ANDLW ci permette di svolgere una funzione AND con i dettagli del registro W e un importo da noi stabilito.

La sintassi è: ANDLW in cui è esattamente ciò che stiamo andando E il contenuto di W con.

La conseguenza della funzione AND sarebbe memorizzata direttamente nel registro W.
ANDWF ci permette di svolgere una funzione AND sul registro W e su un registro diverso, ad esempio un PORT. La sintassi è: ANDWF, d in cui è il registro di cui siamo entusiasti, ad es. PORTA, ed mostra il PIC dove dovresti posizionare il risultato. Se d = 0, il risultato viene inserito nel registro W, e se d = 1 il risultato finale viene salvato nel registro da noi stabilito. Le due parti di codice seguenti mostrano un buon esempio di ciascuna funzione AND.

L'iniziale sta esaminando lo stato del PORTA, in cui dobbiamo verificare se gli ingressi sono 1100. Possiamo rimettere il risultato nel registro W

movlw 1100
ANDWF 05h, 0 La seconda illustrazione potrebbe ora verificare il contenuto del registro W:
ANDLW 1100

O

Abbiamo ormai scoperto una funzione OR, per la precisione XOR. Questo si trasforma in un 1 se due bit non sono uguali, ma sono diversi. Puoi trovare un'altra funzione OR chiamata IOR, che è l'OR inclusivo. Questa funzione genererà un 1 nel caso in cui uno dei due bit sia 1, ma in aggiunta se ogni bit è 1. Di seguito è riportata una tabella di verità chiara per illustrare questo:

A B O / P
0 0 0
0 1 1
1 0 1
1 1 1

Cosa sono gli operatori aritmetici

INSERISCI

Questa funzione esegue ciò che di solito afferma. Contribuisce a due cifre! Nel caso in cui la conseguenza dell'aggiunta delle due cifre superi gli 8 bit, in quel caso verrà probabilmente impostato un flag CARRY. Il flag CARRY si trova all'indirizzo 03h bit 0.

Quando questo bit è programmato, le due cifre hanno superato gli 8 bit. Quando è 0, in quel caso la conseguenza si trova all'interno di 8 bit. Come prima, il PIC ci fornisce due stili di ADD, in particolare ADDLW e ADDWF. Come potresti aver supposto, questa è abbastanza simile alla funzione sopra. ADDLW offre i contenuti del registro W a quanto stipulato. La sintassi è: ADDLW ADDWF aggiunge il contenuto del registro W e qualche altro registro da noi designato.

La sintassi è: ADDWF, d è dove

SUB

A questo punto, immagino che tu non possa presumere cosa conduce questa funzione! Anzi, lo sospettavi, questa funzione
sottrae un bit da un altro. Anche in questo caso il PIC ci fornisce 2 gusti: SUBLW e SUBWF. La sintassi è precisamente simile a quella per la funzione ADD, a parte evidentemente che digiti SUB al posto di ADD!

Incremento Nel caso in cui volessimo includere da 1 a un numero nel PIC, potremmo assolutamente utilizzare la funzione AGGIUNGI e utilizzare il numero uno. ~ La difficoltà con questo è che dobbiamo prima inserire la cifra nel registro W, successivamente utilizzare il controllo ADDLW 1 per incrementarla. Nel caso in cui desiderassimo includere 1 in un registro, può essere ancora peggio. Per prima cosa dobbiamo inserire il numero 1 nel registro W, dopodiché utilizzare ADDWF, 1. Pertanto, ad esempio, per includere 1 nella posizione 0C, diciamo, dovremmo possedere la seguente parte dello script:

movlw 01
addwf 0c, 1

Esiste un metodo più semplice per farlo. Possiamo esercitare il comando INCF. La sintassi è: INCF, d dove, è il registro, o luogo, in cui siamo interessati e d mostra il PIC dove dovresti posizionare il risultato. Nel caso d = 0, il risultato è all'interno del registro W, e nel caso d = 1, la conseguenza è impostata nel registro da noi stabilito.

Utilizzando questa istruzione individuale siamo in grado di realizzare effettivamente il cinquanta percento della codifica. Nel caso avessimo desiderato ripristinare il risultato nel registro W, in quel caso utilizzando l'istanza sopra, avremmo potuto includere un comando aggiuntivo per spostare gli elementi di 0C di nuovo nel registro W, dopodiché rimettere il registro 0C su no importa cosa fosse.

Esiste il comando di incremento. È INCFSZ. Questo comando potrebbe incrementare il registro che stabiliamo, tuttavia se il registro è uguale a 0 dopo l'incremento (che si verificherà mentre includiamo da 1 a 127) dopodiché il PIC probabilmente ignorerà l'istruzione successiva. La parte di codice seguente riflette questo:

Loop incfsz 0C
Goto Loop
:
:
Resto del programma.

Nella parte di codice precedente, 0C verrà incrementato di 1. Successivamente possediamo un'istruzione che informa il PIC di tornare al nostro tag chiamato Loop e incrementare nuovamente 0C di 1. Questo continua fino a quando 0C è uguale a 127. In questa circostanza, quando incrementiamo 0C di 1, 0C ora corrisponderà a 0. La nostra istruzione INCFSZ potrebbe benissimo informare il PIC di omettere l'istruzione successiva, che in questo caso è la dichiarazione goto, quindi il PIC andrà avanti con il resto del programma.

Decremento

Abbiamo già discusso la funzione di decremento nell'allenamento precedente, quindi non la rivedrò più.

Complemento

L'istruzione finale in questa discussione invertirebbe ogni singolo bit nel registro che stipuliamo. La sintassi è: COMF, d in cui

Comprensione delle operazioni sui bit

Questo potrebbe essere utilizzato, ad esempio, per scambiare rapidamente i pin di una porta dall'output all'input e così via. Le funzioni bit ci consentono di modellare un singolo bit all'interno di un'espressione. Ci permettono di procedere, impostare e sbarazzarci di singoli bit nei registri o numeri che stabiliamo.

Alla conclusione di questo corso sveleremo un programma progettato per creare un set di luci in sequenza che procedono in avanti, quindi al contrario. Abbiamo osservato questo risultato in precedenza quando abbiamo esaminato la funzione OR esclusiva, in cui abbiamo eseguito l'OR esclusivo delle porte con un'espressione. Finora abbiamo notato alcune funzioni bit quando stabiliamo le porte sul PIC, e

Permettetemi di ribadire il loro utilizzo qui.

BCF

Questa istruzione cancellerà un po 'che stipuliamo in un registro che designiamo. La sintassi
è:
BCF,

Lo abbiamo utilizzato in precedenza per passare dalla pagina 1 alla pagina 0 rimuovendo un bit nel registro STATUS. Possiamo anche usarlo per aggiustare un bit a 0 in qualsiasi registro / posizione differente. Ad esempio, nel caso in cui desiderassimo impostare il 3 ° bit in 11001101 salvato nella sezione 0C a 0, potremmo
inserire:

BCF 0C, 03

BSF

Questa istruzione aggiusterebbe qualsiasi bit che stabiliamo a 1 in qualsiasi registro che indichiamo. Lo abbiamo utilizzato in precedenza per procedere dalla pagina 0 alla pagina 1. La sintassi è: BSF, ed è utilizzata esattamente nello stesso metodo di BCF sopra.

BTFSC Fino ad ora abbiamo potuto impostare o cancellare un po 'in un registro. Tuttavia, immagina se dobbiamo fondamentalmente verificare se un bit è un 1 o uno 0 in un registro?

Sicuramente è possibile utilizzare BTFSC. Indica Bit Test Register F, e Skip If It Is Clear. Questa istruzione analizzerà il bit che designiamo nel registro. Nel caso in cui il bit sia uno 0, l'istruzione informerebbe il PIC di bypassare l'istruzione successiva.

Potremmo utilizzare questa istruzione nel caso in cui desiderassimo controllare un flag, ad esempio il carry flag. Questo ci evita di dover leggere il registro STATUS e cercare i singoli bit per sapere quali flag sono corretti. 29 Ad esempio, nel caso in cui volessimo controllare se il flag Carry era impostato su 1 dopo aver aggiunto 2 cifre, potremmo digitare quanto segue:

BTFSC 03h, 0
continuare qui se impostato su 1
o qui se impostato a 0

Nel caso in cui lo stato del bit sia 1, in tal caso l'istruzione successiva a BTFSC verrebbe completata. Nel caso sia impostato a 0, in tal caso l'istruzione successiva viene saltata. La parte seguente del codice mostra in cui potrebbe essere impiegato:

Ciclo continuo :
:
:
BTFSC 03,0
Goto Loop

Nel codice precedente, il PIC uscirà semplicemente dal ciclo nel caso in cui il bit 0 del registro STATUS (o il flag Carry) sia definito a 0. Altrimenti, verrebbe eseguito il comando goto.

BTFSS

Questa istruzione indica Bit Test Register F e Skip If Set. Questo può essere paragonabile all'istruzione BTFSC, a parte il fatto che il PIC ometterebbe l'istruzione successiva se il bit che stavamo valutando fosse impostato a 1 invece che a 0.

CLRF

Questa istruzione aggiusterebbe tutti i dettagli di un registro a 0. La sintassi è:

CLRF
Lo abbiamo utilizzato in precedenza per impostare l'output delle porte su 0, applicando CLRF 85h. L'abbiamo inoltre impiegato per correggere le porte in modo da includere tutti i pin in uscita utilizzando CLRF
05h.

CLRW

Questo potrebbe essere simile all'istruzione CLRF, tranne che cancella il registro W. La sintassi è piuttosto semplice:

CLRW

RLF e RRF

Queste direzioni trasporterebbero un po 'in un registro un singolo slot a sinistra (RLF) o a destra (RRF) in un registro. Ad esempio, se avessimo bisogno di 00000001 e abbiamo utilizzato RLF, in quel caso potremmo possedere 00000010. A questo punto, cosa succede nel caso in cui ci sia 10000000 e abbiamo applicato l'istruzione RLF? Sicuramente, l'1 sarebbe posizionato nella bandiera di trasporto. Nel caso in cui abbiamo applicato ancora una volta l'istruzione RLF, l'1 ricomparirà all'inizio. Lo stesso avviene, tuttavia al contrario, per l'istruzione RRF. Il caso in questione qui sotto mostra questo per l'istruzione RLF, in cui possiamo vedere gli 8 bit di un registro, così come il flag di riporto:

C 87654321
0 00000001
RLF 0 00000010
RLF 0 00000100
RLF 0 00001000
RLF 0 00010000
RLF 0 00100000
RLF 0 01000000
RLF 0 10000000
RLF 1 00000000
RLF 0 00000001

Programma di esempio

Vedremo ora un codice di esempio che si può compilare e guidare. Genererebbe una luce di sequenza che inizia a PortA bit 0, andando a PortB bit 8 e
poi tornando.
Collegare i LED a ciascuno dei pin della porta. Avremo un po 'di bit
procedure indicate in questo tutorial.

TIME EQU 9FH Variabile per il delay loop.
PORTB EQU 06H Indirizzo della porta B.
TRISB EQU 86H Porta B Indirizzo Tristate.
PORTA EQU 05H Indirizzo porta A.
TRISA EQU 85H Porta A Indirizzo Tristate.
STATUS EQU 03H Selezione pagina registro.
COUNT1 EQU 0CH Registro loop.
COUNT2 EQU 0DH Registro loop.

STATO BSF, 5 Vai a pagina 1
MOVLW 00H e configurazione
MOVWF TRISB entrambe le porte A e B
MOVLW 00H in uscita,
MOVWF TRISA quindi torna a
STATO BCF, 5 pagina 0.
MOVLW 00H Cancella porta A.
MOVWF PORTA

Inizio del programma principale

RUNMOVLW
01H Imposta il primo bitMOVWF
PORTB su Port B.CALL
RITARDO Aspetta un po 'CHIAMATA
RITARDO
Spostare la punta sulla porta B a sinistra, quindi mettere in pausa.RLF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRLF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRLF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRLF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRLF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRLF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRLF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRLF
PORTB, 1 Sposta la punta nel flag di riporto
Ora spostati sulla porta A e sposta il bit a sinistra.RLF
PORTA, 1 Sposta il bit dal flag zero a PortACALL
DELAYCALL DELAYRLF
PORTA,1CALL
DELAYCALL
DELAYRLF
PORTA,1CALL
DELAYCALL
DELAYRLF
PORTA,1CALL
DELAYCALL
RITARDO
Riportare la punta sulla porta ARRF
PORTA,1CALL
DELAYCALL
DELAYRRF
PORTA,1CALL
DELAYCALL
DELAYRRF
PORTA,1CALL
DELAYCALL
DELAYRRF
PORTA, 1 Questo sposta il bit nel flag di zero Ora sposta il bit
torna su Port BRRF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRRF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRRF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRRF
PORTB, 1 CHIAMATA
DELAYCALL DELAYRRF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRRF
PORTB, 1 CHIAMATA
DELAYCALL
DELAYRRF
PORTB, 1 CHIAMATA
DELAYCALL
RITARDO Ora siamo tornati al punto di partenza, GOTO
RUN andiamo di nuovo.

Esiste una grande opzione nel set di addestramento che consente di utilizzare una tabella di dati.

Una tabella dati è solo un elenco di citazioni di dati, in cui tutto viene esaminato sulla base di alcune considerazioni.
Ad esempio, potresti avere un circuito che utilizza un PIC che conta la quantità di istanze in cui un pin di ingresso diventa alto in 1 secondo. Successivamente è possibile visualizzare il numero su un display a 7 segmenti.

Non appena è stato avviato il cronometraggio, il PIC inizia a contare il numero di volte in cui il pin va alto. Dopo 1 secondo visita la tabella e guarda i dati deve visualizzare sul display il numero che simboleggia il numero di situazioni in cui il pin è stato elevato. Questo può essere utile, poiché non determiniamo quale potrebbe essere la cifra finché il PIC non ha completato la sua stima.

Utilizzando una tabella, siamo in grado di consentire al PIC di determinare quale figura rappresentare. A questo punto, prima di continuare a mostrarti come funziona la tabella dati, potrei doverti dire che il PIC mantiene il percorso di dove si trova nel programma mentre il programma è in funzione.

Facilita per coloro che hanno eseguito determinate programmazioni in BASIC. Altrimenti, non essere ansioso, potresti voler continuare a conoscere la teoria. Immagina che ci sia un programma BASIC simile a quello presentato di seguito:

10 ANNI K = 0
11 K = K + 1
12 SE K> 10 POI ANDARE 20 ALTRIMENTI ANDARE 11
20 STAMPA K
21 END

Il programma inizia alla riga 10. Non appena K è programmato su 0, avanza alla riga 11. Dopo aver incluso da 1 a K, procederemo alla riga 12.

A questo punto potremmo essere curiosi se K è maggiore di 10. In tal caso, andiamo alla riga 20, oppure torniamo alla riga 11.

La riga 20 documenta la K e la riga 21 conclude il programma. BASIC utilizza le statistiche di linea per aiutare il programmatore a tenere traccia della posizione dei problemi, poiché le etichette non sono autorizzate. Il PIC utilizza le etichette per fuggire tra le destinazioni - o può davvero?

Utilizziamo le etichette per assicurarci di essere consapevoli di dove si trovano i problemi, nonché per assicurarci di essere in grado di informare il PIC in modo semplice su dove cercare.

Ciò che accade esattamente è che il PIC si avvale di un contatore di linea interna chiamato Program Counter. Il contatore del programma (abbreviato in PC) traccia della destinazione della memoria in cui si trova l'istruzione presente.

Ogni volta che informiamo il PIC di visitare un'etichetta selezionata, capisce il punto di memoria e quindi aumenta il PC finché non vede quella destinazione di memoria. Questo è esattamente lo stesso metodo con cui controlliamo il programma BASIC sopra. Di seguito è riportato un segmento di codice, con gli spazi di memoria, o gli elementi del PC, accanto a ogni istruzione:

Istruzioni per PC 0000 movlw 03
0001 movwf 0C
0002 Loop decfsc 0C
0003 goto Loop
0004 end

Nella dimostrazione sopra, abbiamo fissato il PC a 0000. Su questo abbiamo l'istruzione movlw 03. Quando il PIC ha implementato questi dati, incrementa il PC in modo che l'istruzione successiva venga scansionata. A questo punto il PIC visualizza movwf 0C. Il PC è nuovamente incrementato.

Ora il PIC studia decfsc 0C. Nel caso in cui i dettagli di 0C non siano 0, in quel caso il PC viene incrementato di 1, così come la seguente istruzione, goto Loop, informa il PC di tornare alla posizione 0003, che è detto Loop. Nel caso in cui i dettagli di 0C siano 0, si consiglia al PC di incrementare di 2, omettere semplicemente l'istruzione successiva.

Comprensione delle tabelle dati

Questo pone il PC nella posizione 0004, in cui termina il programma. Le destinazioni sono fissate dall'assemblatore, e in genere non dovremmo preoccuparci di ciò che il PC sta realizzando. Fino a quando, troviamo la necessità di tenerlo sotto controllo proprio come facciamo quando utilizziamo le tabelle di dati. Il modo più conveniente per descrivere il funzionamento di una tabella dati è iniziare con un'illustrazione.

PC equ 02
movlw 03
tabella delle chiamate
:
tavolo addwf PC
retlw 01
retlw 02
retlw 03
retlw 04
retlw 05
retlw 06
retlw 07
ritorno

L'istruzione iniziale sta assegnando all'etichetta PC l'indirizzo del Program Counter (02h). Saremo subito dopo aver inserito il valore di 03h nel registro w. Dopodiché comunichiamo al tavolo. La prima riga nella tabella della subroutine aumenta i dettagli del registro W (03h) al contatore del programma.

Questo fa sì che il contatore del programma aumenti di 3 o, per dirla in modo diverso, stimola il contatore del programma a procedere verso il basso di 3 righe. Mentre il contatore arriva 3 righe più in basso, il PIC riconosce l'istruzione retlw. Questo comando invia il valore che lo segue nel registro W, dopodiché ritorna dalla subroutine. RETLW significa fondamentalmente Return, Literal to W.

Vedere Ho inserito una virgola dopo la parola Return. Dato che siamo in una subroutine, abbiamo bisogno di un'istruzione Return per farla apparire. Quindi il RET nell'istruzione. Dopo l'istruzione RETLW è un numero, e questo è esattamente ciò che viene inserito nel registro W.

In questo caso è la figura 3. Potremmo designare qualsiasi quantità nel registro W, fintanto che questa figura è combinata con il contatore del programma nella subroutine della tabella, scopriremo un'istruzione retlw. Nell'illustrazione sopra, ciò implica che siamo in grado di possedere un numero qualsiasi da 1 a 7. Nel caso in cui procediamo oltre la subroutine, potremmo essere in grado di completare l'esecuzione di una sezione aggiuntiva del programma. Per questo motivo, di solito è una mossa intelligente posizionare la tabella dati esattamente verso la fine del programma PIC, quindi se superiamo in quel caso arriveremo comunque alla conclusione del programma.

L'argomento delle interruzioni potrebbe essere il più lungo e il più difficile da affrontare.

Non è possibile trovare alcun metodo semplice per dettagliare le interruzioni, tuttavia con un po 'di fortuna verso la fine di questa parte potresti essere in grado di applicare le interruzioni ai tuoi programmi.
Abbiamo separato la sezione in 2 fasi. Questo per abilitare la separazione dell'argomento in sezioni, anche per fornire un pratico plit up per una facile comprensione.

Cos'è esattamente un'interruzione? Sicuramente, come indica il termine, un interrupt è una tecnica o un segnale che impedisce a un microprocessore / microcontrollore di qualunque cosa stia eseguendo che potrebbe accadere qualcosa di diverso.

Consentitemi di darvi un'illustrazione quotidiana. Pensa di rilassarti a casa tua, conversando con un'altra persona. All'improvviso il telefono suona.

Smetti di parlare e prendi il telefono per parlare con il chiamante. Una volta che hai avuto la tua interazione telefonica, decidi di tornare a conversare con la persona prima che squilli il telefono. È possibile considerare la routine principale mentre si parla con qualcuno, lo squillo del telefono interrompe la conversazione e l'interruzione della routine è il metodo per parlare al telefono.

Mentre la discussione telefonica giunge al termine, torni alla tua routine principale di chat. Questa illustrazione è esattamente il modo in cui un processore interrompe l'azione.

Il programma principale è in funzione, svolgendo determinate funzioni in un circuito, tuttavia quando si verifica un'interruzione il programma principale si interrompe mentre viene eseguita una routine diversa. termina la routine, il processore torna alla routine primaria proprio come prima.

Comprensione degli interrupt

Il PIC possiede 4 sorgenti di interrupt. Potrebbero essere suddivisi in un paio di gruppi. Due sono sorgenti di interruzioni che possono essere utilizzate esternamente al PIC, mentre le altre due sono processi interni. Permettetemi di chiarire qui i due tipi esterni. Gli altri due verranno descritti in diversi tutorial una volta arrivati ​​ai timer e alla memorizzazione dei dati.

Se controlli il pin-out del PIC, noterai che il pin 6 è RB0 / INT. A questo punto, RB0 è chiaramente il bit 0 della porta B. L'INT rappresenta che potrebbe anche essere configurato come un pin di interrupt esterno. Inoltre, i pin da 4 a 7 della porta B (pin da 10 a 13) possono essere utilizzati anche per gli interrupt. Prima di poter utilizzare l'INT o un altro pin della porta B, è necessario eseguire due attività. Per prima cosa dobbiamo informare il PIC che utilizzeremo gli interrupt.

Successivamente, dobbiamo designare quale pin della porta B utilizzeremo come interrupt piuttosto che come pin I / O. All'interno del PIC puoi trovare un registro noto come INTCON, ed è all'indirizzo 0Bh. In questo registro scoprirai 8 bit che possono essere abilitati o disabilitati. Il bit 7 di INTCON è noto come GIE. Questo è il Global Interrngupt Enable. Fissando questo a 1 si informa il PIC che utilizzeremo un interrupt.

Il bit 4 di INTCON è noto come INTE, INTerrupt Enable. Mettendo questo bit a 1 si comunica al PIC che RB0 sarà un pin di interrupt. La configurazione del bit 3, chiamato RBIE, informa il PIc che utilizzeremo i bit della porta B da 4 a 7. A questo punto il PIC capisce quando questo pin può essere alto o basso, deve fermare ciò che sta eseguendo e procedere con un interrupt routine. A questo punto, dobbiamo informare il PIC se l'interrupt sarà probabilmente sul fronte ascendente (da 0V a + 5V) o sul fronte di discesa (da + 5V a 0V) del segnale.

In parole povere, desideriamo che il PIC interrompa ogni volta che il segnale si sposta da basso ad alto, o da alto a basso. Per delinquenza, questo può essere stabilito per essere posizionato sul fronte di salita.

Il 'trigger' del fronte è programmato in un registro aggiuntivo chiamato registro OPTION, all'indirizzo 81h. Il bit di cui siamo entusiasti è il bit 6, spesso indicato come INTEDG.

Impostando questo valore su 1, il PIC si interrompe sul bordo di montaggio (stato predefinito) e impostandolo su 0 si stimola il PIC a interrompere il bordo di scorrimento. Se desideri che il PIC si attivi sul fronte di salita, di certo non devi fare nulla per questo bit.

A questo punto, purtroppo, il registro delle opzioni è nel banco 1, il che significa che ci divertiamo a modificare dal banco 0 al banco 1, impostare il bit nel registro delle opzioni, dopodiché tornare al banco 0. La chiave qui è di completare ogni bit del banco 1 si registra in un unico colpo, ad esempio stabilendo i pin della porta, dopodiché torna al banco 0 se hai finito.

Bene, di conseguenza abbiamo notificato al PIC quale pin sarà probabilmente l'interrupt, e dove deve innescare il bordo, cosa succede nel programma e nel PIC ogni volta che si verifica l'interrupt? Succedono un paio di cose. Innanzitutto, è prevista una 'bandiera'.

Questo informa il processore interno del PIC che si è verificato un interrupt. Successivamente, il contatore del programma (di cui ho parlato nel tutorial precedente) punta a un indirizzo specifico all'interno del PIC. Esaminiamo rapidamente tutti questi individualmente. Flag di interrupt Nel nostro registro INTCON, il bit 1 è il flag di interrupt, chiamato INTF. A questo punto, ogni volta che si verifica un'interruzione, questo flag sarà probabilmente fissato a 1.

Quando non c'è un'interruzione, la bandiera viene posta a 0. Inoltre, tutto ciò si ottiene. A questo punto potresti pensare 'qual è il punto?' Sicuramente, anche se questo flag è programmato su 1, il PIC non è in grado di reagire e non reagirà a un'altra interruzione. Pertanto, diciamo che produciamo un'interruzione. Il flag sarà probabilmente fissato a 1 e il PIC potrebbe andare alla nostra routine per lavorare sull'interrupt.

Quando questo flag non era fissato a 1, e al PIC era consentito continuare a rispondere all'interruzione, allora pulsare continuamente il pin poteva far tornare il PIC all'inizio della nostra routine di interruzione e non completarla in alcun modo. Tornando alla mia illustrazione del telefono, è simile a sollevare il telefono, e subito dopo aver discusso inizia a squillare di nuovo poiché un'altra persona desidera parlare con te.

Si consiglia di completare un dialogo, quindi riprendere il telefono per parlare con la persona successiva. Puoi trovare un piccolo problema con questa bandiera. Anche se il PIC imposta rapidamente questo flag su 1, non lo imposta di nuovo su 0! Quell'attività deve essere esercitata dal programmatore, cioè tu. Questo può essere realizzato senza sforzo, poiché ne sono certo presumo, e deve essere ottenuto dopo che il PIC ha eseguito la routine di interrupt.

Posizione della memoria Ogni volta che si accende inizialmente il PIC, o nel caso in cui esista un ripristino, il contatore del programma punta all'indirizzo 0000h, che potrebbe essere immediatamente all'inizio della memoria del programma. Ma, in caso di interruzione, il contatore del programma indica l'indirizzo 0004h.

Pertanto, mentre stiamo componendo il nostro programma che avrà interrupt, dobbiamo prima informare il PIC di saltare sull'indirizzo 0004h e mantenere la routine di interrupt che inizia all'indirizzo 0004h discreta dal resto del programma.

Questo può essere senza problemi da eseguire. Inizialmente, iniziamo il nostro programma con un comando noto come ORG. Questo comando indica Origin o start. Ci atteniamo con un indirizzo. Poiché il PIC inizia all'indirizzo 0000h, digitiamo ORG 0000h. Dopodiché dobbiamo bypassare l'indirizzo 0004h. Otteniamo ciò inserendo un'istruzione GOTO, accompagnata da un'etichetta che suggerisce il nostro programma principale.

Dopodiché aderiamo a questo comando GOTO con un altro ORG, questo momento con l'indirizzo 0004h. Sarà dopo questo comando che inseriremo la nostra routine di interrupt. A questo punto, potremmo essere in grado di digitare la nostra routine di interrupt direttamente dopo il secondo comando ORG, oppure possiamo posizionare un'istruzione GOTO che punta alla routine di interrupt.

È veramente correlato all'opzione da parte tua. Per informare il PIC che offre è arrivato alla conclusione della routine di interrupt dobbiamo posizionare il comando RTFIE verso la fine della routine. Questo comando indica il ritorno dalla routine di interrupt. Mentre il PIC lo nota, il contatore del programma indica la posizione finale in cui si trovava il PIC prima che si verificasse l'interruzione. Abbiamo stabilito di seguito una breve sezione di codice per visualizzare quanto sopra:

Ci sono un paio di cose che dovresti essere informato quando utilizzi gli interrupt. L'iniziale tende ad essere che se stai utilizzando lo stesso registro nel tuo programma principale e nella routine di interruzione, tieni presente che i dettagli del registro molto probabilmente cambieranno quando si verifica l'interruzione.

Ad esempio, utilizziamo il registro w per inoltrare i dati al programma principale della porta A, quindi puoi anche utilizzare il registro w nella routine di interrupt per spostare i dati da una destinazione all'altra.

Nel caso in cui non si sia prudenti, il registro w includerebbe l'ultimo valore ricevuto mentre era nella routine di interrupt, quindi quando torni dall'interruzione questa informazione verrà consegnata alla Porta A invece che al valore che possedevi prima si è verificata l'interruzione.

Il mezzo per aggirare questo è salvare momentaneamente i dettagli del registro w prima di utilizzarlo ancora una volta nella routine di interrupt. Il secondo è il fatto che puoi trovare un ritardo tra il momento in cui si verifica un'interruzione e quando può verificarsi quella successiva. Mentre capisci, il PIC possiede un orologio esterno, che potrebbe essere un cristallo o potrebbe essere un combo resistore-condensatore.

Non importa quale sia la frequenza di questo clock, il PIC lo divide per 4, dopodiché lo utilizza per la sua temporizzazione interna. Ad esempio, nel caso in cui tu abbia un cristallo da 4MHz collegato al tuo PIC, in quel caso il PIC eseguirà le istruzioni a 1MHz. Questo tempismo interno è noto come ciclo di istruzioni. A questo punto, la scheda tecnica afferma (senza dubbio in caratteri minuscoli) che è necessario abilitare da 3 a 4 cicli di istruzioni tra gli interrupt.

Il mio sarebbe abilitare 4 round. Il motivo dietro il ritardo è che il PIC richiede tempo per saltare all'indirizzo di interrupt, il flag e tornare indietro dalla routine di interrupt. Pertanto, tienilo a mente se lavori con un circuito alternativo per attivare un interrupt per il PIC.

A questo punto, un punto da considerare è il fatto che si utilizzano i bit da 4 a 7 della porta B come interruzione. Non è possibile scegliere pin specifici sulla porta B per funzionare come un interrupt.

Pertanto, nel caso in cui consenti questi pin, probabilmente potrebbero essere tutti disponibili. Pertanto, ad esempio, non puoi semplicemente avere i bit 4 e 5 - i bit 6 e 7 saranno probabilmente abilitati allo stesso tempo. Qual è esattamente lo scopo di ottenere quattro bit per rappresentare un interrupt? Sicuramente, potresti avere un circuito collegato al PIC, nel caso in cui qualcuno di quattro linee vada in alto, in quel caso questo potrebbe essere un problema che richiedi al PIC di influenzare immediatamente.

Un esempio di ciò potrebbe essere un allarme di sicurezza domestica, in cui quattro sensori sono collegati ai pin da 4 a 7 della porta B. Qualsiasi sensore specifico può richiedere al PIC di attivare un allarme e la routine di segnalazione di allarme è la routine di interruzione. Ciò risparmia il controllo costante delle porte e consente al PIC di continuare con questioni diverse. Nel prossimo tutorial, comporremo un programma per gestire un interrupt.

Abbiamo affrontato molte basi nell'ultimo tutorial, quindi sento che è giunto il momento di comporre il nostro primo programma.

Il programma che scriveremo conterà il numero di volte in cui accendiamo un interruttore, quindi mostrerà il numero.

Il programma conterà da 0 a 9, visualizzabile su 4 LED in forma binaria, insieme all'ingresso o all'interrupt sarà probabilmente su RB0.

La prima cosa che dobbiamo condurre è informare il PIC di saltare l'indirizzo a cui punta il Program Counter ogni volta che si verifica un'interruzione.

Noterai che stiamo impiegando un metodo unico per mostrare i numeri esadecimali. Prima che mi accadesse applica F9h in cui h indicava esadecimale. Potremmo scrivere questo come 0xF9, che è la struttura che utilizzeremo d'ora in poi.

Ora dobbiamo dire al PIC che useremo gli interrupt e useremo il pin 6 RB0 come pin di interrupt:

bsf INTCON, 7GIE - Abilitazione interrupt globale (1 = abilitazione)
bsf INTCON, 4INTE - Abilitazione interrupt RB0 (1 = abilitazione)
Ho intenzione di cancellare il flag di interruzione per ogni evenienza (non mi fido mai di nulla!)
bcf INTCON, 1INTF - Cancella bit flag per ogni evenienza

Attualmente dobbiamo stabilire le nostre 2 porte. Tieni presente che poiché ora stiamo utilizzando RB0 come pin di interrupt, questo deve essere stabilito come input:

Useremo una variabile chiamata COUNT per memorizzare il numero di conteggi di switch. Potremmo semplicemente aumentare il valore sulla porta A, ma vedrai perché sto usando una variabile quando scriviamo la nostra routine di interrupt.

Pertanto, il nostro programma principale è composto, ea questo punto dobbiamo informare il PIC come procedere ogni volta che si verifica un interrupt. In questo esempio, il nostro interrupt sarà probabilmente lo switch. Proprio quello che vorremmo che il PIC fosse uno per il COUNT regolabile ogni volta che l'interruttore è limitato.

Tuttavia, desideriamo solo mostrare quante volte l'interruttore si spegne da 0 a 9. Sopra, ho affermato che potremmo semplicemente aumentare il valore sulla porta A ogni volta che c'è un interrupt. Tuttavia, la porta A ha 5 bit, nel caso in cui abbiamo semplicemente incrementato la porta, avremo il conteggio più alto di 31. Ci sono un paio di spiegazioni per cui ho scelto di non passare a 31.

Inizialmente utilizzeremo uno schermo a 7 segmenti, che al massimo potrà andare solo da 0 a 15 (da 0 a F in esadecimale). Successivamente, desidero inoltre mostrarvi alcuni dei comandi aritmetici in cui vi siete imbattuti nelle ultime lezioni.

Quindi continueremo con la nostra routine di interruzione. Attualmente la prima cosa che dobbiamo compiere è memorizzare brevemente i dettagli del nostro registro w, poiché lo abbiamo applicato per spostare il contenuto di COUNT in PORTA. Nel caso in cui non lo salviamo, in quel caso potremmo essere in grado di fornire un numero completamente diverso a causa della nostra aritmetica. Quindi eseguiamo prima questo:

A questo punto capiamo se il valore di COUNT è 9 o più. Quello che dobbiamo fare ora è se COUNT è più di 9, rimettilo a 0, oppure torna al programma principale per assicurarci di essere in grado di consegnarlo alla porta A. Il comando BTFSS poiché hai capito sarebbe il successivo
istruzione nel caso in cui sia programmato il carry flag, ad esempio COUNT = 10:

L'unica cosa che resta da fare ora è inserire collettivamente e determinare i valori delle nostre costanti, che siamo in grado di eseguire proprio all'inizio del nostro programma.

Ogni volta che si attiva l'interruttore, i LED conteranno in modo binario da 0000 a 1010 e poi di nuovo a 0000.

La figura seguente mostra lo schema elettrico compatibile con il codice sopra spiegato. È interessante notare che il condensatore di temporizzazione è stato incluso nel progetto. Questo è un simpatico stratagemma attraverso il quale ottieni la libertà di evitare l'inclusione del condensatore nel caso in cui non ne avessi con te durante quel periodo.

Qui la capacità entra in gioco tramite la capacità parassita attraverso il pin dell'oscillatore e la massa.
Ovviamente potrebbe non sembrare un modo molto intelligente per evitare praticamente un condensatore poiché il valore di dispersione potrebbe variare con diverse condizioni date.

Un'altra sezione che può essere vista nel circuito è la rete di denuncia attraverso lo switch. Ciò previene le interferenze durante la commutazione meccanica e impedisce al PIC di confondersi se la commutazione era un singolo interruttore o più interruttori.




Precedente: Circuito timer motore bidirezionale programmabile Avanti: Come funzionano i circuiti buck-boost