Lezione 1

Step 4/6

Passo precedenteInizio lezionePasso successivo

Analizziamo un source assembler

 

Analizziamo ora linea per linea il contenuto del nostro source LED.ASM. Per chi dispone di una stampante è utile effettuare una stampa del source per poter meglio seguire la nostra descrizione. Altrimenti è preferibile visualizzare il source in una finestra separata in modo da seguire simultaneamente il source e la relativa spiegazione.

Partiamo dalla prima linea di codice:

PROCESSOR	16F84

PROCESSOR è una direttiva del compilatore assembler che consente di definire per quale microprocessore è stato scritto il nostro source. Le direttive non sono delle istruzioni mnemoniche che il compilatore traduce nel rispettivo opcode, ma delle semplici indicazioni rivolte al compilatore per determinarne il funzionamento durante la compilazione. In questo caso informiamo il compilatore che le istruzioni che abbiamo inserito nel nostro source sono relative ad un PIC16F84.

RADIX		DEC

La direttiva RADIX serve ad informare il compilatore che i numeri riportati senza notazione, sono da intendersi come numeri decimali. Ovvero se intendiamo specificare, ad esempio il numero esadecimale 10 (16 decimale) non possiamo scrivere solamente 10 perché verrebbe interpretato come 10 decimale, ma 10h oppure 0x10 oppure H'10'.

INCLUDE "P16F84.INC"

Ecco un'altra direttiva. Questa volta indichiamo al compilatore la nostra intenzione di includere nel source un secondo file denominato P16F84.INC. Il compilatore si limiterà a sostituire la linea contenente la direttiva INCLUDE con il contenuto del file indicato e ad effettuare quindi la compilazione come se fosse anch'esso parte del nostro source.

LED	EQU	0   

Ancora direttive ! Ma quando arrivano le istruzioni ? Ancora un po di pazienza.

La direttiva EQU è molto importante in quanto ci consente di definire delle costanti simboliche all'interno del nostro source. In particolare la parola LED da questo punto in poi del source sarà equivalente al valore 0. Lo scopo principale dell'esistenza della direttiva EQU è quindi rendere i source più leggibili e consentire di cambiare i valori costanti in un unico punto del source.

E' importante notare che la parola LED non identifica una variabile ma semplicemente un nome simbolico valido durante la compilazione. Non sarà quindi possibile inserire instruzioni tipo LED = 3 all'interno del source in quanto l'assegnazione dinamica di un valore ad una variabile è un'operazione che richiede l'intervento della CPU del PIC e che quindi deve essere espressa con istruzioni e non con direttive.

Le direttive hanno senso solo durante la compilazione del source quindi un PIC non potrà mai eseguire una direttiva.

Vediamo ora la linea seguente:

ORG 0CH 

Anche ORG è una direttiva e ci consente di definire l'indirizzo da cui vogliamo che il compilatore inizi ad allocare i dati o le istruzioni seguenti. In questo caso stiamo per definire un'area dati all'interno del PIC ovvero un'area in cui memorizzare variabili e contatori durante l'esecuzione del nostro programma. Quest'area coincide con l'area RAM del PIC definita dalla Microchip come area dei FILE REGISTER.

I file register altro non sono che locazioni RAM disponibili per l'utente a partire dall'indirizzo 0CH. Questo indirizzo di inizio è fisso e non può essere cambiato in quanto le locazioni precedenti sono occupate da altri registri specializzati per uso interno.

Count	RES 2   

In questa linea incontriamo una label: Count e una direttiva: RES.

La direttiva RES indica al compilatore che intendiamo riservare un certo numero di byte o meglio di file register all'interno dell'area dati; in questo caso 2 byte. La label Count, dove Count è un nome scelto da noi, è un marcatore che nel resto del source assumerà il valore dell'indirizzo in cui è stato inserito. Dato che precedentemente avevamo definito l'indirizzo di partenza a 0CH con la direttiva ORG, Count varrà 0CH. Se ad esempio inseriamo una label anche alla linea successiva essa varrà 0CH + 2 (due sono i byte che abbiamo riservato) ovvero 0EH. I nomi delle label possono essere qualsiasi ad eccezione delle parole riservate al compilatore quali sono le istruzioni mnemoniche e le direttive).

Una label si distingue da una costante simbolica perchè il suo valore viene calcolato in fase di compilazione e non assegnato da noi staticamente.

ORG 00H 

Questa seconda direttiva ORG fà riferimento ad un indirizzo in area programma (nella EEPROM) anzichè in area dati. Da questo punto in poi andremo infatti ad inserire le istruzioni mnemoniche che il compilatore dovrà convertire negli opportuni opcode per il PIC.

Il primo opcode eseguito dal PIC dopo il reset è quello memorizzato nella locazione 0, da qui il valore 00H inserito nella ORG.

bsf STATUS,RP0 

Ecco finalmente la prima istruzione mnemonica completa di parametri. I PIC hanno una CPU interna di tipo RISC per cui ogni istruzione occupa una sola locazione di memoria, opcode e parametri inclusi. In questo caso l'istruzione mnemonica bsf sta per BIT SET FILE REGISTER ovvero metti a uno (condizione logica alta) uno dei bit contenuti nella locazione di ram specificata.

