Pic 16F84

Stato
Discussione chiusa ad ulteriori risposte.

tyldan

Utente Silver
4 Marzo 2008
0
0
1
58
Posto qui degli appunti che mi sono risultati veramente utili Durante la costruzione di un robot con il microcontrollore Pic16F84.


Il PIC16F84 è un microcontrollore a 8-bit dotato di due porte di I/O digitali, una da 5 bit e una da 8 bit.

pinoutxj2.jpg


La memoria all'interno del PIC16F84 è organizzata in questo modo.

memoriait0.jpg


è divisa in due banchi:
• BANK0 è utilizzato per le operazioni di I/O vere
e proprie
• BANK1 è utilizzato per controllare le modalità di
funzionamento delle porte
Tutta la memoria è divisa in registri da 8 bit.

Le zone di memoria da 0Ch a 4Fh sono mappate
su quelle da 8Ch a CFh (perciò 0Ch e 8Ch
conterranno la stessa cosa), e sono lasciate a
disposizione dei dati utente.

Proviamo a capire come funziona con un esempio.

Vogliamo visualizzare un countdown da 9 a 0 su un
display a led 7 segmenti collegato alla porta B.
Segue il codice del programma

;led7dig.asm
;programma di countdown su un display a 7 segmenti
PROCESSOR 16F84
RADIX DEC
INCLUDE "P16F84.INC"
ORG 0x0C ;Riservo dello spazio per alcune variabili
CONTATORE RES 2 ;Contatore per un ciclo di ritardo
CIFRA RES 10 ;Cifre da mettere sul display
INDICE RES 1 ;Indice per puntare alle cifre
ORG 0x00


movlw 11000000B ;Memorizzo l'impostazione dei segmenti per
movwf CIFRA+0 ; visualizzare ogni cifra in delle locazioni
movlw 11111001B ; di memoria contigue, in modo da poterci
movwf CIFRA+1 ; accedere come con un array
movlw 10100100B
movwf CIFRA+2
movlw 10110000B
movwf CIFRA+3
movlw 10011001B
movwf CIFRA+4
movlw 10010010B
movwf CIFRA+5
movlw 10000010B
movwf CIFRA+6
movlw 11111000B
movwf CIFRA+7
movlw 10000000B
movwf CIFRA+8
movlw 10010000B
movwf CIFRA+9
bsf STATUS,RP0 ;Passo al bank 1
movlw 00000000B
movwf TRISB ;Imposto tutta la porta B come output
bcf STATUS,RP0 ;Ritorno al bank 0

INFINITO
movlw 0x9 ;punto l'indice sul 9
movwf INDICE

COUNTD
movlw 0x0E ;0x0E e' uno spiazzamento di memoria fisso
addwf INDICE,0 ; che corrisponde alla cifra 0
movwf FSR ;Carico l'indice in un puntatore
movf INDF,0 ;Metto nell'accumulatore la zona puntata
movwf PORTB ;Pongo sulla porta B il dato
call RITARDO ;zzzz....
decfsz INDICE,1 ;Decremento l'indice e salto l'istruzione
goto COUNTD ; successiva se questo è nullo
goto INFINITO ;Ricominciamo!

RITARDO
clrf CONTATORE
clrf CONTATORE+1

RLOOP
decfsz CONTATORE,1
goto RLOOP
decfsz CONTATORE+1,1
goto RLOOP
return
END

Analizziamo il programma:

Innanzitutto le parti che ho evidenziato in blu sono direttive al compilatore e non istruzioni vere
e proprie.

Sono importantissime le tabulazioni di inizio riga:

• Se inseriamo una tabulazione stiamo immettendo un istruzione;
• Se non inseriamo una tabulazione stiamo assegnando un etichetta.

PROCESSOR istruisce il compilatore sul tipo di CPU
RADIX stabilisce che dove non specificato diversamente i numeri sono in DECimale
INCLUDE copia il contenuto di un'altro file all'interno di un nostro programma, il file da noi
incluso ci permette di utilizzare etichette, ad esempio TRISB, al posto dell'indirizzo del registro
corrispondente.
ORG specifica che le direttive successive saranno organizzate in celle di memoria dalla 0x0C
(area dati).

Successivamente ci riportiamo all'area per il programma 0x00.

• movlw mette nell'accumulatore W un numero.
• movwf mette nel registro indicato da un indirizzo il contenuto di W
• bsf setta (mette a uno) un bit di un registro indicato.
• bcf resetta (mette a zero) un bit di un registro indicato.

Il display a 7 segmenti a mia disposizione è del tipo ad anodo comune, per cui i segmenti si accendono quando ricevono uno 0.
Ho collegato il display nel seguente modo:

displaygu5.jpg


