PIC uControllers tutorial

Transcript

PIC uControllers tutorial
PIC uControllers tutorial
+ Mikrobasic® programming
Written by: Ulisse
[email protected]
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Indice:
Argomento trattato
• Paragrafo
- Approfondimento
Prima parte: microcontrollers
• Architettura dei microcontrollers PIC
• Clock
• Registri
• Porte di comunicazione
Seconda parte: Ambiente di sviluppo mikrobasic
• Creazione di progetti
• Flag (esempio per il PIC16F88)
• Struttura del programma
Terza parte: Fondamenti di programmazione in mikrobasic (dati)
• Dati
• Dichiarazione ed utilizzo dei tipi statici
• Array
- Buffer overflow
• Stringhe
• Records (strutture)
• Dichiarazione ed utilizzo dei tipi dinamici
Quarta parte: Operators & Simple Data Oriented Isntructions
• Operatori
• Operatori aritmetici
• Operatori di precedenza
• Operatori di bitwise
• Operatori di confronto
- FLAG di ZERO
- FLAG di SEGNO
• Lettura e scrittura dei dati da una porta di comunicazione
- Interfacciamento
Quinta parte: Strutture di controllo del flusso di un programma
• Selezione
- Primo progetto: Hardware key
• Case
• Iterazione
- secondo progetto: Led blink
• Ciclo a conteggio
• Funzioni
• Ricorsione
- Stack overflow
Sesta parte: Advenced Data Oriented Instructions and libraries
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
•
•
•
•
Serial communication and library
- RS232 to TTL
- MSCOMM32.ocx e controllo della porta seriale in Delphi
- Terzo progetto: Roulette
Main Math Library functions
Main String Library functions
Main Conversion library functions
Settima parte: interfacciamento, comunicazione
• Lettura dei dati analogici
- Interfacciamento (parte analogica)
• Scrittura dati verso display a 7 segmenti
• Scrittura dati su LCD Hitachi compatibili
• ENC28J60: PIC ed Ethernet
• Utilizzo di schedine SD ed MMC
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Microcontrollers…
Un microcontroller è un dispositivo che integra onboard un processore e della
memoria contenente il programma (firmware) che il processore deve eseguire.
La miniaturizzaizone dei circuiti integrati ha consentito inoltre di rendere
disponibili sullo stesso chip ulteriori dispositivi come ad esmepio convertitori
AD, cicruiti integrati per la gestione della comunicazione, ulteriore memoria etc
etc..
È quindi possibile fare interagire il firmware con il mondo esterno, controllando
dispositivi di svariata natura, led, interruttori, relè, altoparlnti, motori e persino
dialogare con altri microcontrollers, PC, display LCD…
I microcontrollers sono impiegati in svariate applicazioni per il loro prezzo
conveniente e la loro versatilità (c’è molta differenza tra riprogettare una
scheda elettronica e modificare qualche di codice).
I/O
CPU
Memoria
Architettura dei microcontrollers PIC:
A differenza dei processori x86 e dei
PCn basati dull’architettura di von
Neumann, i microcontrollers PIC
hanno un’architettura del tipo
Harvard che prevede un’unità di
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
elaborazione (CPU) che esegue le istruzioni presenti in una memoria detta
memoria di programma.
I dati, su cui lavorano le istruzioni, sono presenti in un’ulteriore memoria detta
memoria dati.
La suddivisione tra la memoria programma e la memoria dati ha consentito
uno sviluppo più agevole poiché in un architettura del tipo di V.N. i dati e le
istruzioni che compongono il programma devono essere della stessa
dimensione, mentre in un’architettura del tipo di Harvard i dati e le istruzioni
possono avere dimensioni differenti e quindi le due memorie sono collegate al
processore con bus di dimensione diversa ottimizzando il trasferimentod ei
dati.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Il Firmware può essere scritto da qualsiasi PC in diversi linguaggi di
programmazione sia di basso livello (assembler) che di alto livello (C, Basic,
Pascal…).
Una volta scritto il programma dev’essere convertito in linguaggio macchina e
cioè compilato in una serie di codici numerici interpretabili dal processore e va
scritto nella memoria programma attraverso una scheda ed un software di
programmazione.
Tra le diverse schede di programmazione consiglio quelal presente in rete con
il nome “minipippo” ed il software winpicpgm che rileva in automatico la
scheda utilizzata.
Attraverso winpicpgm si può selezionare il file compilato (.hex) e trasferirlo nel
microcontroller.
Una volta programmato, quando si da tensione al microcontroller, inizia
l’esecuzione del firmware partendo dalla prima istruzione presente nella prima
cella della memoria programma.
All’interno del microcontroller sono presenti altri tipi di memoria di cui alcuni
sono fondamentali per l’esecuzione del programma.
Clock
Poiché i microcontrollers PIC sono realizzati in logica RISC, un’istruzione può
occupare più colpi di clock per essere eseguita.
Il clock che serve per fare evolvere lo stato della macchina nonche
sincronizzare i vari dispositivi, è dato da un oscillatore che può essere esterno
(RC o un quarzo) oppure in alcuni microcontrollers è presente all’interno.
Dato che un PIC può lavorare con diverse frequenze (nell’ordine delle decine di
Mhz) è possibile selezionare e configurare l’oscillatore utilizzato settando i bit di
particolari zone di memoria che prendono il nome di flag.
Tali flag consentono tra l’altro di impostare eventuali protezioni ed altre
funzionalità avanzate dei microcontrollers e variano da microcontroller a
microcontroller.
Per la loro configurazione si rimanda al datasheet del prorpio microcontroller
oppure si veda la parte relativa alla creazione di un nuovo progetto in
mikroBasic.
Registri
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
I registri sono aree di memoria molto veloci realizzate in logica latch in grado
di lavorare con lastessa frequenza del processore. Tra questi hanno
fondamentale importanza il registro program counter e l’instruction register i
quali tengono traccia dell’istruzione corrente che si sta eseguendo e sarebbe
impensabile che tali registri non fossero ing rado di lavorare alla stessa
frequenza del processore..
Altri registri servono per configurare i diversi dispositivi presenti sul
microcontroller come ad esmepio quello di configurazione del convertitore AD
(nei PIC che lo implementano) oppure quelli di configurazione dei timers.
Registri di uso generale sono presenti per memorizzare i dati su cui il
processore sta lavorando.
Porte di comunicazione
Coem già acennato nell’introduzioen un pic può interagire con una gran varietà
di dispositivi esterni e per questo presenta dei piedini di I/O.
Per una migliroe gestione vengono raggruppati in PORTE ciascuna di 8pin ed
associata ad un registro PORTx dove x identifica la porta.
Ogni bit di tale registro corrisponde al valore logico presente sul pin del
microcontroller.
Ad esmepio se nel registro PORTA mettiamo 255 (11111111) tutti i pin di
PORTA avranno il valore logico 1 e cioè 5V secondo lo standard TTL.
La disposizione dei pin e delle porte cambia a seconda del microcontroller ma
rimane all’incirca la stessa per i microcontrollers dello setsso package.
a seocnda della notazione, il pin i della
porta x può essere definito come Rxi
oppure come PORTx.i
Come si vede dalla figura i pin di una porta sono sia di input che di output, ma
non possono essere usati in entrambe le modalità contemporaneamente, si
potrebbe infatti verificare un cortocircuito quando in ingresso è presente un
valore di tensione basso e si scrive un valore di tensione alto.
Per questo un ulteriore registro di direzione specifica se i pin del dispositivo
sono di ingresso oppure di uscita.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Nel caso in cui essi siano di ingresso vengono portati nella condizione di alta
impedenza in maniera tale da assorbire poca corrente epermettere
l’interfacciamento del microcontroller verso dispositivi in grado di erogare
corrente ridotta.
Tale registro che nei microcontrollers AVR prende il nome di Data Direction
Register, nei microcontrollers PIC prende il nome di TRISx dove x indica
sempre la porta a cui si riferisce ed ogni bit indica il singolo pin di tale porta.
I bit settati a 0 indicano che il pin corrispondente è un output mentre i bit
settati a 1 indicando che il pin corrispondente è un input.
Nei microcontrollers che integrano dispositivi avanzati come convertitori AD,
timers, USARTs il registro TRIS non ha effetto ma ha priorità l’abilitazione di
tali dispositivi.
Per questo è possibile che un pin del microcontroller abbia più funzioni,
selezionabili impostando i flag di configurazione e cioè andando a scrivere i
registri di cui si è parlato prima.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
L’ambiente di sviluppo mikrobasic:
mikroBasic è un completo IDE che consente di scrivere il firmware per i
microcontrollers della famiglia PIC in BASIC, rendendo disponibili strutture
della programmazione ad alto livello non che numerose librerie che consentono
uno sviluppo più immediato del firmware.
Il compilatore converte il codice scritto in linguaggio macchina cercando tra
l’altro di ridurre al minimo gli sprechi di memoria inevitabili quando si
programma ad alto livello.
Al termine della compilazione viene prodotto un file .hex conteente il
programma in codice macchina che dev’essere trasferito sulla memoria interna
del microcontroller tramite uno dei tanti programmatori disponibili (JDM,
LUDIPIPO, PICPRO).
Progetti
Prima di iniziare a scrivere il codice è necessario creare un “progetto” dal menu
project in maniera tale da specificare per quale microcontroller è destinato il
programma che si sta scrivendo, settando quindi le varie opzioni.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Il campo “Device” indica per quale
microcontroller bisogna compilare il
programma e poiché molte routines
software sono legate al tempo con cui
vengono eseguite è necessario specificare
la frequenza di clock del microcontroller.
La sezione Flag rappresenta la word di
configurazione del dispositivo che varia a
seconda del PIC utilizzato.
È possibile abilitare la protezione di
Brown out così come selezionare il tipo di
oscillatore utilizzato (quarzo, RC….)
Di default viene selezionato un oscillatore
esterno con frequenza > 1MHz (FLAG
HS=1)
Esempio di altri flag: Il PIC16F88
Il PIC16F88 estende il 16F84 che ha solo 4 bit per PORTA poiché gli altri 4 sono
occupati per il quarzo, per /RESET e per l’interrupt del Timer.
Selezionando i FLAG è possibile disattivare le funzioni di oscilalote esterno e
di /RESET ed aggiungere quei pin a PORTA arrivando ad avere 8bit per PORTA.
Come si evde in fgiura, il flag MCLR_ON (e l’opposto MCLR_OFF) abilitano o
disabilitano la funzione di MCLR presente su PortA.4.
Una volta creato il progetto viene creato di default un file e visualizzato
nell’editor.
Ora è possibile iniziare a scrivere il
codice.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Struttura del programma
La sezione indica il nome del
programma ed eventuali moduli
contenenti parti esterne di codice
Il compilatore richeide che la
dichiarazione delle costanti, delle
variabili globali e delle funzioni sia
disposta prima di tutto il resto,
attraverso le direttive symbol, const,
dim, sub che analizzeremo nel
dettaglio in seguito.
Dopodichè con l’etichetta main: ha
inizio la routine che viene eseguita
all’avvio del programma, cioè quando
si da corrente al microcontroller. Per
gli amanti del C corrisponde alla
main().
Analoga è la struttura dei moduli che al
posto della direttiva program riportano
la direttiva module, specificando al
compilatore che si tratta di un modulo
e non del programma principale da
caricare sul microcontroller.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Fondamenti di programmazione in mikroBasic
mikroBasic segue il paradigma della programmazione strutturata e ne fornisce
le strutture fondamentali in maniera ottimizzata per i microcontrollers, che
avendo una memoria molto limitata non possono permettersi di eseguire
codice con strutture dati di alto livello.
Dati
Il firmware memorizzato nella memoria programma, ha la necessità di lavorare
con dei dati che si trovano nella memoria codice.
La memoria del microcontroller è limitata e può essere di diverso tipo a
seconda della versione del microcontroller, in ogni modo è organizzata in celle
numerate (solitamente da 1 byte ciascuna) il cui numero, detto INDIRIZZO
identifica univocamente ogni zona di memoria.
Poiché per un programmatore è scomodo ricordarsi gli indirizzi di memoria a
memoria (scusate il gioco di parole) mikrobasic fornisce la possibilità di
associare ad ogni cella di memoria (e non solo) un nome che identifica quella
cella e un tipo che indica che genere di dato contiene quella cella (numero,
carattere…).
Dichiarazione ed utilizzo dei tipi statici
Al fine di ottimizzare la memoria, il compilatore necessita di sapere a priori le
variabili con cui dovrà lavorare il rpogramma e quindia ssegnare alle celle di
memoria l’identificatore utilizzato come variabile nel programma.
Proprio perché è un linguaggio ad alto livello consente anche di gestire
strutture dati che spaziano su più celle di memoria come array stringhe e
persino records, fornendo dei metodi per la gestione di tali organizzaizoni di
dati.
Come si vede dalla struttura generale di un programma una variabile si
dichiara con la direttiva DIM (dimensiona) la quiale indica al compilatore che si
sta dimensionando una variabile, ovvero assegnando un nome ad una zona di
memoria che conterrà dati di unc erto tipo.
La tipologia dei dati è essenziale al fine di organizzare al meglio la memoria.
I tipi semplici più utilizzati sono i seguenti:
Type
Size
byte
8–bit
char
8–bit
Range
0 – 255
0 – 255 piochè la codifica ASCII
associa ad ognic arattere un numero di
8bit
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Type
Size
word
short
integer
longint
16–bit
8–bit
16–bit
32–bit
float
32–bit
Range
0 – 65535
-128 – 127
-32768 – 32767
-2147483648 – 2147483647
±1.17549435082 * 10-38 ..
±6.80564774407 * 1038
Esempio: dim contatore as byte
Poiché l’utilizzo di indentificatori separati per la gfestione dei dati nons empre è
conveniente, può essere utile l’utilizzo di gruppi di variabili che prendono il
nome di array.
Array:
Un array è essenzialmente una tabella in cui ogni riga è numerata (ha un
determinato indice) e corrisponde ad una variabile.
Possono essere dimensionati array di caratteri (stringhe), array di numeri etc
etc.
Esempio scorretto:
dim temperatura1 as byte
dim temperatura2 as byte
…
dim temperaturaN as byte
l’utilizzo degli array consente di organizzare le temperature in una struttura
migliore
Esempio con array:
dim temperature as byte[N]
dove N indica il numero di celle dell’array.
Per accedere ad una cella basterà porre l’indice tra parentesi [], ad esempio
per memorizzare nella prima temperatura il valore 20:
temperature[0]= 20
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
cioè
NomeArray[indice] = ValoreDaMettereNellaCellaIdentificataDallIndice
(il primo indice valido è quello che indica la cella prima cella e vale 0 come in
C, l’ultimo disponibile indicherà l’ultima cella e corrisponderà a N-1 poiché
inizia da 0)
Nota di approfondimento: overflow
Supponiamo di avere un programma in pseudo-codice di questo tipo:
dim indice as byte
dim temperature as byte[20]
dim X as byte
….
-
leggi l’indice dall’utente
leggi la temperatura dall’utente
temperatura[indice]= (temperatura inserita dall’utente)
se l’utente inserisce un indice che va oltre il numero di celle dell’array -1 (in
questo caso 19) si ottiene una condizione di overlow, ovvero il programma
accede ad una cella che non fa parte dell’array.
Infatti le varie variabili sono memorizzate in maniera contigua sulla RAM del
microcontroller e quindi prima ci sarà una cella che conterrà il valore di indice,
poi 20 celle che corrispondono alle 20 celle dell’array temperature, e poi la
nostra variabile X che ora scopriamo cos’è.
Se l’utente inserisce 20 come indice, il prgoramma memorizza l’informazione
spostandosi di 21 celle dall’inizio dell’array e quindi scriverà il valore di
temperatura in X, cosa che non era prevista.
Essendo un architettura Harvardiana non è possibile che i dati vadano a
sovrascrivere il codice, ma in un architettura von neumaniana i dati sit rovano
prima del codice di un programma, e quindi mandando in overlfow l’array si
può andare anche a sovrascrivere il codice di un programma facendogli fare
operazioni non previste.
Gli array risultano molto comodi nella loro gestione con i cicli, ma la loro
dimensione fissa spreca spesso molta memoria, cosa che viene risolta con le
strutture dinamiche.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Stringhe:
Poiché i messaggi di testo sono le strutture dati più utilizzate, mikrobasic ha
messo a dispositione il tipo string[lunghezza] che consente una getione più
agevolata degli array di char, senza andare a dover accedere alle singole celle.
Dim messaggio as string[20]
…
Messaggio = “Hello World!!”
Come approfondito in seguito sono rpesenti anche delle funzioni per la
manipolazione delle stringhe.
Records (strutture):
Supponiamo il caso di voler memorizzare le invormazioni relative ad uno
studente, ad esempio in un dispositivo che legge una smart card contenente i
dati dello studente (matricola, nome, cognome, classe)
Essi potrebbero essere gestiti da tante variabili sparpagliate, ma torna utile al
fine di una scrittura più compatta del codice, dichiarare un nuovo tipo di
variabile, il tipo Studente che avrà al suo interno i campi matricola, nome,
cognome e classe, ciascuno del tipo corretto.
Come prima cosa occorre dichiarare le generalità di una struttura, in questo
caso di uno studente generico (la classe in OOP)
structure Studente
dim matricola as integer
...
dim classe as string[2]
end structure
Una volta dichiarata una struttura possono essere dimensionate delle variabili
che rappresentano una o più strutture ralmente esistenti sulla RAM , ad
esempio il miglioreStudente
dim migliroeStudente as Studente
oppure tutti gli studenti di una scuola
dim scuola as Studente[100]
quello che noi abbiamo chiamato variabili in questo caso corrispondono
all’istanza in OOP.
In sostanza, la struttura rappresenta lo stampo di unc erto tipo di dato, mentre
l’istanza è la creazione fisica fatta con quello stampo, che si può toccare con
mano, o meglio accedere ed utilizzare.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Dichiarazione ed utilizzo delle strutture dinamiche
Dato che la quantità di memoria disponibile sul microcontroller è molto limitata
e gli array sprecano molta memoria, mikroBasic fornisce, ma non
completamente, al programmatore la possibilità di gestire i puntatori.
Tornando all’esempio dell’array che memorizzava delle temprerature, esso
occuperà sempre quei 20 byte di RAM e non potrà andare oltre, ne sprecare di
meno.
Le strutture dinamiche risolvono questo problema, andando ad occupare una
zona di memoria dati libera quando necessario, e non a priori come le strutture
statiche, sarà quindi possibile occupare una cella libera e memorizzarci un dato
così come liberare e rendere disponibili la memoria dati inutilizzata.
Gi array vengono quindi sostituiti dalle LISTE che sono una sequenza di
strutture formate dal campo che memorizza unc erto valore, e il campo che
contiene l’indirizzo in memoria della cella successiva, in gergo informatico il
puntatore alla cella successiva.
Al termine della lista, l’ultima cella punterà all’indirizzo NULL che indica che lòa
lista è finita.
Oviamente siccome le celle sono prese dove c’è spazio sulla memoria RAM non
sono contigue e se si perde un puntatore non si può più ritrovare il resto della
lista.
Altre strutture dinamiche come gli Alberi binari cosnentono la ricerca di un
elemento utilizzando la ricerca dicotomica che ha una complessità di calcolo
logaritmica rispetto alla ricerca sequenziale che fa passare tutte le celle di un
array fino a che trova il valore desiderato.
Inoltre la potenza dei puntatori non si ferma qui, infatti un puntatore è un
indirizzo di memoria, l’ indirizzo di una cella di memoria, (o la prima di un
gruppo), e quindi non fa distinzione tra i vari tipi di dato contenuti in una cella,
è quindi possibile accedere ai bit di una cella, ignorandone il tipo se si vuiole,
consentendo nella OOP la proprietà del POLIMORFISMO.
Nonostante tuttwe queste belle cose, nelle varie architetture chi si occupa della
gestione della memoria è il SISTEMA OPERATIVO, e quindi le strutture
dinamiche sono solo parzialmente gestite da mikrobasic, il quale fornisce la
possibilità di dichiarare una variabile di tipo puntatore, ma non consente
l’allocazione e la deallocazione dinamica sulla memoria.
Per dichiarare un puntatore ad un certo tipo di variabile (o ad una struttura):
dim puntatore as ^tipo
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
il ^ indica che non è una variabile di quel tipo, ma l’indirizzo alle celle che
contengono una variabile di quel tipo.
Per accederci
puntatore^ = valore
e si legge “puntatore puntato”.
Operators & Simple Data Oriented Instructions:
La trattazione delle strutture dati è avvenuta ad alto livello, utilizzando negli
esempi del codice scritto in uno pseudo-linguaggio (in blu) capibile dal lettore
ma non certamente dal mikrobasic ne tantomeno dal mikrocontroller.
”leggi la temperatura dall’utente”
Allo stesso modo però sono state utilizzate espressioni del tipo
Messaggio = “Hello World!!”
Senza analizzare nello specifico cosa fosse per mikrobasic il simbolo “=”
In questa parte del tutorial vengono analizzati i costrutti resi disponibili da
mikrobasic per operare con i dati, quindi per confrontarli, analizzarli, leggerli e
fornirli in output.
Operatori:
Un OPERATORE è un costrutto della programmazione ad alto livello che
consente di eseguire delle operazioni con e su i dati.
Il più semplice è l’operatore di ASSEGNAZIONE = tanto che per la sua
semplicità è stato ignorato nella parte precedente di questo tutorial.
Si analizzi il seguente codice:
program es_assegnazione
dim a as byte
dim b as byte
main:
…
a=b
…
end.
Il programma dichiatra due variabili di tipo byte,
identificate con i nomi a e b.
All’interno della routine principale (main) troviamo
il costrutto a=b che, prendendo il nome di
assegnazione, assegna ad a, il valore di b, o
meglio, copia in a, il contenuto di b.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Operatori aritmetici di SOMMA, SOTTRAZIONE, MOLTIPLICAZIONE
Anche questi operatori sono molto semplici:
x+y restituisce la somma del contenuto di x e del contenuto di y
x-y “
“ differenza “
“
X*y “
“ il prodotto
“
“
Ma cosa significa restituisce??
Beh non ha senso scrivere x+y come costrutto da solo.. il risultato (che sia la
somma piuttosto che la differenza o la moltiplicazione non ha importanza)
dev’essere assegnato a qualcosa, o comunque utilizzato in un contesto
dim x as byte
dim y as byte
dim risultato as byte
…
risultato = x+y
ecco che quì la parola restituisce assume senso; x+y restituisce la somma, cioè
il valore da assegnare a risultato.
Negazione aritmetica:
Come caso particolare degli operatori precedentemente visti, n = -a viene
interpretato come “n = 0 – a”
Operatori aritmetici di divisione:
la divisione viene trattata separatamente poiché mikrobasic supporta tre
diversi operatori:
Operatore
/
div
mod
Opera su
Due valori
numerici, sia
interi che float
Due valori
numerici interi
Due valori
numerici interi
Restituisce
Indica
Un valore float
(su cui si può
fare un
typecasting [vedi
parte
successiva])
Il quoziente
intero della
divisione
La divisione
reale tra due
numeri il cui
risultato
appartiene ad R.
Meta = n / 2
La divisione
naturale tra due
numeri il cui
risultato
appartiene ad N
il resto “ ”
Q = n div m
Il resto della
divisione
naturale
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Esempio
se n=5 e m=2
Q=5 div 2 = 2
Q = n mod m
se n=5 e m=2
Q=5 mod 2 = 1
Operatori di precedenza
Come nelle espressioni aritmetiche, anche in mikrobasic le parentesi
gestiscono le precedenze degli operatori. Per definizione l’operatore = ha la
priorità minore, cioè vengono prima eseguiti tutti i conti e poi l’assegnazione.
Esempio:
Risultato=((a+b)*c)-4
Operatori sui bit
Gli operatori di bitwise lavorano invece sui bit dei dati.
L’operatore NOT inverte i bit di un numero.. ad esempio
dim a as byte
dim b as byte
a = 0 ‘ in binario a= 00000000
b = NOT a ‘ NOT a restituisce Not(00000000) = 111111111 = 255
L’operatore AND opera bit a bit,
nel caso di confronto tra bit restituisce 1 se entrambi i bit sono 1.
Nel caso di word composte da n bit, per ogni bit restituisce 1 se il bit iesimo del
primo dato è 1 e così anche per l’iesimo bit del secondo dato.
Se a = &b00000011 ‘ &b è la notazione binaria
e b = &b10000001
a AND b restituisce 00000001
del tutto simili gli operatori
OR (1 se almeno un bit = 1)
XOR (0 se i bit sono uguali, 1 se i bit sono diversi)
Gli operatori di bitwise possono essere confcatenati ad altri operatori.
Operatori di confronto
Gli operatori di confronto restituiscono un valore booleano (vero/falso) (1/0)
a seconda che la CONDIZIONE che essi verificano sia veritiera o meno.
MA cos’è una condizione??
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
La CONDIZIONE è quel costrutto della programmazione ad alto livello che può
assumere solo un valore vero o falso, a seconda dei valori assunti da due dati,
legati da un operatore di CONFRONTO.
Essa assume importanza nelle espressioni logiche ma come vedremo
successivamente specialmente negli algoritmi e nelle strutture di controllo del
flusso di un programma.
Dim vinto as byte
dim punteggio_mio as byte
dim punteggio_avversario as byte
vinto = punteggio_mio > punteggio_avversario
In questo caso la condizione è punteggio _mio > punteggio_avversario ed è realizzata
dall’operatore maggiore che opera su due valori e restituisce 1 se il primo
valore è maggiore del secondo, altrimenti restituisce 0.
Del tutto simili sono gli operatori >=, <, <=, = (uguaglianza), <> (diversità)
Nota: l’operatore = in una condizione, e non in un’assegnazione, realizza la
funzione di eguaglianza restituendo 1 se i due valori confrontati sono uguali, 0
se sono diversi.
MA no, state tranquilli non è un MA che fa saltare fuori qualche caso
particolare, è un MA che vuole sottolineare che questo è un tutorial ai
microcontrollers e non alla programmazione strutturata e basta, quindi si cerca
ora di capire come il microcontroller riesce a capire se il contenuto di una cella
di memoria è maggiore del contenuto di un'altra cella di memoria, oppure se è
minore etc etc.
Il microcontroller come detto nella prima parte di questo tutorial, integra al suo
interno un microprocessore che è capace di eseguire operazioni basilari su
delle locazioni di memoria. Come prima cosa quindi per verificare se una cella
di memoria è maggiore di un'altra, occorrerà copiarla in un registro, in amniera
tale da poter accederci più velocemente.
Nel set di istruzioni del microprocessore non sono presenti istruzioni di
cofnronto
Ma solo istruzioni matematiche come ad esempio la sottrazione, ed anche dei
FLAG, che si comportano come le spie del quadro della macchina, sia ccendono
e si spengono in particolari condizioni. In particolare il flag di Zero (Z) vale 1
quando il contenuto di un registro diventa zero.
Il flag di segno ivnece vale 1 quando un registro contiene un dato negativo.
Beh allora per verificare se un dato è maggiore di un altro, basta fare la
sottrazione e vedere il contenuto del flag di segno..
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Se a=2 b=3
e si vuole verificare la condizione a > b
Allora il processore esegue la sottrazione a-b
in questo caso a-b =-1 quindi il flag di segno vale 1
Verrà restituito quindi l’opposto del flag di segno.
Identica cosa per l’operatore < con la differenza che viene restituito il flag di
segno non negato.
Due numeri sono uguali se la loro differenza vale 0, viene quindi restituito il
flag di Zero.
Gli operatori di confronto possono essere concatenati agli altri operatori
Ad esempio
sonoRiccoDiSoldi = (mio_zio = berlusconi) OR (mio_stipendio > 5000)
Lettura e scrittura dei dati da una porta di
comunicazione
Mikrobasic consente di accedere ai registri del microcontroller, quindi questo
capitolo è molto breve in quanto descritto in precedenza nella parte
sull’architettura PIC.
Per leggere da una pin di I/O impostato come input, si ricordi che basta
utilizzare i registri di comunicazione, che in mikrobasic sono accessibili come
una qualsiasi variabile.
Esempio:
dim v as byte
….
TRISB = 255 ‘ scrive in TRISB 11111111 (PORTB usata come input)
….
V=PORTB ‘ legge il contenuto del registro di comunicazione in v
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Strutture di controllo del flusso di un
programma
Fin ora il tutorial è semrpe stato molto astratto, da questo
momento sarà possibile avere una visione più concreta di quello
che si sta realizzando e per questo il tutorial presenta alcuni
progetti da cui trarre spunto, o da realizzare per capire il
funzionamento dei microcontrollers PIC.
Come detto nella prima
parte del tutorial, un
programma è un
insieme di istruzioni
che operano su dei dati, ma il
flusso di esecuzione di queste
istruzioni può VARIARE a seconda
dei dati.
La Variazione del flusso di
esecuzione delle istruzioni prende il
nome di algoritmo e si basa su
strutture fondamentali che danno
l’attributo “strutturata” alla
programmazione.
La prima di queste strutture è la
SELEZIONE:
rappresentata con un rombo in cui entra una freccia e ne escono due, la
SELEZIONE fa una cosa piuttosto che un'altra in base ad una CONDIZIONE,
che come detto nella parte degli operatori assume importanza proprio nelle
strutture di controllo.
In mikrobasic la selezione si rappresenta tramite il costrutto IF
IF (CONDIZIONE) THEN
Istruzioni da compiere se la condizione è vera
ELSE
Istruzioni da compiere se la condizione è falsa
END IF
Dim valore assoluto as byte
Dim a as byte
…
If (a>=0) then
valoreAssoluto=a
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
else
valoreAssoluto = -a
end if
Al fine di comprendere meglio la selezione e per introdurre l’iterazione, si
propone un semplice esercizio: una chiave hardware che accende un Led solo
se la combinazione in ingresso è corretta.
Primo Progetto: Hardware key
Il software ad alto livello è leggibile e semplice, questo esempio come prima
cosa dichiara la combianzioneValida (in questo caso 00000000 in binario) ed
una zona di memrioa in cui mettere la combinazioneInserita
Come seconda cosa il programma inizializza le porte di comunicazione, sugli 8
pin di PORTB viene inserita dall’utente la chiave in binario, spostando dei micro
dip switch, quindi dev’essere una porta di input quindi TRISB = 255
Su PORTA viene collegato il led che si accende in caso di chiave valida.
Il programma attende successivamente 3 secondi (il tempo per impostare la
chiave
Quindi legge la cimbinazioneInserita e verifica SE è = a combinazioneValida.
Se lo è allora setta ad 1 il bit2 di PORTA, altrimenti non fa nulla e il programma
finisce. Per farlo ripartire occorre un RESET.
Dato che il progetto mi sembra utile a livello didattico anche per spiegare
l’iterazione ho deciso di descrivere il circuito.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Con l’iterazioen infatti è possibile fare ripetere l’inserimento della chiave
primaria,o infinite volte, o FINO a CHE si verifica una determinata
CONDIZIONE (ad esempio l’utente ha finito i tentativi disponibili)
Prima di passare allo schema elettrico complichiamoci un attimo la vita
SE la chiave è ERRATA allora facciamo accendere un led rosso, oppure al posto
del led un cicalino che emette un segnale acustico, e colleghiamolo a PORTA.0
Passiamo ora al circuito elettrico.
Dobbiamo realizzare una board che fornisce sugli o pin di PORTB in ingresso 0
(0v) oppure 1 (5V) in base ad una combinazione inseribile dall’utente.
Per farlo si utilizza un 8-micro DIP Switch
Che integra 8 interruttorini.
Gli interruttorini però possono collegare solamente i pin
di PORTB a +5V, MA quando sono aperti cosa succede??
I pin del microcontroller risultano “staccati” e la
condizione staccato non è la condizione di 0V, ma varia a
seconda del caso, dell’elettricità statica presente su quei pin. È
been quindi collegarli a massa con una resistenza da qualche K.
Quando il deviatore è chiuso Vout è collegato a +5V, a cui è
collegata in parallelo anche una resistenza da 4K7 che non
influisce sulla tensione di uscita.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]
Quando il deviatore è aperto, Vout = 0V opiichè viene ricollegato a massa
tramite la resistenza da 4K7.
Questa è un’applicazione agli estremi del partitore resistivo,
infatti, R e la resistenza da 4K7 risultano essere in serie, quindi
sono attraversate dalla stessa corrente I.
Per la prima legge di ohm, I = 5V / Rtot.
Essendo le resistenze in serie, Rtot = somma delle due resistenze
Quindi I = 5V / (4,7K + R)
Vout è la tensione misurata tra il centro del partitore e massa (a massa si
trova anche l’estremo della resistenza da 4,7K) e quindi corrisponde alla
tensione ai capi della resistenza da 4,7K.
Riapplicando la prima legge di ohm in manier ainversa abbiamo Vout = I *
4,7K = (5V*4,7K) / (4,7K + R).
Ora se R è l’interruttore, quando è chiuso la resistenza è nulla quindi R = 0
Quindi Vout(chiuso) = 5V*4,7K / 4,7K = 5V.
Se R è la resistenza corrispondente all’interruttore aperto (resistenza infinita)
si ha Vout = 5V*4,7k / (4,7k + qualcosa di infinito)
E un numero / qualcosa di infinito da 0
Quindi quando l’interruttore è aperto al pin di PORTB arriva 0.
Il resto del circuito è molto semplice.
Powered by: Hacking Group Como http://www.hgcomo.org [email protected]