ESERCITAZIONE # 2
USO dei PORT come uscite digitali
Uno dei più comuni impieghi dei pin di un embedded è il comando di un
carico in uscita (LED, relay, ecc). Questo richiede che il programma provveda,
per prima cosa, a configurare quel pin come uscita.
Questo richiede una azione sul registro di direzione del port (TRIS)
a cui il pin appartiene, in modo da dirigerlo come uscita.
Sfortunatamente, anche un banale uso dei PORT di I/O per accendere un LED
negli embedded richiede una certa struttura, che, a prima vista vista, sembra
molto ampia.
Questo è dovuto semplicemente al fatto che ogni pin può svolgere numerose
funzioni,
tutte programmabili. E non è detto che quella di uscita digitale sia quella
stabilita dal default all' accensione.
In effetti, la politica del costruttore è quella di portare il chip, dopo un
reset, in una condizione "neutra" in cui si da la preferenza ad una
situazione di consumo minimo. E questo privilegia, ad esempio, la configurazione
dei port come analogici piuttosto che digitali.
Quindi, volendo utilizzare uno o più pin con funzione di I/O digitali può
essere necessario modificare i default con un certo numero di istruzioni.
Non tutti i port possono assumere funzioni analogiche; nella famiglia 18 di
solito questo compito è assegnato ai PORTA, B ed E, mentre il PORTC e D ne sono
esclusi. Quindi, la programmazione addizionale riguarderà essenzialmente le
prime.
In ogni caso, essendo tutti port configurati come ingressi dal default del reset,
per tutti i pin che si desidera utilizzare come uscita occorre modificare il
registro di direzione relativo (TRISx).
Il nostro esercizio prevede di collegare un LED al bit 0 di ogni port (RA0,
RB0, RC0). I LED sono posti tra il pin e il gnd (Vss, massa) con la
rispettiva resistenza in serie e quindi saranno accesi quando il pin,
configurato come uscita, sarà portato a livello 1.
L' esercizio ha lo scopo di verificare in pratica il modo di assegnazione di
una funzione GPIO di uscita ad un pin di ogni port.
Ovviamente, dovendo visualizzare il risultato, il progetto imposta Pickit3 come
debugger e viene utilizzata la Uniboard, direttamente alimentata a 5V dal Pickit.
Si dovranno semplicemente collegare i pin PA0, PB0 e PC0 ognuno ad un dei LED
della scheda.
Il Pickit è inserito direttamente nella spina ICSP/ICD e permette un debug passo passo delle
istruzioni.
Ovviamente sarà possibile utilizzare Pickit2 senza variazioni se non la diversa impostazione nell'
ambiente MPLAB; oppure anche REAL ICE o ICD, sempre con il semplice cambio
nel setup di MPLAB, tenendo presente che non tutti i tools sono
in grado di alimentare l' hardaware.
Inoltre è sempre possibile utilizzare SIM senza alcun hardware o
debugger collegato.
|
Una descrizione particolareggiata delle funzioni dei PORT è consultabile
qui.
Per chi non avesse chiare le connessioni, qui trova una pagina dedicata.
L' esercizio richiede le seguenti risorse:
- MPLAB IDE installato
- Pickit3 (o Pickit2)
- 28-40pin UniBoard con PIC18F2321
0 4321 (o 2221 o 4221 o altro hardware similare)
- tre cavetti jumper da 14-15 cm
Il listato sorgente è una estensione di quello già visto nell'
Esercizo 1, di cui conserva la struttura del template, aggiungendo gli elementi
necessari al nuovo lavoro.
Da un punto di vista strutturale il programma agisce in questo modo:
- Azzeramento dei latch dei port. Questa operazione preliminare serve per pre
determinare il livello che i pin assumeranno nel momento in cui
saranno configurati come uscite.
- Disabilitazione delle funzioni analogiche da tutti i PORT A e B agendo sul
registro ADCON1.
- Disabilitazione dei comparatori analogici presenti sui PORTA agendo sul
registro COMCON.
- Imposizione della direzione uscita per i bit 0 dei PORT A, B, C agendo sui
rispettivi registri TRIS.
- Attivazione dei led portando a livello 1 i relativi bit. L' azione viene
effettuata sui registri LAT, dato che i PIC18 consentono un accesso separato
a questi SFR.
- Stop del micro bloccandolo in un loop infinito.
Il punto 6 è necessario in quanto il programma non è un loop chiuso, ma,
una volta accesi i LED, ha terminato la sua funzione. Però non è possibile
bloccare il processore se non in due modi:
- mettendolo in condizione di SLEEP, ovvero bloccando il clock principale
- impegnandolo in un loop infinito
La funzione SLEEP e le sue possibilità saranno oggetto di altre
esercitazioni dedicate a questo.
Ora ci limitiamo alla seconda soluzione, ovvero chiudiamo il programma
costringendo il processore a circolare su una istruzione che si richiude su se
stessa.
Questa soluzione, apparentemente strana, è dovuta al fatto che, altrimenti,
terminate quelle che sono per noi le operazioni richieste al processore, il
Program Counter continuerebbe comunque a scandire locazioni di memoria
programma, mentre la logica di decodifica cercherebbe di eseguire come
istruzioni i codici casuali in esse. Però, essendo queste celle della
Flash non inizializzata, potrebbero verificarsi situazioni imprevedibili.
Dunque, "stoppiamo" il processore costringendolo a fare come il cane
che corre in circolo dietro alla sua coda, soluzione poco elegante, ma efficace.
Vediamo il listato nei dettagli.
Come inizio, è sempre presente una testata di descrizione del programma e delle sue funzioni.
;*****************************************************************
; Esercitazioni PIC18 - Esercitazione # 2
;*****************************************************************
; Esempio di uso dei PORT
; Author : afg
; Version : E18_2_00
; Date : 09/10/2010
;-----------------------------------------------------------------
; Descrizione: Il sorgente imposta alcuni pin dei PORTA,B,C,D
; come uscite e accende i relativi LED collegati.
;-----------------------------------------------------------------
; Note : Processore PIC18F2321
; Oscillatore interno a 1 MHz (clock interno 250 us)
; senza la necessità di componenti esterni
; Debug con MPLAB IDE e PickKit3
; Previsto per funzionare con tutti gli enhanced
;*****************************************************************
|
Inizia ora il vero e proprio sorgente, con gli elementi di definizione del
processore.
LIST P=18F2321 ; Utilizziamo il PIC18F2321
radix dec
; con base decimale per le operazioni
; matematiche
#include "P18F2321.INC"
; Include l' header file
; questo header è fornito dallo stesso Assembler e non richiede
; alcun file addizionale
|
Segue quindi la configurazione del processore.
Qui è utilizzata una configurazione minima. I commenti chiariscono le funzioni
configurate.
;---------------------------------------------------------------------
; Configurazione minima dei debug del processore
;
; Background debugger enabled su RB6 e RB7 per il debug con il
; Pickit o altro, attraverso ICSP/ICD
CONFIG DEBUG = ON
; Single-Supply ICSP disabled
CONFIG LVP = OFF
; Uso dell' oscillatore interno, port su RA7 e FOSC/4 su RA6
CONFIG OSC = INTIO1
; PWRT disabled per il debug
CONFIG PWRT = OFF
; Brown-out in hardware only
CONFIG BOR = ON
; Soglia BOR 4.2V
CONFIG BORV = 1
; Funzione del pin MCLR abilitata
CONFIG MCLRE = ON
; WDT disabilitato
CONFIG WDT = OFF |
Assegniamo un paio di locazioni in RAM con la direttiva CBLOCK/ENDC.
Nel caso di questo programma, non hanno alcuna funzione. Serviranno nelle
esercitazioni successive.
;----------------------------------------------------------------------
;Assegna registri di memoria RAM
CBLOCK 0x00 ; blocco di RAM a partire da 0x00
d1 ; riserva 2 bytes per un contatore
d2
ENDC ; fine blocco RAM
|
Nell' area degli Equates inseriamo alcune definizioni che ci serviranno
durante il programma.
Inizialmente definiamo una maschera che, applicata al registro di direzione
TRISx programmerà il bit 0 come uscita.
Poi, è pratico assegnare delle label ai LED in modo tale da richiamarle
successivamente ed avre una immediata indicazione di cosa fa il programma in
quel dato punto.
Da notare che utilizziamo il registro LATx al posto di POPRTx
;----------------------------------------------------------------------
; Equates
;
; Maschera per impostare il registro di direzione del pin 0 di un port
; come uscita
port0_out equ
b'11111110'
; assegnazioni per i LED
#define
LEDA
LATA,0 ; LED collegato a RA0
#define
LEDB
LATB,0 ; LED collegato a RB0
#define
LEDC
LATC,0 ; LED collegato a RC0
|
Ecco il "programma" vero e proprio, con ampi commenti che
descrivono le funzioni svolte da ogni riga:
;=====================================================================
; Inizio programma
; Il programma:
; - imposta i pin RA0, RB0, RC0 come uscite
; - porta questi pin a livello alto
; se ad essi c'è collegato un LED verso massa, esso verrà acceso
ORG 0x00
; Programma inizia a 0x00 - vettore del reset
Start nop
; dummy - linea utile solo ai fini del debug
; inizializza a 0 i latch di uscita dei PORT
; questo serve per avere subito a livello 0 i pin che saranno
programmati come uscite
; non ha effetto sui pin programmati come ingressi.
clrf LATA
clrf LATB
clrf LATC
; inizializza PORTA
; La prima operazione è quella di disabilitare la funzione di input
; analogico che i pin assumono dopo il reset
movlw 0x0F
; disabilita tutti gli ingressi analogici
movwf ADCON1
; poi, disabilitiamo i compratori
movlw 0x07
; disabilita i comparatori
movwf CMCON
; dal PORTA
; ora possiamo applicare la maschera predefinita che obbliga
; PORTA0 = out e tutti gli altri in
movlw port0_out
movwf TRISA
; inizializza PORTB
; le precedenti linee movlw 0x0F e movwf ADCON1
hanno escluso le funzioni
; analogiche anche da PORTB
movwf TRISB
; inizializza PORTC, che non richiede particolare attenzione
movwf TRISC
; accende i LED
bsf
LEDA
bsf
LEDB
bsf
LEDC
; il programma ha eseguito il suo compito -
blocchiamo il processore
; in un loop infinito
lock goto lock
; loop di blocco
;=====================================================================
; Subroutines
; area vuota
;********************************************************************
; Direttiva di fine sorgente
END
|
La fine del sorgente è determinata come al solito dalla direttiva END.
Da notare che il programma vero e proprio, invece, termina impegnando la CPU
in un loop infinito. Questo è necessario altrimenti il processore proseguirebbe
ad eseguire i codici casuali contenuti nella memoria programma, con la
possibilità di creare situazioni imprevedibili.
Avviando lo step-by-step potremo seguire il flusso delle istruzioni ed
osservare l' accensione di LED dopo le relative istruzioni.
Se si incontrano errori nella compilazione è opportuno verificarli con la
lista di descrizione degli errori e correggere dove si è sbagliato.
Il file compresso di questa esercitazione è scaricabile dall'
area di download.
|