Il parametro STATUS viene definito nel file P16F84.INC tramite una direttiva EQU. Il valore assegnato in questo file è 03H e corrisponde ad un file register (ovvero una locazione ram nell'area dati) riservato.

Anche il parametro RP0 viene definito nel file P16F84.INC con valore 05H e corrisponde al numero del bit che si vuole mettere a uno. Ogni file register è lungo 8 bit e la numerazione di ciascuno parte da 0 (bit meno significativo) fino ad arrivare a 7 (bit più significativo)

Questa istruzione in pratica mette a 1 il quinto bit del file register STATUS. Questa operazione è necessaria, come vedremo nelle lezioni successive, per accedere ai file register TRISA e TRISB come vedremo ora.

movlw 00011111B 

Questa istruzione sta a significare: MOVE LITERAL TO W REGISTER ovvero muovi un valore costante nell'accumulatore. Come avremo modo di vedere più avanti, l'accumulatore è un particolare registro utilizzato dalla CPU in tutte quelle situazioni in cui vengono effettuate operazioni tra due valori oppure in operazioni di spostamento tra locazioni di memoria. In pratica è un registro di appoggio utilizzato dalla CPU per memorizzare temporaneamente un byte ogni volta che se ne presenta la necessità.

Il valore costante da memorizzare nell'accumulatore è 00011111B ovvero un valore binario a 8 bit dove il bit più a destra rappresenta il bit 0 o bit meno significativo.

Nell'istruzione successiva:

movwf TRISA

il valore 00011111 viene memorizzato nel registro TRISA (come per il registro STATUS anche TRISA è definito tramite una direttiva EQU) la cui funzione è quella di definire il funzionamento di ogni linea di I/O della porta A. In particolare ogni bit ad uno del registro TRISA determina un ingresso sulla rispettiva linea della porta A mentre ogni 0 determina un'uscita.

Nella seguente tabella viene riportata la configurazione che assumeranno i pin del PIC dopo l'esecuzione di questa istruzione:

N.bit registro TRISB Linea porta A N.Pin Valore Stato
0 RA0 17 1 Ingresso
1 RA1 18 1 Ingresso
2 RA2 1 1 Ingresso
3 RA3 2 1 Ingresso
4 RA4 3 1 Ingresso
5 - - 0 -
6 - - 0 -
7 - - 0 -

Come è possibile vedere i bit 5, 6 e 7 non corrispondono a nessuna linea di I/O e quindi il loro valore non ha alcuna influenza.

Le due istruzioni successive svolgono le stesse funzioni per la porta B del PIC:

movlw B'11111110'
movwf TRISB 

in questo caso la definizione delle linee sarà la seguente:

N.bit registro TRISB Linea porta B N.Pin Valore Stato
0 RB0 6 0 Uscita
1 RB1 7 1 Ingresso
2 RB2 8 1 Ingresso
3 RB3 9 1 Ingresso
4 RB4 10 1 Ingresso
5 RB5 11 1 Ingresso
6 RB6 12 1 Ingresso
7 RB7 13 1 Ingresso

Notate come il valore 0 nel bit 0 del registro TRISB determini la configurazione in uscita della rispettiva linea del PIC. Nella nostra applicazione infatti questa linea viene utilizzata per pilotare il LED da far lampeggiare.

Abbiamo visto che l'istruzione movwf TRISB trasferisce il valore contenuto nell'accumulatore (inizializzato opportunamente con l'istruzione movlw 11111110B) nel registro TRISB. Il significato di movwf è infatti MOVE W TO FILE REGISTER.

bcf STATUS,RP0

Questa istruzione è simile alla bsf vista in precedenza, con la sola differenza che azzera il bit anzichè metterlo a uno. La sigla un questo caso è BIT CLEAR FILE REGISTER.

Dal punto di vista funzionale questa istruzione è stata inserita per consentire l'accesso ai registri interni del banco 0 anzichè ai registri interni del banco 1 di cui fanno parte TRISA e TRISB. Una descrizione più dettagliata verrà data più avanti in questo corso.

bsf PORTB,LED 

Con questa istruzione viene effettuata la prima operazione che ha qualche riscontro all'esterno del PIC. In particolare viene acceso il led collegato alla linea RB0. PORTB è una costante definita in P16F84.INC e consente di referenziare il file register corrispondente alle linee di I/O della porta B mentre LED è il numero della linea da mettere a 1. Se ben ricordate, all'inizio del source la costante LED è stata definita pari a 0, quindi la linea interessata sarà RB0.

MainLoop 

Questa linea contiene una label ovvero un riferimento simbolico ad un indirizzo di memoria. Il valore della label, come detto in precedenza, viene calcolato in fase di compilazione in base al numero di istruzioni, alle direttive ORG e alle altre istruzione che in qualche modo allocano spazio nella memoria del PIC. In questo caso, se contiamo le istruzioni inserite a partire dall'ultima direttiva ORG possiamo calcolare il valore che verrà assegnato a MainLoop ovvero 07H.

In realtà il valore che assumono le label non ha molta importanza in quanto il loro scopo è proprio quello di evitare di dover conoscere la posizione precisa degli opcode nella memoria del PIC permettendo comunque di referenziare una determinata locazione di memoria.

In questo caso la label MainLoop viene utilizzata come punto di ingresso di un ciclo (dall'inglese Loop) di accensione e spegnimento del led, ovvero una parte di codice che verrà ripetuta ciclicamente all'infinito. Incontreremo più avanti un riferimento a questa label.

call Delay

Questa istruzione dermina una chiamata (dall'inglese call) ad una subroutine che inizia in corrispondenza della label Delay.

Le subroutine sono delle parti di programma specializzare ad effettuare una funzione specifica. Ogni qualvolta è necessaria quella funzione è sufficiente richiamarla con una sola istruzione, anzichè ripetere ogni volta tutte le istruzioni necessarie ad effettuarla. In questo caso la subroutine inserisce un ritardo pari al tempo di accensione e spegnimento del led.

Le istruzioni che compongono la subroutine Delay sono inserite più avanti in questo stesso source.

btfsc PORTB,LED

Il significato di questa istruzione è BIT TEST FLAG, SKIP IF CLEAR ovvero controlla lo stato di un bit all'interno di un registro e salta l'istruzione successiva se il valore di tale bit è zero. Il bit da controllare corrisponde alla linea di uscita cui è collegato il diodo led, tramite questo test potremo determinare quindi se il led è acceso o spento e quindi agire di conseguenza, ovvero se il led è gia acceso lo spegneremo, se il led è spento lo accenderemo.

goto SetToZero 

Questa istruzione è un salto incondizionato (dall'inglese GO TO, vai a)alla label SetToZero dove troveremo le istruzioni per spegnere il led. Questa istruzione verrà saltata dall'istruzione successiva se il led è gia spento.

bsf PORTB,LED
goto MainLoop 

Queste due istruzioni semplicemente accendono il led e rimandano il programma all'ingresso del ciclo di lampeggiamento.

SetToZero 
	bcf PORTB,LED 
	goto MainLoop 

Queste due istruzioni semplicemente spengono il led e rimandano il programma all'ingresso del ciclo di lampeggiamento.

La subroutine Delay

Come descritto in precedenza questa subroutine inserisce un ritardo di circa un secondo e può essere chiamata più volte nel source tramite l'istruzione call Delay.

Vediamo come funziona:

Delay
	clrf Count
	clrf Count+1
DelayLoop
	decfsz Count,1
	goto DelayLoop
	decfsz Count+1,1
	goto DelayLoop
	retlw 0

	END

Delay e DelayLoop sono due label. Delay identifica l'indirizzo di inizio della subroutine e viene utilizzato per le chiamate dal corpo principale del programma. DelayLoop viene chiamato internamente dalla subrountine e serve come punto di ingresso per il ciclo (dall'inglese loop) di ritardo.

In pratica il ritardo viene ottenuto eseguendo migliaia di istruzioni che non fanno nulla !

Questo tipo di ritardo si chiama ritardo software o ritardo a programma. E' il tipo di ritardo più semplice da implementare e può essere utilizzato quando non è richiesto che il PIC esegua altri compiti mentre esegue il ritardo.

Le istruzioni:

clrf Count
clrf Count+1

CLEAR FILE REGISTER azzerano le due locazioni di ram riservate precedentemente con l'istruzione:

Count	RES 2   

Queste due locazioni sono adiacenti a partire dall'indirizzo referenziato dalla label Count.

decfsz Count,1

L'istruzione significa DECREMENT FILE REGISTER, SKIP IF ZERO ovvero decrementa il contenuto di un registro (in questo caso Count e salta l'istruzione successiva se il valore raggiunto è zero). Se il valore raggiunto non è zero viene eseguita l'istruzione successiva:

goto DelayLoop

Che rimanda rimanda l'esecuzione all'inizio del ciclo di ritardo. Una volta raggiunto lo zero con il contatore Count vengono eseguite le istruzioni:

decfsz Count+1,1
goto DelayLoop

Che decremetano il registro seguente fino a che anche questo raggiunge lo zero. Il registro Count+1 in particolare verrà decrementato di uno ogni 256 decrementi di Count.

Quando anche Count+1 avrà raggiunto lo zero l'istruzione:

return

il cui significato è RETURN FROM SUBROUTINE determinerà l'uscita dalla routine di ritardo ed il proseguimento dell'esecuzione dall'istruzione successiva la call Delay.

Per finire END è una direttiva che indica al compilatore la fine del source assembler.

Nel passo successivo compileremo il source LED_1.ASM e programmeremo il PIC con il codice generato in uscita dal compilatore assembler.

 
Home page

PICPOINT, SXPOINT and ELETTROSHOP (C) 1997/98 by Andrea Galizia
For comments on this web site, write to webmaster@picpoint.com
Web design by Tiziano Galizia

Pic by example (c) 1997/98 by Sergio Tanzilli & Tiziano Galizia