Codice:
Bit           RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
Segmento      n/a  g   f   e   d   c   b   a
Memorizzo perciò la configurazione dei segmenti per le 10 cifre in altrettanti registri
di memoria.
Agendo sul bit RP0 del registro STATUS possiamo passare dal bank0 al bank1 e viceversa.
Ora passo al bank1 perchè devo impostare la porta B come uscita e non come ingresso.
Ogni bit della porta può essere configurato indipendentemente in una delle due direzioni.
Per stabilirlo carichiamo in TRISB un byte in cui ogni bit a 0 setta la corrispondente uscita come
output e ogni bit a 1 come input
Ad esempio, se caricassimo in TRISB 01001110 otterremmo
Codice:
Reg      RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0
Direz    OUT IN  OUT OUT  IN IN  IN  OUT
TRISB    0    1   0   0   1   1   1   0
Dopo aver configurato le porte torniamo al bank0.
A questo punto siamo pronti per creare il codice di countdown, facendo muovere un puntatore
da 9 a 0.
All'indice che abbiamo creato dobbiamo aggiungere uno spiazzamento. Questo sarà 0x0E, perchè la memoria delle variabili parte da 0x0C, ma le prime due celle le abbiamo
riservate per un contatore (vedi dopo), per cui le nostre cifre partono proprio da 0x0E.
Faccio questo con addwf INDICE,0; questa istruzione dice: aggiungi il contenuto
dell'accumulatore W al registro f=INDICE e metti il risultato nell'accumulatore (Il risultato
dell'operazione potrebbe altrimenti essere rimesso nel registro se dopo la virgola avessimo messo 1).
Ottenuto così l'indirizzo che contiene la cifra che ci interessa, lo mettiamo nel registro FSR, che
è un registro per l'indirizzamento indiretto. Infatti successivamente mettiamo INDF
nell'accumulatore. Tutte le volte che si legge INDF viene restituito il contenuto della cella il cui
indirizzo è memorizzato in FSR.
A questo punto possiamo semplicemente mettere l'accumulatore in uscita sulla porta B.

Ora creo un piccolo ritardo tramite una CALL a subroutine perchè altrimenti non vedrei scorrere
le cifre sul display; per fare questo conto 255 per 255 volte, in questo modo:
• metto zero in due variabili CONTATORE
• al primo decremento di test queste variabili diventano 0xFF e da lì in avanti continua il
decremento fino al raggiungimento dello 0.
Tool per l'assemblaggio e la scrittura:
Per assemblare il nostro programma utilizziamo MPASMWIN, distribuito dalla stessa
MICROCHIP, produttrice del PIC16F84.
MPASMWIN può girare su Linux tramite wine senza nessun accorgimento particolare.

Selezioniamo il nostro codice con il tasto "Browse..." e poi clicchiamo su "Assemble". Dopo
aver macinato un po', l'assemblatore mettera nella stessa directory del nostro programma altri
file con estensione .COD, .ERR, .LST e .HEX.
I più importanti sono:
• led7dig.ERR, che contiene eventuali errori di compilazione
• led7dig.HEX, che è il codice vero e proprio da passare al programmatore
Abbiamo quasi finito, non ci resta che programmare il PIC16F84 e inserirlo nel circuito.
Il programmatore che ho usato io si chiama PICALLW, reperibile su http://www.picallw.com e
anch'esso installabile su Linux tramite wine. Per poterlo eseguire correttamente è essenziale
avere il modulo del kernel chiamato ppdev.o, che permette a programmi in user-space di
accedere allea porta parallela. Di conseguenza modificherò le sezioni del mio file config di wine
in modo da includere:
Codice:
[parallelports]
"Lpt1" = "/dev/lp0"
[ppdev]
;; key: io-base of the emulated port
;; value : parport-device{,timeout}
;; timeout for auto closing an open device ( not yet implemented)
"378" = "/dev/parport0"
;"278" = "/dev/parport1"
;"3bc" = "/dev/parport2"
[ports]
"read" = "0x779,0x379,0x278-0x27a,0x280-0x2a0,0x378-0x37f"
"write" = "0x779,0x379,0x278-0x27a,0x280-0x2a0,0x378-0x37f"
Picallw in esecuzione con wine
L'hardware di programmazione è un kit parallelo della Asamicros, http://www.asamicros.com ,
che corrisponde a un "P16PRO 74LS05,6 – KIT96" nell voce Hardware setup di picallw.
Apriamo led7dig.HEX (tasto F2 o voce "Open Program"), e configuriamo l'oscillatore su XT
(quarzo) con il tasto F3. E' importante scegliere correttamente l'oscillatore del proprio hardware,
altrimenti il PIC16F84 non parte.
Infine programmiamo il pic con il tasto F4.
Spostiamo il PIC16F84 sulla development board ... connettiamo il display .... fatto! ora abbiamo
anche noi il conto alla rovescia come alla NASA!.
 
Avresti potuto postare anche parte del datasheet per far capire la piedinatura ma comunque Good ;)
 
Stato
Discussione chiusa ad ulteriori risposte.