PROGRAMMARE I MICROCONTROLLORI versione...

98
PROGRAMMARE I MICROCONTROLLORI versione 0.20 17 dicembre 2008

Transcript of PROGRAMMARE I MICROCONTROLLORI versione...

Page 1: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

PROGRAMMARE I MICROCONTROLLORI

versione 0.20

17 dicembre 2008

Page 2: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

ii

(v. 0.20)

Page 3: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Indice

Prefazione ix

1 I MICROCONTROLLORI 11.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 I sistemi a microprocessore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.2.1 La CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2.2 La memoria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.2.3 I dispositivi di Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . 6

1.3 Il microcontrollore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71.4 Tecniche di colloquio tra CPU e periferiche . . . . . . . . . . . . . . . . . . . . . . 8

1.4.1 Polling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81.4.2 Interrupt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.5 Il processo di sviluppo del software . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.5.1 Generazione e modifica del codice sorgente . . . . . . . . . . . . . . . . . . 91.5.2 Compilazione, assemblaggio e linking del codice . . . . . . . . . . . . . . . . 101.5.3 Strumenti di modellazione grafica . . . . . . . . . . . . . . . . . . . . . . . . 11

1.6 Domande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131.7 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2 PROGRAMMAZIONE IN C 152.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152.2 Elementi di un programma C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.2.1 I commenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.2.2 Le parole chiave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.2.3 Gli identificatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.2.4 Le costanti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.2.5 Le costanti stringa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.2.6 Gli operatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192.2.7 La punteggiatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

2.3 Le variabili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212.3.1 Variabili char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222.3.2 Variabili int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232.3.3 Variabili float e double . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.4 Le espressioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.5 La gestione dell’I/0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

2.5.1 La funzione getchar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242.5.2 La funzione putchar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.5.3 La funzione printf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252.5.4 La funzione scanf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

2.6 Controllo del flusso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272.6.1 Operatori relazionali, di uguaglianza e logici . . . . . . . . . . . . . . . . . . 282.6.2 Istruzioni if e if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

iii

Page 4: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

iv INDICE

2.6.3 Istruzione while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302.6.4 Istruzione for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 322.6.5 Istruzione do . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342.6.6 Istruzioni break e continue . . . . . . . . . . . . . . . . . . . . . . . . . . . 352.6.7 Istruzione switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

2.7 Le funzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402.7.1 Definizione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402.7.2 Regole di visibilita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432.7.3 Classi di memorizzazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . 432.7.4 Strutturazione di un programma in moduli . . . . . . . . . . . . . . . . . . 44

2.8 Gli array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452.9 I puntatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462.10 Domande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472.11 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

3 I MICROCONTROLLORI PIC 533.1 Introduzione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533.2 Il microcontrollore PIC 16F876 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

3.2.1 Harvard vs. Von Neumann . . . . . . . . . . . . . . . . . . . . . . . . . . . 543.2.2 Il pinout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563.2.3 Organizzazione della memoria . . . . . . . . . . . . . . . . . . . . . . . . . . 58

3.3 L’assembly dei PIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603.3.1 I registri per uso speciale . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

3.4 Il primo programma in assembler . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623.4.1 Scrittura, assemblaggio, simulazione e debugging del primo programma . . 65

3.5 Il primo programma in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 673.6 Temporizzazioni e routine - Secondo programma in assembler . . . . . . . . . . . . 693.7 Temporizzazioni e funzioni - Secondo programma in C . . . . . . . . . . . . . . . . 723.8 Timer ed interruzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 733.9 Domande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 763.10 Esercizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

4 ARGOMENTI AVANZATI 794.1 Multitasking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

A Set di istruzioni del PIC 16F87X 81

B DIRETTIVE DEL PIC 16F87X 85

(v. 0.20)

Page 5: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Elenco delle figure

1.1 Contenitori per microprocessori/microcontrollori: PDIP - Lead Plastic Dual In-Line, SOIC - Lead Plastic Small Outline. . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Architettura di un sistema a microprocessore. . . . . . . . . . . . . . . . . . . . . . 21.3 Diagramma a blocchi della CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.4 Ciclo di esecuzione delle istruzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . 51.5 Schema a blocchi di un genercio microcontrollore . . . . . . . . . . . . . . . . . . . 81.6 Il ciclo di sviluppo del software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.7 Esempio di codice C e del suo corrispondente diagramma di flusso. . . . . . . . . . 11

2.1 Output del primo programma in C. . . . . . . . . . . . . . . . . . . . . . . . . . . . 162.2 Diagramma di attivita delll’istruzione if-else. . . . . . . . . . . . . . . . . . . . . . 292.3 Diagramma di attivita dell’istruzione while. . . . . . . . . . . . . . . . . . . . . . . 302.4 Diagramma di attivita dell’istruzione for. . . . . . . . . . . . . . . . . . . . . . . . 332.5 Diagramma di attivita dell’istruzione do-while. . . . . . . . . . . . . . . . . . . . . 342.6 Diagramma di attivita dell’istruzione break. . . . . . . . . . . . . . . . . . . . . . . 352.7 Diagramma di attivita dell’istruzione continue. . . . . . . . . . . . . . . . . . . . . 362.8 Diagramma di attivita della sintassi switch-case. . . . . . . . . . . . . . . . . . . . 372.9 Automa riconoscitore di sequenza . . . . . . . . . . . . . . . . . . . . . . . . . . . . 392.10 Diagramma a stati dell’esercizio 7. . . . . . . . . . . . . . . . . . . . . . . . . . . . 502.11 Esercizio 13. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51

3.1 Architetture Harvard e Von Neumann . . . . . . . . . . . . . . . . . . . . . . . . . 543.2 La Pipeline delle istruzioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 543.3 Diagramma a blocchi del PIC16F876. . . . . . . . . . . . . . . . . . . . . . . . . . 553.4 Pinout del PIC16F876 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563.5 Sistema minimo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 563.6 Secondo sistema minimale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 573.7 Architettura della memoria di programma . . . . . . . . . . . . . . . . . . . . . . . 583.8 Mappa della memoria RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 593.9 Prime righe di assembler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603.10 Il segnale RC3 visto dal Simulator Logic Analizer. . . . . . . . . . . . . . . . . . . 66

v

Page 6: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

vi ELENCO DELLE FIGURE

(v. 0.20)

Page 7: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Elenco delle tabelle

2.1 Specifiche di conversione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.2 Sequenze di escape . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262.3 Operatori relazionali, di uguaglianza e logici . . . . . . . . . . . . . . . . . . . . . . 28

3.1 Memorie del PIC16F876 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

A.1 Operazioni orientate al BIT con i file register . . . . . . . . . . . . . . . . . . . . . 81A.2 Operazioni orientate al BYTE con i file register . . . . . . . . . . . . . . . . . . . . 82A.3 Operazioni di controllo e con letterali . . . . . . . . . . . . . . . . . . . . . . . . . . 83

vii

Page 8: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

viii ELENCO DELLE TABELLE

(v. 0.20)

Page 9: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Prefazione

Il proposito di questi appunti e quello di introdurre alla comprensione ed alla programmazionedei sistemi a microprocessore. Essi sono il risultato di anni di insegnamento nella scuola tecnicaindustriale e nei corsi post-diploma e non devono essere considerati come un insieme statico dinozioni ma come un sussidio al libro di testo, in evoluzione proprio grazie agli spunti che vengonocontinuamente dall’attivita didattica. Propro per questo motivo e allora comprensibile perche sipossono trovare alcune imperfezioni e perche il testo e contraddistinto da un numero di versione,ormai la 0.20.

ix

Page 10: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

x

(v. 0.20)

Page 11: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Capitolo 1

I MICROCONTROLLORI

Obiettivi didattici

• Conoscere l’architettura di un sistema a microprocessore.

• Conoscere le modalita di esecuzione di una istruzione.

• Saper distinguere le varie fasi di sviluppo del software per un microcontrollore.

1.1 Introduzione

I microcontrollori, in breve denominati µC, sono il cuore pulsante di molte schede ed apparatielettronici. La riduzione dei costi ed il miglioramento delle loro prestazioni hanno favorito la dif-fusione di massa in tutti gli ambienti. Non siamo lontani dalla verita se affermiamo che all’internodi una attuale abitazione domestica possiamo trovare decine di microcontrollori, all’interno deipiu svariati dispositivi.

Un microcontrollore e generalmente definito come un microprocessore che opera come unsistema embedded. Pertanto dobbiamo dapprima chiarire cosa si intende con i termini micropro-cessore ed embedded.

Un microprocessore e un dispositivo elettronico in grado di effettuare operazioni logiche,aritmetiche e di compiere delle scelte in base all’esito di tali operazioni. La capacita di effettuarescelte e una caratteristica propria di un sistema intelligente.

Un sistema embedded e un sistema di elaborazione specializzato, in pratica un microcom-puter, integrato in un apparato fisico in modo da controllarne le funzioni tramite un appositoprogramma software dedicato. Esempi di dispositivi che integrano al loro interno sistemi em-bedded sono i cellulari, il sistema di frenatura ABS, il controllo airbag, i dispositivi di homeautomation, dispositivi di automazione di macchine industriali, ecc..

Figura 1.1: Contenitori per microprocessori/microcontrollori: PDIP - Lead Plastic Dual In-Line,SOIC - Lead Plastic Small Outline.

Da un punto di vista esterno e difficile distinguere un microcontrollore da un microprocessore.Entrambi sono dei chip di silicio inseriti all’interno di contenitori che assumono svariate forme,identificati da sigle come ad esempio PDIP, SOIC, TQFP, PLCC, ecc. (Figura 1.1).

1

Page 12: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

2 1.2. I SISTEMI A MICROPROCESSORE

Da un punto di vista interno, possiamo affermare in termini grossolani che un microcontrolloree un microprocessore con attorno un po di memoria e di periferiche che gli permettono di essererelativamente autonomo. In questo senso un microcontrollore puo essere considerato un sistemaa microprocessore integrato completamente in un solo chip. Per questo motivo per comprenderecome funzionano i microcontrollori occorre piu in generale avere un’idea di come funzionino isistemi a microprocessore.

1.2 I sistemi a microprocessore

I sistemi a microprocessore sono sistemi elettronici in cui al loro interno sono presenti uno o piumicroprocessori. Per questo motivo essi sono denominati anche sistemi intelligenti. L’architetturadi un sistema a microprocessore si puo riassumere con la seguente schematizzazione.

Figura 1.2: Architettura di un sistema a microprocessore.

In essa vediamo evidenziati i seguenti componenti:

• la CPU;

• la memoria

• i dispositivi di input ed output (interfaccie).

La CPU (Central processing unit) e l’organo di governo ed e il centro delle attivita di tutto ilsistema. La CPU rappresenta in pratica lo stesso microprocessore. Per mezzo dei dispositividi input il microprocessore recepisce ed elabora le informazioni provenienti dal mondo esterno(interruttori, trasduttori, sensori, pulsanti, ecc.) seguendo le istruzioni residenti nella memoria.In seguito a tale elaborazione esso invia per mezzo dei dispositivi di output i comandi ai varidispositivi connessi (rele, led, attuatori, ecc.).

Il microprocessore comunica con la memoria ed i dispositivi di I/O mediante dei particola-ri gruppi di linee di comunicazione denominati bus. Con il termine bus si indica l’insieme deicollegamenti fisici tra CPU e ogni altro blocco funzionale presente nel sistema a microprocessore(memoria, periferiche, dispositivi di I/O, ecc.).

Su un bus possono circolare i seguenti tipi di informazioni:

• dati

• indirizzi di locazioni di memoria e di ingressi ed uscite

• segnali di controllo

In base al tipo di informazioni trasmesse si distinguono pertanto tre tipi di bus: control bus,address bus e data bus.

L’architettura a microprocessore e del tipo master-slave. In essa una unita di comando de-nominata master, solitamente la CPU, decide di volta in volta a quale slave assegnare la risorsa

(v. 0.20)

Page 13: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 1. I MICROCONTROLLORI 3

rappresentata dal data bus. Per svolgere questa attivita di coordinamento il master utilizza ilcontrol bus e l’address bus.

Data Bus Trasporta dati memorizzati in una locazione di memoria (indirizzata preventivamentegrazie al bus indirizzi) alla CPU o viceversa. In esso le informazioni possono viaggiare in un sensoo nell’altro (bus bidirezionale) come e anche evidenziato in figura 1.2. Il data bus e formato daun insieme di linee in cui viaggiano contemporaneamente tutti i bit che formano il singolo dato.Esso e pertanto un esempio di bus parallelo.

Address Bus Trasporta gli indirizzi (univoci) corrispondenti ad una locazione di memoria o aun dispositivo di input/output. Esso e un bus parallelo unidirezionale.

Control Bus E’ l’insieme di tutti i segnali di controllo scambiati dalla CPU con i dispositividi memoria, di elaborazione dati, di input/output che coordinano e sincronizzano le attivita del-l’intero sistema. Poiche le singole linee svolgono compiti differenti il control bus non e un busparallelo.

Tutti segnali presenti in un bus parallelo vengono indicati con la stessa lettera, utilizzando poiun indice numerico corrispondente al peso per differenziarli. Ad esempio i segnali presenti nel databus sono indicati con D0, D1, D2, . . . mentre quelli presenti nell’address bus sono indicati con A0,A1, A2, . . . .

Il dato numerico corrispondente all’indirizzo viene allora immesso nel bus ponendo sulla lineaA0 il bit meno significativo della sua rappresentazione binaria, ovvero quello di peso 0, sulla lineaA1 il successivo bit e cosı via.

Il numero di linee presenti nei diversi bus e un indice delle potenzialita della CPU. Ad esempioil numero di linee dell’address bus permette di determinare il numero massimo di locazioni dimemoria che la CPU puo indirizzare direttamente senza dover ricorrere ad una architettura abanchi.

Esercizio proposto 1.2.1. Determinare il numero massimo di locazioni di memoria indirizzabilidirettamente da un microprocessore dotato di 16 linee di indirizzo.

1.2.1 La CPU

La CPU dirige i vari componenti di un sistema a microprocessore e comunica con essi. Oggettofondamentale di questa comunicazione sono i dati che transitano, codificati in formato binario, suldata bus. In sintesi le funzioni svolte dalla CPU sono:

- trasferimento dati;

- controllo di flusso;

- elaborazioni aritmetiche (addizioni, sottrazioni, incrementi, decrementi, ecc.);

- elaborazioni logiche (AND, OR, NOT, XOR, ecc.).

Ogni microprocessore e caratterizzato da una propria architettura interna con varie parti cheassolvono diverse funzioni. Tuttavia, praticamente in tutti i microprocessori e possibile riconoscerediversi elementi comuni.

Innanzitutto ogni CPU ha un array di registri. Si rammenta che i registri sono dispositivi dimemoria temporanei formati di una batteria di flipo-flop o latch tra loro opportunamenti connessie sincronizzati. Nell’array sono presenti almeno i seguenti registri:

(v. 0.20)

Page 14: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

4 1.2. I SISTEMI A MICROPROCESSORE

- ACCUMULATORE

- PROGRAM COUNTER

- INSTRUCTION REGISTER

- STACK POINTER

Figura 1.3: Diagramma a blocchi della CPU

Una parte importante della CPU e la ALU (Arithmetic Logic Unit) che effettua le operazioniaritmetiche e logiche sui dati contenuti in memoria. La ALU e dotata di due ingressi per glioperandi e di una uscita per il risultato. Essa non e dotata di memoria propria per cui i dati su cuiopera devono essere posti su alcuni registri interni tra cui in particolare il registro accumulatore.Le dimensioni, in bit, del registro accumulatore caratterizzano le capacita di elaborazione dei datida parte del microprocessore stesso (grande accumulatore, grandi capacita di calcolo). Si parla,in questo senso di microprocessori, e quindi anche di microcontrollori, a 8 bit, a 16 bit, a 32 bit ea 64 bit.

Esecuzione delle istruzioni

Il microprocessore, fondamentalmente, esegue una serie di istruzioni presenti nella memoria delsistema. Questo insieme di istruzioni viene denominato programma. Le istruzioni residenti nellamemoria sono codificate come una sequenza di word binarie a cui e associato un particolaresignificato, denominata codice macchina . Le istruzioni si possono suddividere in due grandicategorie: istruzioni operative e istruzioni di controllo. Le istruzioni operative specificano sia leazioni da compiere, sia gli operandi, ovvero i dati su cui le azioni sono compiute. Le istruzionidi controllo alterano il flusso sequenziale di esecuzione delle istruzioni, eventualmente in funzionedei risultati ottenuti dall’istruzione operativa precedente. L’esecuzione di una istruzione da partedella CPU si divide in due fasi: fase di FETCH (caricamento) e fase di EXECUTE (esecuzione).Durante la fase di Fetch:

1. La CPU carica sull’ address bus l’indirizzo dell’istruzione da eseguire, fornito dal ProgramCounter (PC), registro allocato nella Control Unit della CPU;

(v. 0.20)

Page 15: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 1. I MICROCONTROLLORI 5

2. Sul control bus ci sono i comandi per leggere la locazione di memoria il cui indirizzo esull’address bus, mentre sul data bus vengono caricati i dati dalla locazione di memoriaindirizzata dal Program Counter;

3. I dati presenti nel data bus vengono caricati nell’Instruction Register (IR);

4. il PC viene aggiornato ed ora punta alla prossima istruzione del programma da eseguire.Durante la fase di Execute:

5. L’istruzione caricata nell’ IR viene decodificata;

6. Vengono eseguiti i trasferimenti di dati necessari e le operazioni logiche e/o aritmetichederivate dalla decodifica dell’istruzione;

7. Il risultato, a seconda del tipo di operazione eseguita viene scritto in un registro o in unalocazione di memoria o su un dispositivo di I/O.

Figura 1.4: Ciclo di esecuzione delle istruzioni

1.2.2 La memoria

Le memorie, da un punto di vista generale, possono essere classificate in base a diversi criteri. Dalpunto di vista costruttivo si distinguono:

- Memorie ottiche

- Memorie magnetiche

- Memorie a semiconduttore

Nel caso della CPU sono ovviamente utilizzate le memorie a semiconduttore per le loro caratteri-stiche di velocita e di robustezza. Queste ultime si suddividono, in base alla capacita di mantenerele informazioni in assenza di alimentazione elettrica, in:

- Memorie volatili

- Memorie non volatili.

Per inciso, le memorie ottiche e magnetiche sono entrambe non volatili. Le informazioni in unamemoria vengono memorizzate in modalita binaria, normalmente a gruppi di otto bit (bytes).Una memoria puo essere vista come una sequenza di caselle, ciascuna della dimensione di un byte,denominate anche locazioni. Ogni locazione di memoria e dotata di un indirizzo univoco che puoessere espresso, nella documentazione tecnica allegata al PLC, in forma decimale, esadecimale e

(v. 0.20)

Page 16: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

6 1.2. I SISTEMI A MICROPROCESSORE

piu raramente in forma binaria. La dimensione, o capacita, di una memoria e data dal numero dilocazioni di memoria possibili, espresse generalmente per mezzo di multipli di 2. Per esempio:

1KByte = 1024bytes = 1024 × 8bit = 8Kbit

1MByte = 1024× 1024bytes = 1024× 1024 × 8bit = 8Mbit

Un’altra caratteristica molto importante delle memorie e la modalita di accesso; essa puo esseresequenziale (SAM) o casuale (RAM). Nel caso dell’accesso casuale sarebbe piu corretto parlare diaccesso a matrice. Il termine RAM e pero normalmente utilizzato per indicare delle particolarimemorie a semiconduttore volatili, dotate di buone capacita di immagazzinamento e di velocitadi accesso alle informazioni. Esse vengono realizzate con tecnologia MOS e si suddividono in duecategorie in base alla tipologia della cella di memoria :

- RAM statiche (cella di memoria bistabile)

- RAM dinamiche (cella di memoria monostabile)

Nei sistemi embedded si usano di norma le RAM statiche; esse hanno capacita di memoria ridotterispetto alle RAM dinamiche ma per contro sono di impiego piu facile. Sotto il termine memorieROM rientrano diverse tipologie di memorie quali ad esempio:

- Mask ROM (ROM mascherate)

- OTPROM (One Time Programmable ROM)

- EPROM (Erasable and Programmable ROM)

- EEPROM (Electrically Erasable and Programmable ROM)

- Flash (Delle EEPROM molto capienti, cancellabili e riscrivibili a banchi)

Alcune di queste tipologie possono essere presenti all’interno di un sistema embedded, con lo scopodi svolgere differenti funzioni di memorizzazione. Per esempio il software, che una volta risiedevanormalmente in una EPROM od in una OTPROM; ormai da tempo viene memorizzato nelleFlash per le loro caratteristiche di riprogrammabilita in-circuit. I parametri di funzionamentodel sistema, ovvero le costanti che vanno programmate dall’utente e raramente cambiate sonomemorizzate in EEPROM. In RAM normalmente risiedono i dati del programma. Per renderenon volatili i dati contenuti nella RAM si fa uso di batterie tampone che intervengono mantenendocostante l’alimentazione dei chip di RAM quando cessa l’alimentazione generale del sistema.

1.2.3 I dispositivi di Input/Output

I moduli di ingresso e di uscita connettono l’unita centrale all’automatismo o all’impianto. LaCPU ed il mondo esterno comunicano tra loro tramite segnali elettrici di tensione o di corrente.Le principali funzioni svolte dalle interfaccie di I/O sui segnali elettrici sono:

- adattamento

- isolamento galvanico

- filtraggio

Adattamento dei segnali elettrici. I moduli di ingresso ricevono segnali elettrici provenientida sensori, trasduttori, pulsanti, interruttori ecc., e li adattano ai livelli di tensione e correnti propridella CPU I moduli di uscita ricevono i segnali provenienti dall’unita centrale e li adattano ai livellidi tensione e corrente propri dei componenti di comando o segnalazione quali contattori, lampade,valvole, rele, ecc.

Isolamento galvanico L’isolamento galvanico viene generalmente effettuato sia sui circuitidi ingresso che sui circuiti di uscita. Esso e normalmente realizzato con l’ausilio di particolaridispositivi optoelettronici. Nel caso di ingressi ed uscite digitali si utilizzano i fotoaccoppiatori;essi sono in grado di garantire un isolamento tra due circuiti da un minimo di 1500 V ad un

(v. 0.20)

Page 17: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 1. I MICROCONTROLLORI 7

massimo di 4000 V. Nel caso di ingressi ed uscite analogiche l’isolamento puo essere realizzato conl’ausilio degli amplificatori di isolamento.

Filtraggio In tutti gli ambienti, ma soprattutto in quelli industriali, la CPU puo essere soggettaa disturbi di natura elettromagnetica; in questo caso si parla di EMI. Ma anche la CPU stessa puoemettere disturbi (EMC). Tali interferenze, se di valore sufficiente, possono dare luogo a dei segnalifasulli che potrebbero essere interpretati dalla CPU e dalle altre apparecchiature come segnali verie propri, generando in questo modo degli errori di interpretazione. Un’altra causa di errori el’effetto rimbalzo (debounce) dei contatti meccanici, dovuto alla loro elasticita. I disturbi elettricie l’effetto debounce possono essere eliminati o per lo meno ridotti a livelli accettabili mediantel’introduzione di opportuni filtri hardware e software. Un’altra strategia consiste nell’introdurredei ritardi nell’acquisizione dei dati dell’ordine dei 10 ¸25 ms (sia di tipo hardware che di tiposoftware). Infatti un disturbo dura generalmente poco mentre un segnale proveniente da unsensore dura di piu.

I segnali elettrici possono essere digitali o analogici. I segnali digitali possono assumere solodue livelli di tensione e corrente, a cui sono associati due stati logici 1 e 0 oppure ON ed OFF.Ciascun livello deve essere compreso entro opportune bande di tolleranza. I segnali analogicipossono assumere all’interno di un range di ingresso tutti i possibili valori intermedi. Una stessagrandezza fisica puo essere rilevata sia in modo digitale che analogico. La scelta tra digitale edanalogico viene effettuata in base a specifiche di prontezza e precisione del sistema di controllo. Peresempio nel caso del controllo di temperatura si puo optare per una soluzione digitale (controlloON-OFF) meno precisa e pronta, ma anche meno costosa, oppure per una soluzione analogica(controllo PID), sicuramente piu precisa e pronta ma piu onerosa. La scelta deve essere effettuatain base a criteri di convenienza; nel caso di una camera climatica potrebbe essere indispensabileoptare per una soluzione analogica, mentre nel caso del condizionamento di un edificio di nonelevate dimensioni la soluzione digitale puo rivelarsi sufficiente.

1.3 Il microcontrollore

I termini µP , CPU e MPU (Microprocessor Unit) possono essere considerati sinonimi e,.comeabbiamo visto, la CPU e sostanzialmente l’insieme di ALU e Control Unit. Quando la CPU eun singolo circuito integrato (IC, Integrated Circuit) e chiamata µP o MPU. L’insieme di MPU,memoria e porte di Input/Output (I/O) e denominato MICROCOMPUTER Al’inizio degli anniottanta si inizio ad integrare in un unico chip CPU, memoria e I/O. Si comincio allora a parlaredi MICROCONTROLLER (µC). In pratica, un microcontrollore, opportunamente programmato,e in grado di svolgere attivita di controllo acquisendo e inviando dati senza l’ausilio di circuiterieesterne. Cerchiamo di fare un confronto tra microprocessore e microcontrollore.

• MICROPROCESSORE (µP )

1. Contiene unita di gestione delle memorie interne ed esterne ed e provvisto di memoriacache.

2. La performance (n◦ di istruzioni exe al sec.) e la caratteristica piu importante, il costoe secondario.

3. Viene usato tipicamente nei PC fissi nei laptop o nelle workstations.

• MICROCONTROLLORE (µC)

1. Ha RAM e ROM integrate, ma e sprovvisto di cache

2. Ha integrate molte periferiche e viene usato in applicazioni embedded

3. Usato anche in applicazioni di controllo Real Time

4. Basso costo, basso consumo di potenza

In realta la distinzione non e sempre cosı chiara. Inoltre, in diversi casi il microprocessore di ierie diventato il microcontrollore di oggi.

(v. 0.20)

Page 18: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

8 1.4. TECNICHE DI COLLOQUIO TRA CPU E PERIFERICHE

Figura 1.5: Schema a blocchi di un genercio microcontrollore

1.4 Tecniche di colloquio tra CPU e periferiche

In una sistema a microprocessore la CPU deve ricevere e trasferire dati alle periferiche esternequali tastiera, display, stampante, dispositivi di memorizzazione, ecc. Le tecniche utilizzate dalleCPU per effettuare lo scambio di dati con le periferiche si dividono fondamentalmente in duecategorie:

• polling

• interrupt

1.4.1 Polling

Il polling, o interruzione, e la tecnica piu semplice per lo scambio di informazioni tra microproces-sore e periferiche, anche se essa costa alla CPU un maggior uso di risorse ed una minore reattivita,o prontezza di risposta. Essa consiste nell’interrogazione ciclica da parte del programma dellostato delle periferiche collegate alla CPU.

1.4.2 Interrupt

Quando una periferica deve inviare dati alla CPu o vuole ricevere dati da essa effettua ina richiestadi interruzione. In questo caso, la CPU interrompe l’esecuzione del programma principale e metteautomaticamente in esecuzione una routine di servizio dell’interrupt, memorizzata a partire da unindirizzo ben preciso.

In alcuni casi la routine di interrupt e comune a piu periferiche, per cui e necessario chela routine stessa verifiche quale periferica ha innescato l’interrupt, in altri casi per ogni singolaperiferica e prevista una specifica routine. La CPU sa quale routine deve andare a chiamareandando a pescare il suo indirizzo in una precisa area di memoria denominata tabella dei vettoridi interrupt. Quando il programmatore, andando a modificare dei singoli bit di controllo presentiin memoria, puo disabilitare il segnale di interrupt proveniente da una periferica, si parla alloradi interrupt mascherabile. In caso contrario si parla di interrupt non mascherabile, o NMI1.

1Not Mascherable Interrupt

(v. 0.20)

Page 19: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 1. I MICROCONTROLLORI 9

In particolari condizioni puo essere richiesto un flusso molto imponente di dati dalle periferichealla memoria e viceversa.

1.5 Il processo di sviluppo del software

Il processo di sviluppo del software per i sistemi a microprocessore viene spesso identificato comeun processo ciclico che interessa i seguenti passaggi:

• Analisi dei requisiti

• Generazione e modifica del codice sorgente

• Compilazione, assemblaggio e linking del codice

• Caricamento e debugging del programma

E’ piu improbabile che raro che questi passi vengano svolti tutti una volta sola. Lo sviluppo delsoftware avviene passando per una serie di raffinamenti successivi, in cui anche le stesse specifichedi partenza sono soggette ad una modifica ed un miglioramento continui.

Figura 1.6: Il ciclo di sviluppo del software

Ciascuno dei passi elencati precedentemente viene effettuato con l’ausilio di strumenti softwareappositi. Quando questi strumenti vengono integrati all’interno di un unico ambiente di sviluppo siparla allora di IDE (Integrated Development Environment). Un esempio di IDE, molto utilizzatoin ambito scolastico, e l’ambiente di sviluppo del Turbo Pascal, prodotto dalla Borland. Un IDEorientato al mondo dei microcontrollori e il software MPLAB messo a disposizione gratuitamentedalla Microchip Technology per favorire la realizzazione di sistemi basati sui propri dispositivi.

1.5.1 Generazione e modifica del codice sorgente

Un programma e una sequenza dettagliata di istruzioni univoche e ordinate scritte in uno dei moltilinguaggi di programmazione attualmente esistenti.

Un linguaggio di programmazione e costituito da un insieme di regole sintattiche e lessicali chemettono insieme parole e punteggiatura allo scopo di creare un programma corretto.

Qui di seguito e riportato una parte di un programma scritto nel linguaggio C.

void main(void)

{

IO_settings();

setup_multitasking();

while(1) {

if (task2_go==TRUE) {

task2_go=FALSE;

if (PORTC & 0x08) {

PORTC = PORTC & ~0x08; // Led 1 OFF

(v. 0.20)

Page 20: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

10 1.5. IL PROCESSO DI SVILUPPO DEL SOFTWARE

} else {

PORTC = PORTC | 0x08; // Led 1 ON

}

}

}

}

Chi vuole realizzare un programma per prima cosa produce un o piu files di testo, denominaticodice sorgente , che contengono le istruzioni, scritte in uno dei linguaggi di programmazionedisponibili per il microprocessore in oggetto.

Per scrivere programmi e quindi necessario disporre di un editor di testi non formattati. Anchenotepad di Windows puo essere sufficiente allo scopo, ma quando si inizia a realizzare program-mi poco piu che elementari e conveniente utilizzare uno dei molti editor freeware o sharewaredisponibili in rete, tra cui ad esempio Textpad 2 , oppure gli stessi editor di testo integrati negliIDE.

Il microcontrollore nell’eseguire un programma (run del programma) esegue le istruzioni di cuie costituito il codice sorgente in maniera ordinata e sequenziale e si limita a portare a termineesclusivamente le istruzioni che gli vengono sottoposte nell’ordine in cui gli sono sottoposte.

1.5.2 Compilazione, assemblaggio e linking del codice

Il programma che verifica se le regole sintattiche utilizzate in un codice sorgente sono rispettate e ilcompilatore. Quando il linguaggio utilizzato nel codice sorgente e l’assembler3 le regole sintattichevengono verificate da un programma denominato assemblatore.

Il compilatore processa il file o i files di testo che compongono il programma e verifica chele regole sintattiche siano state rispettate. Se esso trova errori, produce messaggi inerenti alletipologie di errore trovate e termina, altrimenti produce un programma eseguibile.

Entrando nel dettaglio del processo di compilazione si possono distinguere in realta tre distintefasi: pre-compilazione, compilazione e link.

Pre-compilazione In questa fase entra in azione un programma denominato pre-compilatore,che verifica ed esegue solo alcuni tipi di istruzioni presenti nel listato processato e produce unnuovo codice sorgente.

Compilazione Durante la fase della compilazione vera e propria vengono verificate le regolesintattiche e ciascun file di testo che compone il codice sorgente viene convertito in un corrispon-dente file, denominato object file, contenente il codice oggetto , una codifica del programma moltosimile al codice macchina.

Link In questa fase viene invocato un programma in grado di connettere tutti i gli object files checompongono il programma al fine di produrre un file contenente il codice macchina vero e proprio.Molto spesso alcuni degli object files non sono forniti dall’utente ma fanno parte di librerie disistema fornite insieme al compilatore.

Pertanto i compilatori, gli assemblatori e i linker sono programmi che servono per generarealtri programmi. Essi girano normalmente sulle piattaforme hardware e software piu diffuse,come ad esempio i personal computer dotati di sistema operativo Windows o linux. I programmiprodotti per mezzo di essi possono essere destinati a girare sulle stesse piattaforme dove sonostati generati. Oppure essi funzioneranno su piattaforme hardware completamente diverse daipersonal computer. Quest’ultima situazione si verifica quando si sviluppa software per sistemiche utilizzano microcontrollori, come ad esempio una stampante, un sistema di controllo della

2www.textpad.com3L’assembler, o assemby, e il linguaggio di programmazione di base per generare il codice binario per i

microcontrollori e i microprocessori in generale

(v. 0.20)

Page 21: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 1. I MICROCONTROLLORI 11

temperatura, un controllo assi di una automazione, ecc.. In questo caso i compilatori vengonodenominati piu correttamente cross-compilatori .

1.5.3 Strumenti di modellazione grafica

Ogni volta che in una disciplina dell’ingegneria vi e la necessita di realizzare un manufatto si cercadi produrre una serie di diagrammi, ovvero una rappresentazione razionalizzata e semplificata delsistema reale che consenta di evidenziarne l’aspetto finale e di studiarne le prestazioni, l’affidabilita,il comportamento, ecc., in pratica si cerca di produrre un modello.

Anche in ambito informatico si vive questa esigenza. Ad esempio, per rappresentare la sequenzadi esecuzione delle istruzioni da molti anni si fa ricorso ad un metodo di rappresentazione graficadenominato diagramma di flusso (figura 1.7).

Figura 1.7: Esempio di codice C e del suo corrispondente diagramma di flusso.

Da diversi anni, in ambito informatico, si sono diffusi metodi di rappresentazione grafica delsoftware notevolmente piu articolati e complessi, come ad esempio lo UML. Esso, come indica ilsuo acronimo (Unified modeling language), e un linguaggio grafico di modellazione che permettedi produrre una serie di diagrammi che modellano visivamente il sistema che si intende realizzare.

Lo UML nasce dalla unificazione, operata da tre ricercatori, Grady Booch, James Rumbaughe Ivar Jacobson, delle metodologie di modellazione utilizzate a meta degli anni novanta.

Ogni volta che in una disciplina dell’ingegneria vi e la necessita di realizzare un manufatto siprocede cercando di produrre in tempi relativamente brevi una rappresentazione razionalizzatae semplificata del sistema reale che consenta di evidenziarne l’aspetto finale e di studiarne leprestazioni, l’affidabilita, il comportamento, ecc., ovvero un modello. Lo UML e nato in ambitoinformatico, ma molti dei suoi aspetti e strumenti potrebbero essere applicati ad altre disciplineingegneristiche.

Forse un po grossolanamente possiamo affermare che lo UML permette di produrre una seriedi diagrammi che modellano visivamente il sistema che si intende realizzare.

Lo UML definisce una serie di diagrammi, suddivide nelle seguenti quattro categorie:

• Diagrammi statici.

• Diagrammi di comportamento.

• Diagrammi di interazione.

• Diagrammi di implementazione.

(v. 0.20)

Page 22: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

12 1.5. IL PROCESSO DI SVILUPPO DEL SOFTWARE

Nella didattica di un linguaggio di programmazione di tipo procedurale non ad oggetti quale eil C possono risultare molto efficaci, in termini di comunicazione, i diagrammi di comportamento.Essi si suddividono a loro volta in due tipologie:

• Diagrammi di stato.

• Diagrammi di attivita.

I diagrammi di stato sono molto utili a rappresentare il comportamento degli automi a statifiniti. E poiche un qualsiasi microprocessore, dotato di un programma da eseguire, e in realta unautoma a stati finiti essi ben si prestano a descrivere il comportamento di parti di codice.

I diagrammi di attivita4, piu diffusamente conosciuti con il nome di diagrammi di flusso (flowchart), sono utilizzati per visualizzare algoritmi piu o meno complessi, enfatizzando eventualiscelte ed esecuzioni parallele.

4I diagrammi di attivita rappresentano una variante dei diagrammi di stato in cui le proprieta dell’elementostato sono state ridotte.

(v. 0.20)

Page 23: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 1. I MICROCONTROLLORI 13

1.6 Domande

1. Descrivi brevemente, anche con l’ausilio di schemi a blocchi, l’architettura di un sistema amicroprocessore.

2. L’architettura che hai appena disegnato e di tipo Harvard, Von Neumann o nessuna delledue ? Giustifica la risposta.

3. Quale funzione svolgono i registri accumulatore, program counter, instruction register e stackpointer.

4. I microprocessori che hanno un elevato numero di set di istruzioni e che possono eseguirefunzioni complesse sono denominati:

(a) embedded;

(b) RISC;

(c) CPU;

(d) CISC;

(e) microcontrollori.

5. Cosa e lo stack e quali funzioni svolge ?

6. Quanti bit sono necessari per indirizzare una memoria da 364 locazioni.

7. Elencare le operazioni svolte durante la fase di fetch di una istruzione.

8. Elencare le operazioni svolte durante la fase di execute di una istruzione.

(v. 0.20)

Page 24: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

14 1.7. ESERCIZI

1.7 Esercizi

1.

(v. 0.20)

Page 25: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Capitolo 2

PROGRAMMAZIONE IN C

Obiettivi didattici

• Conoscere le principali regole sintattiche del linguaggio C.

• Conoscere i tipi di variabili, gli operatori ed alcune librerie.

• Saper realizzare semplici programmi console in linguaggio C.

2.1 Introduzione

La storia del linguaggio C e strettamente intrecciata con quella del sistema operativo UNIX. Infattiil linguaggio C e stato ideato da Dennis Ritchie nei Bell Laboratories agli inizi degli anni ’70 conlo scopo fondamentale di definire un linguaggio adatto alla scrittura di software di sistema, inparticolare quello dei sistemi operativi, che non avesse le limitazioni dell’assembler.

Ken Thompson aveva iniziato a lavorare nel 1969 su un computer PDP-7, utilizzando il lin-guaggio assembler, con lo scopo di scrivere un linguaggio ad alto livello per l’implementazione disistemi operativi. Thompson prese spunto dal CPL (Combined Programming Language) e dalBCPL1 per creare il linguaggio B che risultava essere ancora troppo pesante per l’hardware a di-sposizione. Utilizzando il linguaggio B ed un assemblatore, nel 1970 Thompson sviluppo la primaversione di UNIX. Dennis Ritchie, che era un collaboratore di Thompson ai Bell Laboratories,mise mano al linguaggio B cercando di sopperire principalmente alla mancanza di tipizzazione deidati in modo da ridurre la necessita di utilizzare i puntatori e l’aritmetica degli indirizzi.

Il linguaggio C permise di riscrivere quasi totalmente lo UNIX di Thompson per un computerpiu avanzato, il PDP-11, inaspettatamente in tempi rapidissimi. Cio spinse Thompson, Ritchiee Kernighan a scrivere il kernel anche per l’ Interdata 8/32 ed il Dec VAX 11/780, quest’ultimoparticolarmente diffuso all’epoca.

Tra il 1973 ed il 1980 il C si diffuse anche su architetture Honeywell 635 e IBM 360/370, grazieanche alla nascita delle prime librerie, come ad esempio la standard I/O library.

Nel 1978 Kernigham e Ritchie scrissero un libro divenuto subito famoso, il C ProgrammingLanguage, comunemente conosciuto con il nome di Libro Bianco, che contribuı ulteriormente alladiffusione di uno standard ‘de facto’ del C.

Alla fine degli anni ’80 il comitato X3J11 dell’American National Standard Institute inizio adabbozzare lo standard di quello che ora e noto come ANSI C.

Al giorno d’oggi il C non e solo un linguaggio di programmazione che ha fatto la storia del-l’informatica ma e anche un linguaggio flessibile e consolidato, disponibile su molte macchine emolti sistemi operativi. Basti pensare che il sistema operativo Linux e quasi interamente scrittoin C e che buona parte dei microcontrollori si programmano utilizzando le doti di portabilita e dieconomia di risorse proprie del C.

1Il Basic CPL fu sviluppato da Martin Richards nel 1967

15

Page 26: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

16 2.2. ELEMENTI DI UN PROGRAMMA C

Inoltre il linguaggio C e alla base del C++, un linguaggio di programmazione orientato aglioggetti ancora significativamente diffuso in ambito industriale.

Per chi vuole imparare il linguaggio C al giorno d’oggi non ci sono problemi nel procurarsi unodei molti compilatori e crosscompilatori disponibili gratuitamente sia per ambiente Windows cheLinux. Gli esempi riportati nelle pagine seguenti sono compilati e testati in ambiente Windowsutilizzando uno di questi compilatori, integrato all’interno del software Dev-C++. Essi sono ingran parte esempi di applicazioni monitor2.

2.2 Elementi di un programma C

Analizziamo il seguente esempio funzionante. Una volta avviato esso mostra nella finestra di testoa video una frase ed attende che venga premuto un tasto per terminare.

#include <stdio.h>

#include <stdlib.h>

/* primo programma in C */

int main(void)

{

printf("Il C e piccolo e portabile \n");

system("PAUSE");

return 0;

}

Questo programma puo essere scritto con un qualsiasi editor di testi, come ad esempio l’editorintegrato nel software Dev-C++. Dopo avere provveduto a compilare il programma, se non cisono errori viene prodotto un file con estensione .exe avente lo stesso nome del progetto. In figura2.1 e riportato l’output del programma conseguente alla sua esecuzione.

Figura 2.1: Output del primo programma in C.

Analizziamo il programma, riga dopo riga.

#include <stdio.h>

Quando viene invocato il compilatore, prima che sia fatta la compilazione vera e propria, vienerichiamato il preprocessore. Le righe che iniziano comandi con il carattere # contengono comandiper il preprocessore. In questo il comando chiede al preprocessore di includere il file d’intestazione3

stdio.h. I simboli < e > indicano che esso si trova in un posto predefinito nel disco rigido. Il filestdio.h contiene la dichiarazione della funzione printf().

2Per applicazione monitor si intende un programma che per l’output su video utilizza una finestra di testo,comunemente denominata finestra DOS, che fa girare l’interprete dei comandi del vecchio sistema operativo DOS

3I file di intestazione vengono denominati in lingua inglese header files.

(v. 0.20)

Page 27: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 17

#include <stlib.h>

Il file stdlib.h contiene le dichiarazioni di un altro set di funzioni tra cui la funzione di sistemasystem(). Senza addentrarci troppo, facciamo presente che stlib.h e il file di intestazione dellalibreria standard che contiene le dichiarazioni di diverse funzioni di utilita relative alla conversionedei numeri, alla allocazione di memoria, alla terminazione del programma, ecc.

/* primo programma in C */

La riga precedente rappresenta un commento. Essa e delimitata dalle due coppie di caratteri/* e */.

int main(void)

Questa e la prima riga della definizione della funzione main(). Le parentesi tonde indicano chesi tratta di una funzione. Le parole int e void sono parole chiave, o riservate. Ogni programmascritto in C contiene sempre una funzione chiamata main. L’esecuzione del programma iniziasempre con questa funzione.

{

...

}

Le parentesi graffe racchiudono il corpo della definizione della funzione. Esse vengono utilizzatein diversi contesti per raggruppare piu istruzioni.

printf("Il C e piccolo e portabile \n");

La funzione printf() stampa sullo schermo la costante di tipo stringa rappresentata dallaserie di caratteri racchiusa dai doppi apici "Il C e piccolo e portabile \n". I due caratteri\n (backslash n) che terminano la stringa rappresentano in realta un solo carattere, denomina-to newline. Esso e un carattere non stampabile che fa avanzare il cursore all’inizio della rigasuccessiva.

Se osserviamo bene la figura 2.1 possiamo notare che il carattere ‘e ‘ e stato tramutato inuno strano simbolo. Questo problema e legato alla gestione della codifica extended ASCII si cuiritorneremo piu tardi.

system("PAUSE");

La funzione system(), appartenente alla libreria stdlib.h, passa alla shell4 del sistema operativouna stringa che rappresenta un comando. In questo caso il comando PAUSE impone al sistemaoperativo di attendere la pressione di un tasto, prima che il controllo venga di nuovo restituito alnostro programma.

return 0;

L’istruzione return termina l’esecuzione della funzione main e quindi anche del nostro pro-gramma, passando il controllo al sistema operativo a cui viene restituito il valore 0.

Il precedente esempio ci ha permesso di vedere un programma dunzionante nella sua interezzae quindi di poterlo subito provare con il proprio compilatore. Nell’apprendimento di un linguaggiodi programmazione e buona norma evitare di leggere troppe pagine di manuali prima di mettersi aprovare concretamente. Pertanto i successivi argomenti intendono essere uno stimolo ad effettuareulteriori verifiche sul campo provando ad estendere il programma appena proposto.

4L’interprete dei comandi del sistema operativo.

(v. 0.20)

Page 28: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

18 2.2. ELEMENTI DI UN PROGRAMMA C

Esercizio proposto 2.2.1. Modificare il programma precedente in modo che stampi su piu righenome e cognome, classe e materia di insegnamento.

Il codice sorgente di un programma in linguaggio C e costituito da 7 tipi diversi di elementi.

• I commenti

• Le parole chiave

• Gli identificatori

• Le costanti

• Le costanti stringa

• Gli operatori

• La punteggiatura

2.2.1 I commenti

I commenti sono sequenze arbitrarie di caratteri racchiuse dai delimitatori /* e */. Il compilatoreignora i commenti limitandosi a sostituirli con un singolo spazio bianco. Ecco alcuni esempi dicommenti.

/*

Un commento puo estendersi

anche su piu linee

*/

/******************************

e puo essere esteticamente

ricercato.

******************************/

2.2.2 Le parole chiave

Le parole chiave sono delle parole che hanno un significato particolare nel codice. Ognuna di essereserve a definire una particolare azione. Le parole chiave sono in numero limitato e non possonoessere ridefinite dal programmatore.

auto break case char const continue

default do double else enum extern

float for goto if int long

register return short signed sizeof static

struct switch typedef union unsigned void

volatile while

2.2.3 Gli identificatori

Un identificatore e costituito da una successione contigua di lettere minuscole e/o maiuscole,numeri e dal carattere _ (underscore). In C un identificatore puo iniziare con _ o con una lettera,ma mai con un numero.

(v. 0.20)

Page 29: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 19

Identificatori validi

k

la_mia_incognita

_IlMioIndice

parametro2

Identificatori non validi

123_stella

tentativo#sbagliato

-negative

Un identificatore serve ad identificare qualcosa all’interno del programma, per esempio il nomedi una variabile. E’ conveniente assegnare alle variabili degli identificatori che esprimano unsignificato in modo evidente per aiutare a ricordare a cosa esse si riferiscono.

Il C e un linguaggio di tipo case sensitive, ovvero sensibile all’uso delle minuscole e dellemaiuscole nel formazione degli identificatori. Ad esempio l’identificatore primonome e riconosciutodiverso dall’identificatore primoNome.

2.2.4 Le costanti

In ogni programma si incontrano numerosi tipi di costanti. Una costante e costituita da un numeroo da un carattere.

2 23 172 sono esempi di costanti intere.1.23 3.14159 sono esempi di costanti reali’a’ ’b’ ’F’ ’\n’ sono esempi di costanti carattere. Le costanti carattere vanno scritte tra

apici.Le costanti si dichiarano utilizzando la parola chiave const. In realta spesso le costanti vengono

inserite nel listato di un programma utlizzando la direttiva #define.Oltre alle precedenti costanti, in C esistono le costanti enumerative definite mediante la parola

chiave enum.

2.2.5 Le costanti stringa

Le costanti stringa sono sequenze di caratteri racchiusi tra doppi apici, come ad esempio "Qwerty".Le costanti stringa vengono gestite dal compilatore come un unico oggetto, ovvero come un array5

monodimensionale di caratteri.I doppi apici non vengono memorizzati ma sono necessari per delimitare sintatticamente la

stringa. Se all’interno di una stringa si vuole utilizzare i doppi apici come carattere occorre farliprecedere dalla barra inversa \.

Ecco alcuni esempi di costanti stringa:

"Sono una stringa!"

"" /*stringa vuota*/

"a = b + 2;" /*non e una operazione*/

" " /*stringa di spazi*/

2.2.6 Gli operatori

In C ad alcuni caratteri speciali viene associato un particolare significato. Per esempio gli operatoriaritmetici sono identificati da:

+ - * / %

5Vettore.

(v. 0.20)

Page 30: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

20 2.2. ELEMENTI DI UN PROGRAMMA C

che rappresentano le usuali operazioni di addizione, sottrazione, moltiplicazione, divisione emodulo.

Il significato di alcuni simboli dipende dal contesto. Per esempio il simbolo % nelle due istruzioniseguenti corrisponde nella prima all’operatore modulo, mentre nella seconda istruzione rappresental’inizio di una specifica di conversione.

a = b % 7;

printf("%d e %d modulo 7%d", a, b);

Esercizio proposto 2.2.2. Modificare il primo programma proposta nel paragrafo 2.2 introdu-cendo le due precedenti istruzioni, avendo l’accortezza di definire le due variabili a e b prima delladefinizione della funzione main nel seguente modo:

int a;

int b = 24;

Gli operatori possiedono regole di priorita e associativita che determinano esattamente comeavvenga la valutazione delle espressioni. Poiche le espressioni tra parentesi vengono valutate perprime, le parentesi possono essere utilizzate per modificare o anche solo per evidenziare l’ordinecon cui le operazioni devono essere eseguite. Per esempio l’espressione 1 + 2 * 3 e equivalente a1 + (2*3) perche in C l’operatore * ha una priorita piu alta dell’operatore +.

Aspetto caratteristico del C e la presenza dell’operatore di incremento ++ e decremento --.Essi possono essere utilizzati sia in notazione prefissa,++i,che postfissa,i++.

Entrambe le precedenti istruzioni fanno incrementare di 1 la variabile i.L’espressione ++i incrementa il valore di i prima che esso venga utilizzato nell’istruzione, mentre

l’espressione i++ incrementa la variabile i solo dopo che l’istruzione e stata eseguita. Ad esempiola seguente istruzione composta

a = ++b + 2;

equivale alle due istruzioni semplici

b = b + 1;

a = b + 2;

mentre

b = a++ - 2;

equivale alle due seguenti istruzioni semplici

b = a - 1;

a = a + 1;

Gli operatori di incremento possono essere applicati alle variabili, ma non alle costanti o alleespressioni ordinarie. Per comprendere l’uso degli operatori di incremento provare ad effettuare iseguenti esercizi

(v. 0.20)

Page 31: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 21

Esercizio proposto 2.2.3. Che output possiamo aspettarci con le seguenti righe di codice ? Perverificare se la nostra risposta e esatta utilizzare le seguenti istruzioni in un programma minimofunzionante.

int a =1, b=2;

a = ++b+1;

b = a++-2;

printf("a = %d, b = %d \n", a, b);

Esercizio proposto 2.2.4. Utilizzare le seguenti istruzioni in un programma minimo funzionante.

int a, b, c = 0;

a = ++c;

b = c++;

printf("%d %d %d %d \n", a, b, b++, ++c); /* output 1 1 1 3*/

2.2.7 La punteggiatura

I caratteri ";" "," "{" "}" "(" ")" sono simboli di interpunzione. Essi sono utilizzati, comegli spazi vuoti, per aiutare il compilatore a riconoscere i vari elementi del programma.

2.3 Le variabili

Nella fisica le variabili sono attributi misurabili della realta. Per esempio, la temperatura di unastanza e un attributo dell’ambiente stanza a cui puo essere associato un numero mediante unaoperazione di misura.

In informatica una variabile e un elemento del codice che identifica un particolare blocco dimemoria. Il contenuto di questo blocco viene utilizzato e modificato dal programma e ad esso puoessere associato un significato ben preciso da chi scrive il programma.

Le variabili sono rappresentate nel codice sorgente mediante degli identificatori.In C ogni variabile, per poter essere utilizzata, deve essere prima definita. La definizione di

una variabile e un aspetto fondamentale perche permette al compilatore di allocare la quantita dimemoria necessaria al tipo di variabile che si deve gestire e di scegliere le istruzioni in linguaggiomacchina idonee ad eseguire operazioni su di essa.

Elemento importante nella definizione di una variabile e il tipo di dato che essa deve contenere.Le seguenti parole chiave identificano i quattro tipi di dato piu comuni del linguaggio C.

• char. Carattere: richiede un byte di memoria

• int. Intero: richiede due o quattro bytes di memoria a seconda del sistema

• float Reale in singola precisione. Richiede quattro bytes

• double Reale in doppia precisione. Richiede otto bytes.

Alle variabili viene assegnato un valore mediante delle espressioni di assegnamento in cui siutilizza l’operatore di assegnamento =, come nel seguente caso.

i = 7

(v. 0.20)

Page 32: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

22 2.3. LE VARIABILI

Alla variabile i viene assegnato il valore 7 che diviene anche il valore assunto dall’intera espres-sione. Una espressione seguita da un punto e virgola diventa una istruzione. Questa distinzionetra espressione di assegnamento e istruzione di assegnamento puo sembrare un po filosofica, ma nelC una espressione di assegnamento puo, a sua volta, essere assegnata ad una variabile. le seguentiistruzioni, che in un altro linguaggio potrebbero creare qualche problema, vengono compilate consuccesso da qualsiasi compilatore C.

i = 1 + (j=7);

printf("i %d j %d \n", i, j); /* output i 8 j 7 */

Le espressioni di assegnamento non devono essere confuse con le equazioni matematiche. Adesempio l’equazione

x + 3 = 0

non trova corrispondenza nella seguente istruzione:

x + 3 = 0; /* errore */

Mentre la seguente istruzione produce l’incremento di una unita della variabile x.

x = x + 1;

Ad essa corrisponde l’equazione matematica x = x + 1, priva di senso.

2.3.1 Variabili char

Una variabile di tipo char puo essere utilizzata per memorizzare caratteri oppure interi di piccoladimensione. Essa occupa un byte, ovvero 8 bit, per cui essa puo memorizzare 28 = 256 valoridiversi. Quando si hanno a disposizione 8 bit i caratteri vengono normalmente memorizzati utiliz-zando la codifica Extended ASCII, una estensione della codifica ASCII6 a 7 bit, introdotta ancoranegli anni ’60 per gestire la comunicazione Telex. Nel set ASCII standard i primi 32 valori, da00000002 a 00111112, furono assegnati a caratteri di controllo della comunicazione e della stampa,mentre i restanti 96 valori furono asswegnati ai piu comuni segni di interpunzione, alle cifre da 0a 9 e alle lettere minuscole e maiuscole dell’alfabeto latino.

Nella codifica extended ASCII il carattere ’a’ viene rappresentato con il valore numerico 97.Le seguenti dichiarazioni producono tutte lo stesso effetto

char c = ’a’; /* codice binario 01100001 */

char c = 97; /* notazione decimale */

char c = 0x61; /* notazione esadecimale */

char c = 0141; /* notazione ottale */

Nella terza dichiarazione il prefisso 0x indica la notazione esadecimale, mentre nell’ultimadichiarazione lo 0 preposto alle cifre 141 indica la notazione ottale.

Utilizzando i qualificatiori identificati dalle parole chiave signed e unsigned l’ANSI C forniscei tre tipi char, signed char, unsigned char.

Una variabile unsigned char assume i valori numerici appartenenti all’intervallo da 0 a 255.Il tipo char corrisponde a signed char o a unsigned char a seconda del compilatore.

Una variabile signed char assume i valori interi relativi da -128 a 127. Nei microprocessorii numeri interi relativi vengono rappresentati utilizzando la notazione binaria del complemento adue. Cerchiamo di capire con un esempio: se assegniamo ad una variabile di tipo signed char ilvalore -1 noteremo che in essa e stato memorizzato il valore binario 111111112, nel caso di -2 siotterra 11111110, e cosı via seguendo la seguente tabella di corrispondenza, ovviamente incompletaper motivi di spazio.

6La codifica ASCII ( American Standard Code for Information Interchange

(v. 0.20)

Page 33: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 23

decimale binario

+127 01111111

+126 01111110

...

+4 00000100

+3 00000011

+2 00000010

+1 00000001

0 00000000

-1 11111111

-2 11111110

-3 11111101

-4 11111100

-127 10000001

-128 10000000

Si nota che con il controllo del solo bit piu significativo si e in grado di capire se un numero epositivo, quando e 0, o negativo, quando e 1.

Qual’e la rappresentazione in complemento a due -5 ? Se si e capito il meccanismo si rispondera111110112.

C’e un modo rapido per determinare la rappresentazione in complemento a due di un numerointero negativo. Si prende la rappresentazione binaria del suo valore assoluto, si parte dal bitmeno significativo fino allla prima cifra pari a 1, dall successiva fino alla fine si sostituiscono gli 1con 0 e gli 0 con 1.

La rappresentazione in complemento a due e particolarmente interessante per i sistemi dicalcolo automatico come i microprocessori perche permette di utilizzare per la sottrazione lo stessocircuito di somma. Se per esempio devo effettuare la seguente sottrazione 2-3 prima trasformo 2nella sua rappresentazione binaria, ovvero 000000102; poi rappresnto in complemento a 2 il valore-3 mediante 111111012 e poi faccio la somma binaria tra 000000102 e 111111012,

+ 00000010

- 11111101

--------

= 11111111

ottenendo 111111112, proprio la rappresentazione in complemento a due di -1.

Esercizio proposto 2.3.1. Provare ad effettuare la precedente operazione e visualizzare gli effettiutilizzando la specifica di conversione esadecimale %x.

char c = -2;

printf("c = %02x \n",c); // c = FFFFFFFE

2.3.2 Variabili int

In C il tipo di dati int e quello normalmente piu utilizzato. Nei sistemi piu piccoli, come imicrocontrollori, int viene memorizzato utilizzando 2 bytes, mentre nei PC vengono utilizzati 4bytes. Poiche la dimensione di un int varia da un sistema all’altro, anche il numero di valoripossibili memorizzabili dipende dal sistema. Se si dispone di 2 bytes un int puo assumere tuttivalori interi da −215 a 215 − 1 ovvero da -32768 a 32767.

(v. 0.20)

Page 34: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

24 2.4. LE ESPRESSIONI

2.3.3 Variabili float e double

L’ANSI C fornisce tre tipi reali, o in virgola mobile, float, double e long double. Il tipoprincipale e double.

Nei microcontrollori i tipi reali sono poco utilizzati a causa del grosso dispendio sia di memoriadi programma che di memoria dati che essi richiedono.

Esercizio proposto 2.3.2. Scrivere un programma che data una variabile reale side calcola emostra a video i valori delle aree del quadrato di lato pari a side, del cerchio inscritto nel quadratoe del cerchio che circoscrive il quadrato

2.4 Le espressioni

Nella maggior parte dei casi le espressioni vengono utilizzate nella parte a destra di istruzioni diassegnamento o come parametri di funzioni.

Le espressioni piu semplici sono le costanti.La valutazione delle espressioni puo richiedere l’utilizzazione di regole di conversione. Ad

esempio, il risultato della divisione di due interi e ancora un intero e l’eventuale resto viene perso.

int dividendo = 11;

int divisore = 5;

int quoziente;

quoziente = dividendo / divisore;

resto = dividendo % divisore;

printf(" quoziente = %d \n",quoziente); /* output: quoziente = 2 */

printf(" resto = %d \n",resto); /* output: resto = 1 */

2.5 La gestione dell’I/0

Si analizzeranno ora gli strumenti che il C offre per operare con l’input e l’output. L’I/O vieneper ora inteso come semplici operazione a video comandate dalla tastiera. Per fare questo bisognainserire all’inizio del codice sorgente la seguente direttiva al compilatore:

#include <stdio.h>

Essa mette a disposizione alcune funzioni predefinite per eseguire la lettura da un dispositivodi input (es. tastiera) o scrittura su un dispositivo di output (es. video); le prime funzioni di cuisi parlera sono getchar, putchar, printf e scanf.

In realta getchar e putchar sono formalmente delle macro anche se vengono utilizzate allostesso modo delle funzioni.

2.5.1 La funzione getchar

Il compito della getchar e la lettura di un carattere per volta dalla tastiera.Qui di seguito si presenta un programma che, dopo aver premuto il tasto INVIO7, conta

il numero di volte che e stato digitato un carattere qualsiasi. Per interrompere il programma enecessario premere contemporaneamente la sequenza di tasti CTRL+D, corrispondente al caratterespeciale EOF8. Il numero di caratteri viene poi mostrato a video con l’ausilio della funzione printf.

7Getchar e line buffered, ovvero non restituisce il controllo finche non viene premuto il tasto INVIO.8EOF, End Of File

(v. 0.20)

Page 35: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 25

#include <stdio.h>

main()

{

int ch, i = 0;

while((ch = getchar()) != EOF)

i ++;

printf("%d\n", i);

system("PAUSE"):

}

2.5.2 La funzione putchar

La putchar svolge un compito complementare a quello della getchar. Essa legge un carattere allavolta e lo mostra a video. Il seguente programma converte ogni carattere inserito nell’equivalentelettera maiuscola (grazie alla funzione toupper().

#include <ctype.h> /* Per la definizione di toupper */

#include <stdio.h> /* Per la definizione di getchar, putchar ed EOF */

main()

{

int ch;

while((ch = getchar()) != EOF)

putchar(toupper(ch));

}

Esercizio proposto 2.5.1. Scrivere un programma che legge una successione di caratteri dallostandard input e li scrive due volte nello standard input.

2.5.3 La funzione printf

L’istruzione per stampare a video piu usata e la printf, che ha il controllo su cio che viene stampato,nel senso che permette di decidere cosa stampare ed in quale forma. La struttura di printf e laseguente:

int printf(char *formato, lista argomenti ...)

Essa stampa sullo stdout (il video in questo caso) la lista di argomenti conformemente allastringa di formato specificata. La funzione ritorna il numero di caratteri stampanti. La stringa diformato ha due tipi di argomenti:

• caratteri ordinari

• specificazioni di conversione

I caratteri ordinari vengono copiati nell’output mentre le specificazioni di conversione, con-traddistinte dal carattere percentuale "%" e da un carattere che specifica il formato, permettonodi stampare le variabili presenti nella lista di argomenti.

(v. 0.20)

Page 36: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

26 2.5. LA GESTIONE DELL’I/0

Tabella 2.1: Specifiche di conversione

Specifica argomento esempio%d, %i Intero con segno printf("Il voto e %d", voto)

%u Intero senza segno printf("Il voto e %d", voto)

%f Numero in virgola mobile printf("L’altezza e %d", altezza)

%c Carattere printf("Carattere e %c", mio_car)

%s Stringa di caratteri%o Numero in formato ottale%x, %X Numero in formato esadeci-

male%e, %E Numero in formato scienti-

fico%% Stampa il carattere ’%’

La tabella seguente mostra i possibili formati che possono essere usati per formattare levariabili; tali considerazioni si applicano anche alla funzione scanf.

E possibile inserire, tra il simbolo % e l’identificativo del formato, una delle seguenti voci:

* Segno meno (-), esegue la giustificazione a sinistra; * Un numero intero, specifica l’ampiezzadel campo; * m.d, dove m e l’ampiezza del campo e d e la precisione del numero; usato generalmenteper le stringhe o per un numero di tipo reale.

Quindi facciamo degli esempi per far capire meglio l’uso del printf:

int x = 10;

printf("Il numero e %d", x);

// l’output a video e "Il numero e 10"

print("%-.2.3f \n", 24.392734);

// l’output a video e 24.393

printf("IVA = 20%% \n");

// l’output a video e, "IVA = 20%"

Altri linguaggi che usano printf, oltre al C, sono il C++, per il quale, pero esiste anche il comandoproprietario cout, ed il PHP, nel quale si comporta in modo analogo a quello del C.

All’intero di quello che verra stampato notiamo spesso il simbolo "\n" che, come avrete intuitoserve per andare a capo; tale simbolo viene chiamato sequenza di escape. Le sequenze di escapeservono per rappresentare quei caratteri speciali presenti nella codifica ASCII e che non stampanonulla a video, ma permetto di introdurre all’interno di cio che verra stampato eventuali spaziature.Le sequenze di escape iniziano con il carattere backslash ’\’ e sono interpretate come un singolocarattere.

Tabella 2.2: Sequenze di escape

Sequenza Descrizione\n Ritorno a capo\t Tabulazione orizzontale\b Tabulazione verticale\a Torna indietro di uno spazio\f Salto pagina

(v. 0.20)

Page 37: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 27

2.5.4 La funzione scanf

La funzione scanf serve per leggere dallo stdin (generalmente la tastiera) una sequenza di caratteri(lettere o cifre) che verranno memorizzate all’interno di opportune variabili. Scanf e, quindi,definita come segue:

int scanf(char *formato, lista argomenti ...)

Da far notare che la scanf, oltre a poter leggere stringhe di testo, e non un solo caratterealla volta come la getchar, permette di leggere piu variabili contemporaneamente, se queste sonospecificate nella lista degli argomenti. A differenza della printf, pero la variabile deve esserepreceduta dal simbolo &, perche in realta tra gli argomenti non dobbiamo passare il nome dellavariabile, ma il suo indirizzo, cosa che puo essere fatta tranquillamente utilizzando un puntatore(ed ecco il perche del &, simbolo che serve ad ottenere l’indirizzo del puntatore. I puntatoriverranno trattati piu avanti.

#include <stdio.h>

int main()

{

int i;

scanf("%d \n", &i);

printf("%d \n", i);

}

Questo semplice programma sopra esposto serve solamente per leggere un numero da tastierae ristamparlo a video; avrete notato che e possibile usare gli specificatori di conversione ancheper la scanf, che, quindi, si comporta in modo molto simile a printf. Una piccola particolaritalimitatamente all’uso delle stringhe e degli array con la funzione scanf, e la seguente:

char stringa[100];

scanf("%s", stringa);

In questo caso e possibile omettere il simbolo & che richiama l’indirizzo del puntatore, ed usare,invece, il nome della variabile, perche il nome di un array corrisponde all’indirizzo di partenzadell’array stesso.

2.6 Controllo del flusso

Le istruzioni di un programma vengono normalmente eseguite in sequenza, ovvero una dopo l’altra.Se si intende effettuare una scelta o la ripetizione di una azione e necessario alterare il flussosequenziale di esecuzione delle istruzioni. Il controllo del flusso viene implementato utilizzandoalcune parole riservate appositamente dedicate allo scopo.

Una scelta tra piu azioni alternative puo essere ottenuta utlizzando le istruzioni if, if-else,e switch-case.

La ripetizione di una o piu azioni e possibile utilizzando le istruzioni while, for e do-while.Vediamo un esempio.

if (a<3)

b++;

Se la variabile a risulta minore di 3 allora viene eseguita l’istruzione b++ altrimenti essa nonviene eseguita.

(v. 0.20)

Page 38: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

28 2.6. CONTROLLO DEL FLUSSO

In C, per decidere se effettuare o meno una scelta oppure una ripetizione possono essere uti-lizzate espressioni del tipo piu disparato. Di esse viene calcolato il valore e se esso viene trovatodiverso da 0 la scelta o la ripetizione viene effettuata altrimenti no.

In sostanza in C non esiste un vero e proprio tipo booleano come ad esempio in Pascal ma unacondizione viene considerata falsa se l’espressione che la identifica assume semplicemente 0 comevalore, mentre viene considerata vera se essa assume un valore diverso da 0.

Sulla base di queste considerazioni possiamo allora comprendere perche nel seguente esempiol’incremento della variabile b venga sempre effettuato qualunque sia il valore precedentementeassunto dalla variabile a.

int a = 1;

int b = 1;

printf(" a = %d", a); /*output: a = 1*/

if (a=3)

b++; /* questa istruzione viene sempre eseguita !!! */

printf(" a = %d", a); /*output: a = 3*/

printf(" b = %d", b); /*output: b = 1*/

Si rammenta che nel C il segno di uguaglianza = da solo rappresenta solo l’operatore assegna-zione mentre l’operatore di uguaglianza viene rappresentato mediante due segni di uguaglianzaconsecutivi: ==.

2.6.1 Operatori relazionali, di uguaglianza e logici

Nei costrutti relativi al controllo del flusso vengono abbondatemente utilizzate tre tipologie dioperatori: relazionali, di uguaglianza e logici.

La seguente tabella riporta gli operatori piu frequentemente utilizzati per modificare il controllodel flusso.

Tabella 2.3: Operatori relazionali, di uguaglianza e logici

Operatori relazionali: < minore di> maggiore

di<= minore di o

uguale di>= maggiore

di o ugualedi

Operatori di uguaglianza: == uguale!= diverso

Operatori logici: ! negazione&& and logico|| or logico

Con l’eccezione dell’operatore negazione essi sono tutti operatori binari. Essi restituisconoun valore di tipo int che puo essere 0 o 1. Anch’essi, come gli altri operatori, godono di regoledi priorita ed associativita che determinano esattamente la valutazione delle espressioni in cuivengono utilizzati. Comunque in caso di dubbio l’uso delle parentesi permette di fissare a prioril’ordine di valutazione.

(v. 0.20)

Page 39: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 29

2.6.2 Istruzioni if e if-else

La forma generale di un’istruzione if e la seguente:

if (expression)

statement

Per expression si intende una qualsiasi espressione costruita utilizzando operatori relazionali,di uguaglianza e logici. Sappiamo gia che in C tutte le espressioni assumono un valore numerico.Le espressioni false assumono il valore zero mentre le istruzioni vere assumono un valore diversoda 0.

Per statement si intende una istruzione semplice o una istruzione composta. Una istruzionecomposta e una sequenza di dichiarazioni e istruzioni racchiuse tra parentesi graffe.

L’istruzione if-else deriva direttamente dall’istruzione if. La sintassi utilizzata e riportataqui di seguito:

if (expression)

statement1

else

statement2

Se expression e diversa da 0 viene eseguita l’istruzione statement1 altrimenti viene eseguital’istruzione statement2. Un buon ausilio per la comprensione del funzionamento delle istruzioniif-else e offerto dal diagramma di attivita riportato in figura 2.2, piu comunemente conosciuto conil nome di diagramma di flusso.

Figura 2.2: Diagramma di attivita delll’istruzione if-else.

Il seguente programma accetta in ingresso un numero intero e verifica se e pari o dispari.

#include<stdio.h>

#include<stdlib.h>

int main(void)

{

int input;

printf("Inserisci un numero: ");

scanf("%d", &input);

if((input%2) == 0)

{

printf("\nE’ un numero pari !\n\n");

}

else

(v. 0.20)

Page 40: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

30 2.6. CONTROLLO DEL FLUSSO

{

printf("\nE’ un numero dispari !\n\n");

}

system("PAUSE");

return 0;

}

Esercizio proposto 2.6.1. Prendendo come suggerimento l’esempio precedente scrivere un pro-gramma che accetta in ingresso un numero n minore di 20 e che determina i numeri per cui essoe divisibile.

Suggerimento. Evitare di scrivere degli if inutili!

2.6.3 Istruzione while

Uno dei punti di forza di un computer e la possibilita di ripetere delle azioni perche permette dipoter elaborare quantita di dati molto elevate. Ad esempio l’esercizio 2.6.1, se n potesse assumereun valore grande a piacere, non potrebbe essere risolto con il solo ausilio della sintassi if-else.

Le istruzioni while e for sono gli strumenti indispensabili per far ripetere al microprocessoreun certo numero di istruzioni.

Prendiamo in considerazione la seguente sintassi:

while (expression)

statement

next_statement

Innanzitutto viene valutata expression, se essa e diversa da 0 (quindi vera) viene eseguitastatement e il controllo ritorna sll’inizio del ciclo while. In questo modo statement viene eseguitafintanto che expression non diventa 0 (quindi false).

Pertanto il corpo di un ciclo while puo essere eseguito 0 o piu volte.

Figura 2.3: Diagramma di attivita dell’istruzione while.

Come primo esempio vediamo un ciclo while che determina la somma dei primi n numerinaturali.

(v. 0.20)

Page 41: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 31

int i = 0;

int n = 5;

int sum = 0;

while(i<n)

{

i++;

sum = sum + i;

}

Si noti la presenza di una variabile (i) che tiene nota del numero di volte che il ciclo e statoeffettuato.

Esercizio proposto 2.6.2. Scrivere un programma che accetta dallo standard input un numeronaturale, calcola il prodotto dei primi n numeri e lo invia allo standard output.

Suggerimento. Cosa accade se viene digitato un numero negativo ?

Esercizio proposto 2.6.3. Scrivere un programma che accetta in ingresso un numero naturaleminore di 30 e che determina se esso e primo.

I cicli while possono anche essere annidati uno dentro l’altro come nel seguente esempio chescrive l’n-esimo numero triangolare.

#include<stdio.h>

#include<stdlib.h>

int main(void)

{

int n;

int i = 0;

int row = 0; // contatore delle righe

int col = 0; // contatore delle colonne

printf("Inserisci un numero: ");

scanf("%d", &n);

while(row<n)

{

row++;

col = 0;

while(col<row)

{

col++;

i++;

printf("%d ",i);

}

putchar(’\n’);

}

system("PAUSE");

return 0;

}

(v. 0.20)

Page 42: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

32 2.6. CONTROLLO DEL FLUSSO

Esercizio proposto 2.6.4. Scrivere un programma che accetta dallo standard input un numeronaturale n ed invia allo standard output l’n-esimo numero quadrato.

Ecco i primi tre numeri quadrati:

n = 1 1

n = 2 1 2

3 4

n = 3 1 2 3

4 5 6

7 8 9

2.6.4 Istruzione for

L’istruzione for, come l’istruzione while viene utilizzata per ripetere piu volte del codice. Il suomodo di operare puo essere spiegato servendosi dell’istruzione while. Infatti la seguente sintassi

for (expr1;expr2;expr3)

statement

next_statement

e semanticamente equivalente a

expr1;

while (expr2)

{

statement

expr3;

}

next_statement

Prima di tutto viene valutata expr1, che normalmente inizializza il ciclo; viene valutata poiexpr2 e se essa e diversa da 0 viene eseguita statement seguita da expr3 ; il controllo torna poiall’inizio del ciclo for.

Rivediamo l’esempio dell’n-esimo numero triangolare utilizzando questa nuova parola chiave.

#include<stdio.h>

#include<stdlib.h>

int main(void)

{

int n;

int i = 0;

int row = 0; // contatore delle righe

int col = 0; // contatore delle colonne

printf("Inserisci un numero: ");

(v. 0.20)

Page 43: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 33

Figura 2.4: Diagramma di attivita dell’istruzione for.

scanf("%d", &n);

for(row=1;row<=n;row++)

{

for(col=1;col<=row;col++)

{

i++;

printf("%d ",i);

}

putchar(’\n’);

}

system("PAUSE");

return 0;

}

Esercizio proposto 2.6.5. Date le seguenti righe di codice disegnare il diagramma di attivita edindicare quante volte viene eseguita la riga 5.

n = 10; // 1

for(index=1; index<n; index = index + 1) // 2

{ // 3

if ((index%2)==0) // 4

printf("%d e’ pari",index); // 5

else // 6

printf("%d e’ dispari",index); // 7

} // 8

Esercizio proposto 2.6.6. Rifare l’esercizio 2.6.4 utilizzando il costrutto for.

(v. 0.20)

Page 44: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

34 2.6. CONTROLLO DEL FLUSSO

Esercizio proposto 2.6.7. In matematica un quadrato perfetto o numero quadrato e un numerointero che puo essere espresso come il quadrato di un altro numero intero, ovvero un numero lacui radice quadrata principale e anch’essa un numero intero. Ad esempio, 9 e un quadrato perfettoin quanto puo essere scritto come 3 × 3.

Scrivere un programma che legga un intero n e scriva tutti i quadrati perfetti minori di n.

Esercizio proposto 2.6.8. Scrivere un programma che legga un intero n e scriva quanti sonotutti i quadrati perfetti minori di n.

Esercizio proposto 2.6.9. Scrivere un programma che accetta in ingresso un numero naturaleminore di 30 e che determina se esso e primo.

2.6.5 Istruzione do

L’istruzione do permette di utilizzare una variante dell’istruzione while. Mediante essa il testviene effettuato al termine del ciclo invece che all’inizio.

La sintassi assume la seguente forma:e semanticamente equivalente a

do

statement

while (expression);

next-statement

Prima viene eseguita statement e solo dopo viene valutata expression. Se il valore di expressione diverso da 0 (vero) il controllo torna all’istruzione do e viene rieseguita statement. Quandoexpression e 0 (falso) si esce dal ciclo e viene eseguita next-statement.

Figura 2.5: Diagramma di attivita dell’istruzione do-while.

Il seguente esempio attende dallo standard input un intero positivo e ripete la richiesta fincheil dato inserito non e un intero positivo.

int n, error;

do {

printf("Inserisci un numero intero positivo: ");

(v. 0.20)

Page 45: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 35

scanf("%d", &n);

if(error = (n <= 0))

printf("\nErrore !! Riprova di nuovo! \n\n");

} while (error);

printf("\nBene ! Hai inserito il numero positivo %d\n\n",n);

Esercizio proposto 2.6.10. Scrivere un programma che non termina finche non viene inseritauna vocale, utilizzando la struttura dell’esempio precedente.

Suggerimento. Utilizza le istruzioni c=getchar() oppure scanf("%c",&c), ovviamente dopo averdefinito una variabile c di tipo char.

2.6.6 Istruzioni break e continue

Le istruzioni break e continue interrompono il normale controllo del flusso. L’istruzione break

provoca l’uscita dal ciclo piu interno che la contiene, o da una istruzione switch come vedremopiu avanti.

In figura 2.6 e riportato il diagramma di attivita di un ciclo while in cui e utilizzata l’istruzionebreak. Si puo notare che esso e perfettamente equivalente al diagramma di attivita di figura 2.5.In esso e presente un esempio di ciclo infinito mediante l’istruzione while(1) ovvero l’uso dellaespressione sempre vera 1 per far eseguire perennemente il ciclo while.

Figura 2.6: Diagramma di attivita dell’istruzione break.

Il seguente esempio chiede che venga inserito in ingresso una cifra, se il carattere inserito non euna cifra il ciclo continua ad essere eseguito, altrimenti viene immediatamente interrotto mediantel’istruzione break.

while (1)

{

printf("Inserisci una cifra tra 0 e 9 e premi il tasto <invio>: ");

scanf("%c%c", &c);

if((c >= ’0’) && (c <= ’9’))

break;

printf("\nErrore !! Non hai inserito una cifra tra 0 a 9!\n Ritenta ancora\n\n");

}

printf("\nBravo!! Hai inserito una cifra tra 0 a 9!\n\n");

(v. 0.20)

Page 46: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

36 2.6. CONTROLLO DEL FLUSSO

L’istruzione continue interrompe l’esecuzione dell’iterazione corrente del ciclo e causa l’inizioimmediato dell’iterazione successiva del ciclo.

Figura 2.7: Diagramma di attivita dell’istruzione continue.

Il seguente esempio accetta dallo standard input una sequenza di caratteri, filtra i caratteridiversi da ’0’, ’1’ e ’\n’, e poi invia la sequenza allo standard output.

char InChar;

printf("Inserisci una sequenza di 0 e 1 e poi premi <invio>.\n");

while (InChar != ’\n’)

{

scanf("%c",&InChar); // prendi un carattere dalla coda in ingresso

if((InChar != ’0’) && (InChar != ’1’) && (InChar != ’\n’))

continue;

putchar(InChar);

}

Esercizio proposto 2.6.11. Modificare il precedente programma in modo tale che il programmacontinui a funzionare anche quando viene premuto il tasto Invio.

2.6.7 Istruzione switch

L’istruzione switch permette di effettuare delle scelte multiple in base al valore assunto da unaespressione di controllo di tipo intero.

Supponiamo di dover scrivere un programma che effettua la scelta tra diverse opzioni: a, b ec. Il codice seguente ne e un esempio.

char c;

(v. 0.20)

Page 47: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 37

Figura 2.8: Diagramma di attivita della sintassi switch-case.

printf("Che merendina vuoi ? (a, b, c):");

c= getchar();

if (c == ’a’)

printf("\nHai scelto la merendina al cioccolato");

else if (c == ’b’)

printf("\nHai scelto la merendina alla marmellata");

else if (c == ’c’)

printf("\nHai scelto i fichi secchi");

else

printf("\nHai scelto nulla.");

Le precedenti righe di codice possono essere egregiamente sostituite dalla seguente sintassibasata sulle parole riservate switch, case, break e default.

char scelta;

printf("Che merendina vuoi ? (a, b, c):");

scelta = getchar();

switch(scelta)

{

case ’a’:

printf("\nHai scelto la merendina al cioccolato");

break;

case ’b’:

printf("\nHai scelto la merendina alla marmellata");

break;

case ’c’:

printf("\nHai scelto i fichi secchi");

break;

default:

printf("\nHai scelto nulla.");

break;

(v. 0.20)

Page 48: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

38 2.6. CONTROLLO DEL FLUSSO

}

Ma forse l’utilita dell’istruzione switch non appare ancora cosı evidente.

Esercizio proposto 2.6.12. Nell’esempio precedente ci siamo dimenticati di considerare valideper la scelta anche le lettere maiuscole. Per esempio modificate la prima versione dell’esempio,quella con le istruzioni if-else, in modo da considerare valide per l’effettuazione della sceltaanche le corrispondenti lettere maiuscole.

Il problema presentato nell’esercizio 2.6.12 puo essere risolto mediante l’istruzione switch nelseguente modo.

char c;

printf("Che merendina vuoi ? :");

c= getchar();

switch(c)

{

case ’a’:

case ’A’:

printf("\nHai scelto la merendina al cioccolato");

break;

case ’b’:

case ’B’:

printf("\nHai scelto la merendina alla marmellata");

break;

case ’c’:

case ’C’:

printf("\nHai scelto i fichi secchi");

break;

default:

printf("\nHai scelto nulla.");

break;

}

Istruzione switch e macchine a stati

L’istruzione switch e tipicamente utilizzata per implementare le macchine a stati, ovvero gliautomi a stati finiti.

Ad esempio prendiamo in considerazione l’automa riconoscitore di sequenze dotato di un ingres-so I di tipo booleano, che accetta sequenze di caratteri 0 e 1. L’automa e in grado di riconoscerela sequenza 101,l quella che presenta uno zero preceduto e seguito da un 1. Quando l’automariconosce la sequenza esso porta l’uscita U da 0 a 1 dopo il riconoscimento di tale sequenza per unsolo ciclo di clock. Le seguenti sequenze di ingresso, stato ed uscita permettono di chiarire meglioil comportamento della nostra macchina a stati:

I 1011111 1010011 1010111 1011011

S 1234222 1234312 1234342 1234234

U 0001000 0001000 0001010 0001001

Il cui diagramma degli stati, secondo il modello di Mealy, che descrive il funzionamento dellamacchina a stati e riportato in fig. 2.9.

(v. 0.20)

Page 49: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 39

Figura 2.9: Automa riconoscitore di sequenza

Basandoci proprio sul diagramma di stato precedente e possibile costruire il seguente codicesorgente implementa l’automa riconoscitore di sequenza. Il cuore della macchina a stati e ilcostrutto switch che in base al valore della variabile stato, che rappresenta lo stato attuale,ed il valore della variabile i che rappresenta l’ingresso attuale, prelevato dallo standard input,determina lo stato futuro e l’uscita.

#include<stdio.h>

#include<stdlib.h>

int main(void)

{

char i = 0; // ingresso

char u = 0; // uscita

int stato = 1; // variabile di stato

printf("Inserisci la sequenza! (solo 0 o 1, f per terminare)\n");

while (i!=’f’)

{

scanf("%c",&i);

if((i != ’0’) && (i != ’1’)) // filtra i caratteri digitati

{

if(i==’\n’)

putchar(’\n’);

continue;

}

switch(stato) { // macchina a stati

case 1:

if (i == ’1’)

stato = 2;

u = ’0’;

break;

case 2:

if (i == ’0’)

stato = 3;

u = ’0’;

break;

case 3:

if (i == ’0’)

stato = 1;

if (i == ’1’)

stato = 4;

(v. 0.20)

Page 50: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

40 2.7. LE FUNZIONI

u = ’0’;

break;

case 4:

if (i == ’0’)

stato = 3;

if (i == ’1’)

stato = 2;

u = ’1’;

break;

}

putchar(u);

}

putchar(’\n’);

system("PAUSE");

return 0;

}

In esso si nota il ruolo centrale svolto dall’istruzione switch per l’esecuzione della macchina astati, oltre ad uno stile di scrittura un po piu compatto.

Esercizio proposto 2.6.13. Realizzare l’automa riconoscitore di sequenza in grado di riconoscerele sequenze di ingresso in cui avviene un passaggio per lo 0 con uno o piu zeri . Quando l’automariconosce la sequenza esso porta l’uscita U da 0 a 1 dopo il riconoscimento di tale sequenza peruna solo ciclo. I seguenti sempi di sequenze di ingresso e di uscita chiariscono il comportamentodella macchina a stati:

I 10111111 10100111 10001111

U 00010000 00010010 00000100

2.7 Le funzioni

Le funzioni sono uno degli strumenti piu potenti del C, e non solo. Infatti, esse sono presentipraticamente in tutti i linguaggi si programmazione. Le funzioni rendono piu leggibile e riusabileil codice, permettendo un notevole risparmio di tempo, con evidenti vantaggi per il programmatore.

La risoluzione efficace dei problemi si basa spesso sulla scomposizione dei problemi in sotto-problemi piu semplici. La soluzione di ciascuno dei sottoproblemi puo essere demandata ad unaapposita funzione. Per scrivere programmi di grandi dimensioni e di fondamentale importanzaridurre il problema in piccole parti facilmente maneggevoli ed eventualmente riusabili. Questametodologia di programmazione e nota come tecnica top-down.

2.7.1 Definizione

Alcuni linguaggi fanno distinzione tra le funzioni che restituiscono un valore e quelle che, invece,non restituiscono alcun valore. Ad esempio nel linguaggio Pascal le funzioni che non ritornano al-cun valore vengono denominate procedure. Il C, invece, non fa distinzione tra funzioni e proceduree, tra l’altro, non fa uso di parole riservate per identificare le funzioni.

In C occorre distinguere tra definizione di funzione e dichiarazione di funzione. La definizionedi funzione e il codice C che descrive dettagliatamente le operazioni eseguite dalla funzione, mentrela dichiarazione di funzione informa il compilatore solo sul numero e il tipo di parametri che devonoessere passati alla funzione e sul tipo del valore da essa restituito.

(v. 0.20)

Page 51: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 41

Prendiamo in considerazione come esempio la definizione di una funzione che accetta comeparametri un valore di tipo double ed un valore di tipo int e fa un elevamento a potenza,restituendo come risultato un valore di tipo double:

double elevamento_potenza(double valore, int potenza)

{

double valore_ritorno = 1.0;

int i;

for(i=0; i<potenza; i++)

{

valore_ritorno = valore_ritorno * valore;

}

return(valore_ritorno);

}

Analizzando questa funzione possiamo notare che restituisce un valore corretto anche quandola potenza vale zero. Iniziamo, dunque, a studiare il codice nel dettaglio:

double elevamento_potenza(double valore, int potenza)

{

// corpo della funzione

}

La definizione della funzione inizia con l’indicazione del tipo del valore di ritorno (double),seguito dal nome della funzione (elevamento_potenza) e dalla lista di argomenti passati allafunzione, ciascuno di essi specificato mediante l’indicazione del tipo (double e int) e del nomecorrispondente (valore e potenza).

return(valore_ritorno);

All’interno del corpo della funzione, quando si raggiunge la parola chiave return, il controllodel programma ritorna al codice che ha chiamato la funzione. Il valore ritornato e quello posto dopola parola return. Se si termina la definizione della funzione, mediante la parentesi graffa, senzaaver messo alcuna istruzione return, il valore ritornato dalla funzione avra molto probabilmenteun significato non valido. Il valore ritornato da una funzione puo essere assegnato, ad esempio, aduna variabile. che poi potremmo usare all’interno del programma come qualsiasi altra variabile.

Il codice seguente e un esempio completo di utilizzazione della funzione elevamento_potenza.

#include <stdio.h>

double elevamento_potenza(double valore, int potenza)

{

double valore_ritorno = 1.0;

int i;

for(i=0; i<potenza; i++)

{

valore_ritorno = valore_ritorno * valore;

}

return(valore_ritorno);

}

int main(void)

{

(v. 0.20)

Page 52: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

42 2.7. LE FUNZIONI

double val = 100.0;

int pot = 3;

double risultato;

printf("Vogliamo elevare %f alla %f \n", val, pot);

risultato = elevamento_potenza(val, pot);

printf("Otteniamo come risultato %f \n", risultato);

return 0;

}

Nell’esempio precedente possiamo notare che la funzione elevamento_potenza e stata definitaprima della funzione main. Qualora la definizione fosse stata posta dopo il punto in cui essa vieneutilizzata il compilatore avrebbe segnalato un errore. Un modo per evitare questo errore e quellodi introdurre una dichiarazione della funzione prima del suo utilizzo, come si puo osservare nellaseguente variante del programma precedente.

#include <stdio.h>

double elevamento_potenza(double valore, int potenza); // dichiarazione della funzione

int main(void)

{

double val = 100.0;

int pot = 3;

printf("Vogliamo elevare %f alla %f \n", val, pot);

double risultato = elevamento_potenza(val, pot);

printf("Otteniamo come risultato %f \n", risultato);

return 0;

}

double elevamento_potenza(double valore, int potenza) // definizione della funzione

{

double valore_ritorno = 1.0;

int i;

for(i=0; i<potenza; i++)

{

valore_ritorno = valore_ritorno * valore;

}

return(valore_ritorno);

}

Possono essere definite anche funzioni che non ritornano alcun valore, in questo caso si parladi funzioni void, come mostrato di seguito:

void stampa_errore(int linea)

{

fprintf(stderr, "Errore: linea %d\n", linea);

}

Una funzione void non deve avere necessariamente un’istruzione return, anche se essa puoessere utilizzata per uscire dalla funzione in maniera opportuna, un po’ come l’utilizzazionedell’istruzione break all’interno dei cicli.

(v. 0.20)

Page 53: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 43

In questo caso particolare all’interno della funzione stampa_errore e stata utilizzata la funzionefprintf, una variante della printf. Essa stampa il messaggio di errore sullo stderr. Esso chepuo essere un file o un messaggio a video (generalmente quest’ultimo). Per richiamare la funzione,basta, ovviamente, scrivere il nome con, tra gli argomenti, il numero di linea in cui si e verificatol’errore.

int linea_err = 14;

stampa_errore(linea_err);

Esercizio proposto 2.7.1. Scrivere un programma che definisce ed utilizza una funzione checalcola l’ipotenusa di un triangolo rettangolo e che ha come argomenti i due cateti del triangolo.Il corpo della funzione main deve:

1. Richiedere da tastiera i valori dei due cateti.

2. Chiamare la funzione che calcola l’ipotenusa

3. Visualizzare sullo schermo i dati di ingresso e il risultato restituito dalla funzione.

2.7.2 Regole di visibilita

Le regole di visibilita, o scope rules, determinano quali variabili del programma siano disponibili inun dato punto di una funzione. La regola fondamentale di visibilita impone che gli identificatori so-no accessibili solo all’interno del blocco nel quale sono dichiarati. Al di fuori dei limiti di tale bloccoessi sono sconosciuti . Puo accadere che uno stesso identificatore sia utilizzato per dichiarazionidifferenti. Sorge allora il problema di sapere a quale oggetto si riferisca un identificatore.

Vediamo un esempio.

{

int pippo = 1;

printf("%d\n", pippo); // stampa 1

{

int pippo = 10;

printf("%d\n", pippo); // stampa 10

}

pippo++;

printf("%d\n", pippo); // stampa 2

}

2.7.3 Classi di memorizzazione

Tutte le funzioni e le variabili in C hanno due attributi: il tipo e la classe di memorizzazione. Iltipo indica quanto spazio viene occupato ed il significato associato ai singoli bit. La classe, invece,offre informazioni su quale area di memoria viene utilizzata e sulle sue modalita di gestione. Lequattro classi di memorizzazione previste dal C sono identificate dalle seguenti parole chiave:

auto extern register static

(v. 0.20)

Page 54: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

44 2.7. LE FUNZIONI

auto (automatica) E’ la classe di memorizzazione piu comune. Le variabili dichiarate all’internodei corpi delle funzioni sono implicitamente automatiche.

La parola chiave auto puo essere eventualmente utilizzata per specificare esplicitamente taleclasse di memorizzazione.

auto int i, j, k;

All’ingresso nel blocco di una funzione il compilatore alloca la memoria necessaria per le va-riabili automatiche in quell’area di memoria denominata stack. Le variabili vengono poi utilizzateall’interno di tale blocco. All’uscita dal blocco il compilatore rende di nuovo disponibile la memoriaprecedentemente assegnata alle variabili automatiche.

Se la funzione viene di nuovo richiamata il compilatore alloca di nuovo la memoria per levariabili senza pero recuperare i valori precedenti.

extern (Esterna) Quando una variabile viene dichiarata al di fuori di una funzione, ad essaviene assegnata memoria in modo permanente e la sua classe di memorizzazione diventa extern,anche se non viene utilizzata la parola chiave.

In sostanza le variabili esterne esistono per tutta la durata dell’esecuzione del programma.Esse vengono allocate in un’area di memoria diversa dallo stack, denominata in molti sistemi dataregion.

Una variabile extern puo essere utilizzata da tutte le funzioni definite dopo la sua definizioneo dichiarazione. Per questo motivo questo tipo di variabili vengono denominate anche variabiliglobali mentre le variabili auto vengono denominate anche locali.

Il seguente programma mette in evidenza questi concetti.

#include <stdio.h>

int a=1, b=2; // variabili globali (extern)

int f(void); // prototipo della funzione f

int main(void)

{

printf("f()= %d\n", f()); // stampa il valore restituito dalla f()

printf("a=%d, b=%d \n"’,a, b); // stampa le variabili globali

return 0;

}

int f(void)

{

int b=4, c=4; // variabili locali (auto)

// la var. globale b e coperta dalla var.locale b

return (a+b+c);

}

register (Registro) La classe di memorizzazione register segnala al compilatore che la varia-bile corrispondente dovrebbe essere memorizzata nei registri di memoria interni al microprocessore,sempre che cio sia possibile. Qualora il compilatore non riesca ad allocare un registro fisico vieneutilizzata la classe auto.

2.7.4 Strutturazione di un programma in moduli

Un programma di una certa dimensione non viene mai scritto, di solito, in un unico grande file(per esempio il solo main.c).

(v. 0.20)

Page 55: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 45

Un programma normalmente viene scritto in una directory apposita sotto forma di un insiemedi file di testo con estensione .c e .h. I file con estensione .c contengono le definizioni delle funzioniche compongono il programma mentre i file con estensione .h, denominati anche file header ,contengono le dichiarazioni delle stesse.

In questo modo, oltre a mettere un po di ordine nel programma e a renderlo piu modulare,quando si modifica la definizione di una singola funzione non e necessario ricompilare tutto ilprogramma ma e necessario ricompilare solo il modulo interessato. Di queste cose se ne occupanormalmente make, una utility molto famosa tra i programmatori.

Esercizio proposto 2.7.2. Modificare il codice sorgente dell’esercizio 2.7.1 in modo tale chel’input/output risieda in un modulo separato.

2.8 Gli array

In molte situazioni e necessario operare con una serie di dati omogenei (per esempio una serie dimisure di un esperimento, l’insieme dei voti subiti in sistemi durante un trimestre, ecc.). Se peresempio si devono elaborare i valori assunti da una tensione elettrica potremmo dichiararli nelseguente modo:

float V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17;

E’ evidente che fare elaborazioni su tali valori non e molto agevole. Se ad esempio fossenecessario determinare il loro valore medio si dovrebbe scrivere le seguenti istruzioni.

float media;

media = (V0+V1+V2+V3+V4+V5+V6+V7+V8+V9+V10+V11+V12+V13+V14+V15+V16+V17)/18;

Se il numero dei valori e grande l’utilizzazione di identificatori unici per rappresentare e ma-nipolare ciascun dato diventa una fatica improba. Diventa allora necessario utilizzare un array9,un tipo di dato derivato.

Un array puo essere visto come una variabile dotata di indice. In pratica gli array si utilizzanoquando si devono effettuare operazioni su una serie di dati omogenei.

float V[18];

float media = 0;

int i;

for(i=0;i<18;i++)

media = media + V[i];

media = media/i;

L’intero 18 nella dichiarazione rappresenta il numero di elementi presenti nell’array. L’indiciz-zazione degli elementi parte sempre da 0.

E’ buona norma di programmazione utilizzare una costante simbolica per definire la lunghezzadi un array. Per esempio, nel caso precedente sarebbe stato piu opportunio scrivere:

#define NUMERO_MISURE

float V[NUMERO_MISURE];

float media = 0;

int i;

9Array si traduce vettore

(v. 0.20)

Page 56: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

46 2.9. I PUNTATORI

for(i=0;i<NUMERO_MISURE;i++)

media = media + V[i];

media = media/i;

In C, una stringa e un array di caratteri avente come ultimo termine il carattere ’\0’ equi-valente a 0x00 in notazione esadecimale. I concetti di array, stringa e puntatore sono tra lorostrettamente legati.

Esercizio proposto 2.8.1. Scrivere un programma che richiede come input n valori interi e poidetermina il minimo valore ed il massimo valore tra quelli inseriti.

Esercizio proposto 2.8.2. Il polinomio di quinto grado p(x)

p (x) = a0 + a1 · x + a2 · x2 + a3 · x

3 + a4 · x4 + a5 · x

5

puo essere rappresentato in C mediante il seguente array:

#define N 5

double a[N+1]

Scrivere una funzione

double eval(double p[], double x, int n);

che restituisca il valore del polinomio calcolato in x.

Suggerimento.Si utilizzi eventualmente la regola di Horner che nel caso di un polinomio di quinto grado si

esprime nel seguente modo.

p (x) = a0 + x · (a1 + x · (a2 + x · (a3 + x · (a4 + x · (a5)))))

2.9 I puntatori

Un puntatore non e altro che una variabile che contiene l’indirizzo di un’oggetto in memoria, comead esempio una variabile odu una funzione.

(v. 0.20)

Page 57: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 47

2.10 Domande

Conoscenze

1. Il linguaggio C viene da molti considerato un linguaggio di medio livello perche:

(a) non ha la potenza dei linguaggi ad alto livello perche non supporta istruzioni di elevatoformalismo;

(b) ha regole di scritture delle istruzioni decisamente semplificate rispetto ai linguaggi dialto livello;

(c) permette di utilizzare sia istruzioni di elevato formalismo sia istruzioni che lavoranodirettamente con i byte;

(d) e piu potente dell’assembly e consente di ottenre un codice oggetto piu compatto.

2. Cosa rappresenta una stringa nel linguaggio C ?

3. Scrivi il significato dei seguenti termini: identificatore, parola riservata, main.

4. Quali sono i tipi di dati fondamentali forniti dal C ?

5. In cosa consiste la rappresentazione in complemento a due e perche essa e importante neisistemi di calcolo automatico ?

6. Se pippo e una variabile, cosa rappresenta l’espressione &pippo ?

7. Cosa accade se viene eseguita la seguente riga di codice ? Perche ?

scanf("%c", &option);

8. Come si chiamano l’operatore = e l’operatore == ? Quale differenza passa tra di essi ?

9. Elenca gli operatori logici e i rispettivi simboli utilizzati nel linguaggio C.

10. Che differenza passa tra la dichiarazione di una funzione e la definizione di una funzione ?

11. Nel C un sottoprogramma e identificabile con il concetto di:

(a) Programma di assegnamento

(b) Funzione

(c) Procedura

(d) Funzione e procedura

12. Scrivi la definizione di prototipo di una funzione.

13. Scrivi le due modalita con cui possono essere passati gli argomenti a una funzione, specifi-cando le principali differenze tra di esse.

14. Che differenza passa tra una variabile globale ed una variabile locale ?

(v. 0.20)

Page 58: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

48 2.10. DOMANDE

Abilita

1. Scrivi l’output a video delle seguenti righe di programma.

char c = ’c’;

c = c ’a’;

printf("c = %c \n", c + ’d’);

printf("c = %d \n", c + ’d’);

2. Qual’e il valore numerico delle seguenti espressioni, tenendo conto che prima di essere valutatela variabile a vale 2 e la variabile b vale 3 ?

(a) (a == b)

(b) (a != b)

(c) (a = b)

(d) (a = 2)

3. Quante volte viene eseguito il seguente ciclo ?

int sum = 0, i = 0;

while(sum < 10)

{

sum = sum + i;

i++;

}

4. Quante volte viene eseguito il seguente ciclo ?

int sum = 10, i = 0;

while(sum > 0)

{

sum = sum - i;

i++;

}

5. Cosa fa il seguente programma ?

#include<stdio.h>

#include<stdlib.h>

int main(void)

{

int n, i = 0;

printf("Inserisci un numero: ");

scanf("%d", &n);

for(i=0;i<n;i++)

{

if((i%2) == 0)

printf(" %d ",i);

}

system("PAUSE");

return 0;

}

(v. 0.20)

Page 59: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 49

2.11 Esercizi

1. Indicare quale valore assumono le variabili a e b dopo l’esecuzione delle seguenti righe dicodice:

int a = 1, b = 2;

a = 1 + b++;

b = ++a;

2. Scrivere un programma che richiede il valore della velocita angolare in rad/s e la convertein giri/min, mostrandola poi a video.

3. Disegnare il diagramma di flusso che descrive le seguenti righe di codice:

scanf("%c", &option);

if(option == ’y’)

a++;

else

a--;

4. Disegnare il diagramma di flusso che descrive le seguenti righe di codice:

for(i=0;i<n;i++)

{

if((i%2) == 0)

printf(" %d ",i);

}

5. Disegnare il diagramma di flusso che descrive le seguenti righe di codice:

double s = 0;

scanf("%d", &n);

for(i=0;i<n;i++)

{

scanf("%d", &dato);

s = s + dato;

}

s = s/n;

6. Disegnare il diagramma di flusso che descrive le seguenti righe di codice:

scelta = input_scelta();

switch (scelta)

{

case ’s’:

printf("voglio studiare il linguaggio C");

break;

case ’n’:

printf("voglio giocare a carte con gli amici");

break;

default:

printf("Boh!");

break;

}

(v. 0.20)

Page 60: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

50 2.11. ESERCIZI

7. Un distributore e dotato di un validatore di monete che accetta monete da 1 e 2 euro. Per ognieuro inserito il validatore genera un impulso 1 di durata pari un ciclo. Quando il distributorerileva che sono stati introdotti almeno 2 euro esso genera un impulso della durata di un cicloche provoca l’erogazione di un prodotto. Si prenda come esempio le seguenti sequenze diingresso e di uscita

due monete da 1 euro 1 moneta da 2 euro

I 0100000001000 I 010100000000

U 0000000000010 U 000001000000

una moneta da 1 euro ed una da 2 euro

I 0100000101000

U 0000000001000

due monete da 1 euro con disturbo in mezzo

I 0100011001000

U 0000000000010

Disegnare il diagramma degli stati dell’automa e scrivere il codice C che implementa l’auto-ma.

[Soluzione]

In figura e riportato il diagramma degli stati dell’automa che risponde alle specifiche. Daldiagramma e relativamente semplice realizzare il codice della macchina a stati modificandoquello proposto nel paragrafo 2.6.7.

Figura 2.10: Diagramma a stati dell’esercizio 7.

Si puo eventualmente valutare di inserire uno stato iniziale (S0) in modo che si inizi ariconoscere le monete solo da quando in ingresso si rileva un passaggio per lo 0.

8. Scrivere la sequenza degli stati corrispondenti alle sequenze di ingresso proposte nell’esercizio7.

9. Scrivere un programma che calcola il modulo e fase di un vettore sul piano. Esso deve:

(a) accettare le componenti da tastiera;

(b) visualizzare sullo schermo i dati di ingresso e i risultati.

10. Scrivere un programma che calcola il modulo di un vettore nello spazio. Esso deve:

(a) accettare le componenti da tastiera;

(v. 0.20)

Page 61: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 2. PROGRAMMAZIONE IN C 51

(b) visualizzare sullo schermo i dati di ingresso e i risultati.

11. Calcolare la velocita media in m/s di un’auto che percorre uno spazio S in un tempo T. Ilprogramma deve:

(a) accettare i dati di ingresso S in ingresso e T in secondi da tastiera;

(b) visualizzare sullo schermo i dati di ingresso e i risultati.

12. Modificare il programma precedente in modo tale che il risultato venga espresso anche inkm/ora.

13. Dato il diagramma di attivita di figura 2.11 determinare il relativo codice sorgente in C edindicare cosa permette di determinare.

Figura 2.11: Esercizio 13.

14. Scrivere un programma che richiede come input le coordinate x,y,z e la massa di n puntimateriali, calcola il baricentro e lo mostra a video.

(v. 0.20)

Page 62: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

52 2.11. ESERCIZI

(v. 0.20)

Page 63: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Capitolo 3

I MICROCONTROLLORI PIC

Prerequisiti

• Conoscenza dei sistemi di numerazione binario ed esadecimale.

• Conoscenze di base sull’architettura di un microcontrollore.

• Conoscenze di base del linguaggio C.

• Nozioni elementari di elettronica.

Obiettivi didattici

• Conoscere l’architettura e le funzionalita principali del controllore PIC16F876.

• Saper modificare e programmare semplici programmi per il PIC.

3.1 Introduzione

Questo capitolo intende essere un tutorial per introdurre alla programmazione dei microcontrolloriPIC. In realta, quando ci si avvicina al mondo dei microcontrollori occorre fare subito la sceltadi quale microcontrollore utilizzare. In questo caso si e deciso di operare con il il PIC 16F876,versione piu evoluta del PIC 16F84. La scelta e stata condizionata dal fatto di avere a disposizionealcuni mini-robot economici prodotti dalla ditta Robot Factory di Chirgnago (VE)1.

Questi minirobot utilizzano tutti una scheda basata sul PIC 16F876, denominata motherboard,che puo essere programmata direttamente mediante la porta seriale e l’ausilio di PIC downloader,un programma freeware facilmente reperibile in internet.

3.2 Il microcontrollore PIC 16F876

I microcontrollori PIC si suddividono in tre grandi famiglie, in base alla lunghezza in bit delleistruzioni: 12 bit, 14 bit e 16 bit. In questi appunti si fara riferimento alla famiglia intermedia a14 bit (Mid-Range) ed in particolare al modello PIC16F876.

Questo microcontrollore, e con esso tutti quelli della famiglia Mid-Range, e dotato di alcunecaratteristiche generali quali:

• Architettura Harvard

• Istruzioni eseguite in un solo ciclo

• Set ridotto di istruzioni1www.robotfactory.it.

53

Page 64: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

54 3.2. IL MICROCONTROLLORE PIC 16F876

3.2.1 Harvard vs. Von Neumann

Nell’architettura Harvard la CPU accede alla memoria di programma (program memory) ed allamemoria dati (data memory) attraverso due bus separati, a differenza della tradizionale architet-tura Von Neumann in cui il programma e i dati vengono caricati dalle memorie attraverso lo stessobus, normalmente ad otto bit.

Figura 3.1: Architetture Harvard e Von Neumann

In questo modo si evita di avere il caricamento di una istruzione lunga piu di otto bit (situazionefrequente) in piu fasi e l’istruzione viene eseguita in un solo ciclo macchina(Single cicle instruc-tions). Inoltre viene incrementato il livello di parallelismo nella CPU (Figura 3.2): mentre unaistruzione viene eseguita (execute) l’istruzione seguente viene caricata (fetch). Questa peculiaritaviene tradizionalmente denominata Instruction Pipeline.

In realta non tutte le istruzioni vengono eseguite in un solo ciclo macchina. Ad esempiole istruzioni di branching richiedono due cicli macchina, uno per la sua esecuzione ed uno peril caricamento della prossima istruzione da eseguire, dipendente dall’esito della esecuzione dellaistruzione di branch.

Figura 3.2: La Pipeline delle istruzioni

Un ciclo macchina corrisponde a quattro cicli di clock. Ad esempio un PIC funzionante con unquarzo da 20 MHz impiega 200 ns ad eseguire una istruzione. Di questo aspetto e necessario tenerneconto quando, per specifiche esigenze, e necessario controllare nei dettagli il tempo impiegato dalmicro per esguire alcune operazioni.

Il PIC16F876 e un microcontrollore realizzato in tecnologia CMOS2, disponibile in packages3

da 28 pin.Il seguente schema a blocchi (Figura 3.3) rappresenta la struttura interna del microcontrollore.

In esso si possono intravvedere i registri e i dispositivi fondamentali, in precedenza discussi, comead esempio la ALU, il Program Counter, lo stack, ecc.

Nel micro sono presenti tre tipi diversi di memoria, ciascuno di essi e utilizzato per uno specificocompito.

2CMOS = Complementary Metal Oxide Silicium e una tecnologia utilizzata per realizzare i transistor presentinei circuiti integrati

3Contenitori

(v. 0.20)

Page 65: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 55

Tabella 3.1: Memorie del PIC16F876

Memoria dimensioni funzioneFLASH 8 KBytes programmaSRAM 368 Bytes dati volatiliEEPROM 256 Bytes dati non volatili

Figura 3.3: Diagramma a blocchi del PIC16F876.

(v. 0.20)

Page 66: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

56 3.2. IL MICROCONTROLLORE PIC 16F876

3.2.2 Il pinout

I 28 pin sono disponibili in due tipi diversi di packages, PDIP e SOIC. La mappatura dei pin,indipendente dal tipo di package, e riportata in figura 3.4.

Figura 3.4: Pinout del PIC16F876

La figura 3.5 mostra un sistema minimo realizzato con un 16F876. E’ evidente che tale si-stema non ha alcuna utilita da un punto di vista pratico poiche nessuno dei port di I/O sonoutilizzati. Esso mette pero in evidenza le connessioni assolutamente necessarie per permettere almicrocontrollore di poter funzionare.

Figura 3.5: Sistema minimo

In questo sistema minimo il cristallo Q1 e connesso ai pin OSC1/CLKIN e OSC2/CLKOUTin modo da stabilire una oscillazione costante, denominata clock, la cui frequenza dipende diret-tamente dal cristallo utilizzato. Tale oscillazione viene utilizzata internamente al microcontrollore

(v. 0.20)

Page 67: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 57

per scandire le varie attivita; ad esempio per eseguire una istruzione sono necessari quattro ciclidi clock.

Il pin MCLR/THV e l’ingresso Master Clear (Reset). Esso e collegato al circuito di reset eprovoca il RESET del microcontrollore in presenza di un segnale attivo basso. Il microcontrolloree dotato internamente di una logica interna di reset che serve a porre il dispositivo in uno statoiniziale ben determinato. In esso, tutti i registri e i pin di I/O del microcontrollore assumono unostato predefinito; in particolare il Program Counter viene azzerato. Appena il segnale di resetdiventa inattivo (da un livello basso di tensione passa ad un livello alto di tensione) la logica dicontrollo interna provvede ad eseguire il fetch dell’istruzione presente all’indirizzo 0 della memoriadi programma. Pertanto con la pressione del pulsante S1 di figura 3.5 viene imposta la riesecuzionedall’inizio del programma memorizzato nel microcontrollore.

I pin VSS (19 e 8) e VDD (20) forniscono l’alimentazione al microcontrollore. In particolareVSS e il riferimento di massa per la logica interna ed i pin di I/O (tensione di Source secondo,la denominazione tipica delle logiche CMOS), mentre VDD rappresenta l’alimentazione positivasempre per la logica interna e i pin di I/O. Il condensatore C1 applicato in prossimita di VDDsvolge la funzione di filtro, ovvero cerca di mantenere il piu possibile costante il livello della tensionedi alimentazione.

In particolare, il micro 16F876 deve essere alimentato con una tensione di 5V, con una tolleranzadel 10%.

Lo schema elettronico seguente e una variante del precedente a cui e stato aggiunto un minimodi funzionalita. Esso verra utilizzato come riferimento per la comprensione dei primi esempi diprogrammazione presenti in questo tutorial.

Figura 3.6: Secondo sistema minimale

Il pin RA1/AN1 (PORTA bit 1, Analog Input 1) in questo caso viene utilizzato come portdigitale di uscita per pilotare il buzzer SP1, mediante il transistor T1. Il pin 3, come anche tutti ipin da 2 a 6, puo essere anche configurato per funzionare come ingresso analogico di un convertitoreAD.

I pin RC3/SCK e RC4/SDI, facenti parti di PORTC, sono configurati come uscite digitalie pilotano due LED. Il pin RC3/SCK puo anche essere utilizzato come segnale di clock sia perdispositivi SPI4 o I2C.

4Serial Peripheral Interface

(v. 0.20)

Page 68: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

58 3.2. IL MICROCONTROLLORE PIC 16F876

3.2.3 Organizzazione della memoria

Per comprendere il funzionamento del PIC 16F876 e indispensabile conoscere la struttura internadella memoria e le funzioni svolte da alcuni dei registri. La memoria e suddivisa in memoria di

programma e in memoria dati. Questi due tipi di memoria fanno uso di un bus di comunicazioneseparato, in accordo con l’architettura Harvard. In questo modo l’accesso a ciascun blocco puoavvenire durante lo stesso ciclo di clock.

La memoria di programma e suddivisa in quattro pagine da 2K. La figura seguente mostrala memoria di programma insieme allo stack a 8 livelli e al Program Counter. Il PIC16F876, cometutti i micro PIC mid-range, ha un Program Counter formato da 13 bit in grado di indirizzareuna memoria di programma di dimensione pari a 8Kx14.

Figura 3.7: Architettura della memoria di programma

Per passare da un banco di memoria all’altro e necessario programmare la parte alta del PCtramite il registro speciale PCLATH5.

Alcuni compilatori C in versione dimostrativa, come ad esempio il PICCLITE della HiTech,permettono di operare solo con il primo banco di memoria.

La memoria dati si divide ulteriormente in memoria dati di tipo RAM e in memoria datidi tipo EEPROM. Tralasciando per ora la memoria EEPROM analizziamo la memoria RAM.Anch’essa si suddivide in due parti: da un lato i registri per uso speciale (SFR6) e dall’altro latola RAM per uso generale che contiene i registri per uso generale (GPR7).

I registri per uso speciale non possono essere utilizzati dal programmatore per inserirvi dei datigenerici, essi devono essere invece utilizzati per poter configurare il microcontrollore.

La memoria RAM e suddivisa in quattro banchi. Si accede a ciascun banco configurandoopportunamente i bit RP1 e RP0 presenti nel registro speciale STATUS.

Ciascun banco si estende fino all’indirizzo 7Fh, per un totale di 128 bytes. Le locazioni dimemoria agli indirizzi piu bassi sono riservate ai registri SFR, mentre agli indirizzi piu alti trovanoposto i registri GPR.

5Program Counter LATch High6Special Function Registers7General Purpose Registers

(v. 0.20)

Page 69: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 59

Figura 3.8: Mappa della memoria RAM

(v. 0.20)

Page 70: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

60 3.3. L’ASSEMBLY DEI PIC

3.3 L’assembly dei PIC

Il codice in assembler per i microcontrollori PIC puo essere generato con l’ausilio di un qualsiasieditor di testo in formato ASCII. Il codice assembler viene poi dato in pasto all’assemblatore.Ogni linea del codice sorgente puo contenere le seguenti quattro informazioni:

- Etichetta

- Istruzione, direttiva e macro

- Operando (o operandi)

- Commento

L’ordine e la posizione di queste informazioni e importante ai fini di una corretta programmazione.Le etichette vengono poste nella prima colonna, le istruzioni, le direttive e le macro nella secondacolonna, l’operando o gli operandi nelle colonne successive ed infine i commenti alla fine. Levarie parti vengono separate da spazi bianchi o caratteri di tabulazione, in particolare i commentiiniziano sempre con un punto e virgola.

Figura 3.9: Prime righe di assembler.

I valori numerici possono essere espressi utilizzando diverse notazioni, come si puo notare daiseguenti esempi.

MOVLW 20 ;decimale - carica nell’accumulatore (W) il numero 20;

MOVLW 14h ;esadecimale - idem

MOVLW 0x14 ;esadecimale - idem

MOVLW 0B00010100 ;binario - idem

3.3.1 I registri per uso speciale

Prima di addentrarsi nella programmazione in assembler verranno esposti alcuni esempi elementaridi programmazione che permettono di operare con alcuni dei principali registri speciali.

Registro W Il registro W, denominato anche accumulatore, e una locazione di memoria RAMcomposta da 8 bit direttamente connessa alla ALU.

Il registro W si differenzia dagli altri registri, compresi quelli speciali, perche la ALU quandosvolge delle operazioni lo utilizza sia come operando che come destinazione del risultato. Il registroW viene usato spessissimo anche per un altro motivo. Si supponga di voler scrivere nella locazionedi memoria di indirizzo 0x20 della RAM il valore 0xAA. Analizzando il set di istruzioni del PIC sinota che non esiste un’unica istruzione in grado di effettuare questa operazione. Essa deve esserenecessariamente effettuata in due passi, utilizzando le due seguenti istruzioni:

MOVLW 0x01 ; carica il valore 0x01 nell’accumulatore

MOVWF 0x20 ; carica il contenuto dell’accumulatore nel file register di indirizzo 0x20

(v. 0.20)

Page 71: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 61

Esiste un motivo per questa limitazione. Per codificare in una unica istruzione le due precedentiistruzioni servirebbero

8 bit per specificare il valore che si intende inserire 7 bit per specificare l’indirizzo della locazionedi memoria destinazione del dato 5 bit per codificare l’istruzione tra le 32 del set del PIC

per un totale di 20 bit.

Program Counter Il PIC utilizza un registro speciale, il Program Counter, per memorizzarel’indirizzo della prossima istruzione che deve essere eseguita. Questo registro, nel caso specifico delPIC 16F876, e composto da 13 bit quanti sono necessari per indirizzare una memoria di programmada 8 KWords. Questo registro viene automaticamente incrementato ad ogni istruzione eseguita.Esistono pero alcune istruzioni, come ad esempio GOTO e CALL che permettono di cambiare lasequenza di esecuzione delle istruzioni e di saltare in un altro punto del programma, andandoproprio a modificare il contenuto del Program Counter.

TRISA (85h), TRISB (86h) e TRISC (87h) Le linee delle porte A, B e C possono esseresingolarmente utilizzate come ingressi od uscite. I registri TRISA, TRISB e TRISC servono perstabilire quali delle linee delle rispettive porte debbono essere considerate di ingresso e quali diuscita. I singoli bit di questi due registri devono essere posti ad 1 se si vuole che il corrispondenteport funzioni come ingressi, altrimenti a 0 se il porte deve funzionare come uscita.

Esempio 3.3.1. Il seguente esempio imposta i port RC3 ed RC4 come uscite ed i restanti portcome ingressi.

Soluzione.

MOVLW E7h ;carica il numero E7h (L\footnote{L come Literal.}) nell’accumulatore (W);

TRIS 07h ;carica il contenuto dell’accumulatore nel registro TRISC

Il dato di configurazione (14h) deve essere posto prima nell’accumulatore e poi spostato nelregistro TRISC. Si noti che l’istruzione TRIS utilizza l’indirizzo 07h, quello del registro PORTC,invece dell’indirizzo 87h del registro TRISC, come ci si potrebbe aspettare.

PORTA (05h), PORTB (06h) e PORTC (07h) Questi registri permettono di leggere i datipresenti in ingresso o di impostare i dati in uscita delle porte A, B e C.

Esempio 3.3.2. Dopo aver configurato la porta C come nell’esempio precedente, si pongano allivello alto tutte le linee configurate come uscite.

Soluzione.

MOVLW 0Bh ;carica il numero 14h nell’accumulatore (W)

MOVWF 07h ;carica il contenuto di W nel registro PORTA

I dati messi nelle porte utilizzate come entrate sono ininfluenti.

Per leggere il contenuto di un port si puo utilizzare l’istruzione MOVF. La seguente istruzionecopia il contenuto del port A (05h) nell’accumulatore identificato dal numero 0.

MOVF 05h, 0

(v. 0.20)

Page 72: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

62 3.4. IL PRIMO PROGRAMMA IN ASSEMBLER

STATUS (03h) E’ uno dei registri piu importanti. Esso contiene i flag Z (zero), C (carry) e DC(digit carry). Mediante i bit RP0 e RP1 si possono selezionare i banchi 0, 1, 2 e 3 della memoriadati.

Esempio 3.3.3. Configurare i port RC3 ed RC4 come uscite e le restanti linee della porta C comeingressi senza fare uso dell’istruzione TRIS. Poi porre a livello alto le due linee configurate comeuscite.

Soluzione.Il banco 1 della memoria dati, dove si trova il registro TRISC, viene selezionato mettendo ad

1 RP0, il quinto bit del registro STATUS: SI utilizza poi l’offset 07h relativo all’inizio del bancoper scrivere sul registro TRISC, e non 87h.

BSF 03h, 5 ; pone a 1 il bit 5 del registro STATUS (03h)

MOVLW E7h ; carica nell’accumulatore (W) il numero E7h

MOVWF 07h ; carica il contenuto di W nel registro TRISC

BCF 03h, 5 ; pone a 0 il bit 5 del registro STATUS (03h)

MOVLW 14h ;carica il numero 0Bh nell’accumulatore (W);

MOVWF 07h ;carica nel registro PORTC il contenuto dell’accumulatore

3.4 Il primo programma in assembler

Quello che segue e un esempio di un programma in assembler completamente funzionante. Essoviene proposto anche se buona parte delle istruzioni e direttive presenti non sono state approfon-dite. D’altronde, da un punto di vista didattico, i linguaggi di programmazione vengono compre-si piu agevolmente attraverso l’analisi di esempi funzionanti piuttosto che l’esposizione rigida esequenziale di tutte le istruzioni, le direttive e le regole sintattiche.

Questo programma e ideato per operare con l’hardware esposto nei precedenti paragrafi. Essoconfigura il port RC3 come uscite e poi esso commuta l’uscita RC3 da 0 (tensione VSS) a 1(tensione VDD) e viceversa. In questo modo si rende disponibile sul pin 15 del microcontrolloreun segnale elettrico quadro che puo essere eventualmente visualizzato mediante un oscilloscopio.L’analisi delle forme d’onda con l’oscilloscopio permette anche una stima sufficientemente accuratadei tempi di esecuzione delle istruzioni.

list p=16f876 ; direttiva che definisce il microprocessore

include <p16f876.inc> ; direttiva di inclusione di un file di testo

ORG 0x000 ; direttiva che stabilisce l’indirizzo

CLRF PCLATH ; azzera i bit di pagina

GOTO init ; salta all’inizio del programma

ORG 0x010 ; salta l’interrupt vector

init MOVLW 0xF7 ; fase di inizializzazione del micro

TRIS PORTC ; poni RC3 come uscita

MOVLW 08h ;

MOVWF PORTC ; alza RC3

loop BCF PORTC, 3 ; abbassa RC3

BSF PORTC, 3 ; alza RC3

GOTO loop

END ; direttiva che indica il termine del programma

(v. 0.20)

Page 73: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 63

Analizziamo ora con certosina pazienza, riga per riga, il nostro programma. Osserviamo laprima riga di codice:

list p=16f876 ; direttiva che definisce il microprocessore

Essa e un direttiva che indica per quale microcontrollore e stato scritto il codice seguente. Le di-rettive non sono delle istruzioni che il compilatore traduce in codice operative, ma delle indicazionirivolte al compilatore per influenzarne il funzionamento durante la compilazione. Le direttive sonomolto simili ai comandi del preprocessore utilizzati nel C.

include <p16f876.inc> ; direttiva di inclusione di un file di testo

Questa direttiva provoca l’inclusione nel sorgente del contenuto del file p16f876.inc, fornito dallaMicrochip, e presente in una directory dell’installazione di MPLAB. Il file p16f876.inc contiene gliindirizzi dei vari registri utilizzati, individuati da nomi come PCLATH e PORTC definiti a lorovolta mediante l’uso della direttiva all’assemblatore EQU nel file di testo p16f876.inc. Questa diret-tiva non e strettamente indispensabile. Nulla vieta un programmatore dall’utilizzare dierttamentei valori numerici degli indirizzi dei vari registri. E’ pero evidente che il lavoro di programmazione,di per se gia abbastanza difficoltoso, diventerebbe anocora piu insopportabile.

ORG 0x000 ; direttiva che stabilisce l’indirizzo

La direttiva ORG consente di definire l’indirizzo della memoria di programma da cui si vuole che ilcompilatore inizi a memorizzare il codice operativo delle istruzioni che seguono.

CLRF PCLATH ; azzera i bit di pagina

Questa e la prima vera istruzione. Il codice mnemonico CLRF significa CLeaR File register.Obiettivo di questa istruzione e l’azzeramento del registro PCLATH8 Nel nostro caso l’istruzioneCLRF PCLATH impone di lavorare con il primo banco di memoria Flash.

GOTO init ; salta all’inizio del programma

Subito dopo l’esecuzione di questa istruzione la prossima istruzione ad essere eseguita e quellacontenente la label9 init. L’istruzione GOTO e un esempio di salto incondizionato (unconditionalbranch); esso permette di saltare direttamente ad un qualsiasi punto all’interno della memoria diprogramma. Il termine incondizionato sta ad indicare che il salto viene effettuato in qualsiasi caso,a differenza di altre istruzioni di salto in cui il salto viene effettuato solo se una certa condizione esoddisfatta. L’istruzione GOTO, come e spiegato bene a pag.139 di [2], per svolgere la sua attivitaagisce sul contenuto del Program Counter.

ORG 0x010 ; salta l’interrupt vector

Questa direttiva, come la precedente, impone all’assemblatore di memorizzare le istruzionisuccessive dall’indirizzo 0x010 in poi. A questo punto del nostro percorso puo risultare pocochiaro il motivo di questa scelta. possiamo solo anticipare che essa e stata dettata dalla volontadi lasciare libera la locazione di memoria di indirizzo 0x04. Essa e infatti l’indirizzo di partenzadell’interrupt handler10, ovvero la parte di programma che deve gestire gli interrupt, un argomentoche svilupperemo piu avanti.

8Program Counter LATch High. Durante l’esecuzione di una istruzione CALL o di una istruzione GOTO i cinquebit meno significativi di PCLATH vengono caricati nella parte alta del Program Counter (PCH). Non entrandotroppo in dettaglio [2] possiamo dire che il registro PCLATH permette di passare da una pagina all’altra dellamemoria Flash in cui viene memorizzato il programma. In realta questa e solo una precauzione legata all’uso delbootloader perche dopo un reset il registro PCLATH ed i bit piu significativi del Program Counter dovrebberoessere tutti azzerati.

9Etichetta.10Gestore di interrupt.

(v. 0.20)

Page 74: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

64 3.4. IL PRIMO PROGRAMMA IN ASSEMBLER

init MOVLW 0xF7 ; fase di inizializzazione del micro

L’istruzione MOVLW11 carica il dato 0xF7 nell’accumulatore (W). Questa istruzione preparal’istruzione successiva in cui si carichera il contenuto dell’accumulatore in uno specifico registro.

TRIS PORTC ; poni RC3 come uscita

Sappiamo gia il significato di questa istruzione. Essa carica il contenuto dell’accumulatore nelregistro TRISC, che contiene i data direction bits, i bit che impongono la configurazione comeingresso o come uscita delle linee del port C. Se diamo un’occhiata al set di istruzioni del PIC16F876 notiamo che questa istruzione non viene riportata, ed inoltre se assembliamo il precedenteprogramma con ogni probabilita noteremo un messaggio di avvertimento che informa che l’usodell’istruzione TRIS e fortemente sconsigliato, pena eventuali future incompatibilita. Per questa eforse l’ultima volta che vedremo utilizzata questa istruzione e d’altronde abbiamo gia intravvistoun modo alternativo e piu corretto di configurare i port.

MOVLW 08h

L’istruzione MOVLW si limita a caricare il dato 0x08 nell’accumulatore. Anche questa istruzionee strettamente connessa alla successiva istruzione.

MOVWF PORTC ; alza RC3

L’istruzione MOVWF carica il contenuto dell’accumulatore nel registro PORTC. In questo modoil pin RC3 del PIC passa da un livello basso ad un livello alto. Contemporaneamente tutti gli altribit del port C vengono messi a zero, ma questo non e un problema perche sono configurati comeingressi, e quindi non rischiamo eventuali conflitti hardware, e non sono attualmente utilizzati peraltri scopi.

A questo punto e terminata la fase di inizializzazione del microcontrollore ed inizia l’esecuzionedella parte ciclica del nostro programma.

loop BCF PORTC, 3 ; abbassa RC3

L’istruzione BCF12 mette a zero il bit di peso 3 del registro PORTC. Ovvero abbassa il livellodi tensione della linea RC3.

BSF PORTC, 3 ; alza RC3

L’istruzione BSF13 effettua l’esatto contrario dell’istruzione precedente e pertanto mette a uno ilbit di peso 3 del registro PORTC, elevando cosı il livello di tensione della linea RC3.

GOTO loop

L’ultima istruzione riporta l’esecuzione all’inizio del loop. In questo modo le ultime treistruzioni del programma verranno eseguite per un tempo indefinito.

END ; direttiva che indica il termine del programma

L’ultima riga del programma e la direttiva END che comunica all’assemblatore la conclusionedel programma.

11MOVe Literal to W12Bit Clear F13Bit Set F

(v. 0.20)

Page 75: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 65

3.4.1 Scrittura, assemblaggio, simulazione e debugging del primo pro-gramma

Il programma presentato nel precedente paragrafo puo essere editato, assemblato e simulato lavo-rando con l’ambiente integrato di MPLAB. In questo testo si fa riferimento alla versione 8.00 diMPLAB o successive.

Dopo che il programma e stato assemblato nella finestra Program memory di MPLAB si puoosservare il codice oggetto, od object code, ovvero la sequenza delle word che verranno memorizzatenella memoria di programma del PIC. Nel nostro caso il programma consiste di 9 word da 14 bitciascuna, evidenziate nella seguente tabella.

Address Opcode Disassembly

0000 018A CLRF 0x0A

0001 2810 GOTO 0x10

0010 30F7 MOVLW 0xF7

0011 0067 TRIS 0x07

0012 3008 MOVLW 0x08

0013 0087 MOVWF 0x07

0014 1187 BCF 0x07, 0x03

0015 1587 BSF 0x07, 0x03

0016 2814 GOTO 0x14

Durante la compilazione del nostro programma, l’assemblatore genera una serie di files aventilo stesso nome del sorgente da noi editato ma aventi una diversa estensione. Vediamo alcuni diessi:

*.lst E’ un file di testo contenente il codice sorgente e la corrispondente traduzione in codiceoggetto. Esso e molto utile per comprendere come il compilatore allocca le varie risorsenecessarie al programma. In esso troviamo proprio le informazioni riportate nella precedentetabella.

*.hex Questo file contiene il codice oggetto del programma codificato in un formato introdottodalla Intel. Essendo in formato ASCII, esso e visionabile mediante un comune editor ditesti.

Esempio 3.4.1. Determinare il codice oggetto della seguente istruzione.

BCF 07h, 4

Soluzione. L’istruzione precedente azzera il bit di peso 4 del registro di indirizzo 7 del banco dimemoria RAM attualmente selezionato. Per determinare l’object code dell’istruzione e necessarioconsultare il paragrafo 13.0 di [2]. Osservando la tabella 13-2 (PIC16F87X INSTRUCTION SET)si nota che l’istruzione precedente e codificata nel seguente modo:

Mnemonico ed operandi BCF f,b

Descrizione Bit Clear f

Opcode 14-bit 01 00bb bfff ffff

Nel nostro caso i 3 bit bbb, che rappresentano l’indirizzo del bit all’interno del registro, valgono100 mentre i 7 bit fffffff, che rappresentano l’indirizzo del registro all’interno del banco, valgono0001111.

Per cui l’opcode dell’istruzione assume il seguente valore binario

01 0010 0000 0111

(v. 0.20)

Page 76: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

66 3.4. IL PRIMO PROGRAMMA IN ASSEMBLER

corrispondente in esadecimale al valore 1207h.

Esercizio proposto 3.4.1. Determinare il codice oggetto delle seguenti righe di codice:

ORG 0x020 ; imposta l’indirizzo in flash

loop BCF PORTA, 1 ; abbassa RA1

BSF PORTA, 1 ; alza RA1

GOTO loop

Per effettuare la simulazione del programma :

• dal menu debugger - select tool scegliere lo strumento MPLAB SIM

• dal menu debugger - scegliere l’opzione Animate

Dopo aver effettuato le precedenti impostazioni e possibile anche visualizzare l’andamento dellatensione sul pin RC3 mediante lo strumento Simulator Logic Analizer che si rende disponibileall’interno del menu View dopo che e stato configurato il simulatore.

Figura 3.10: Il segnale RC3 visto dal Simulator Logic Analizer.

Osservando la finestra del simulator logic analizer (figura 3.10) si nota che il segnale prodottoha un livello alto che dura un ciclo macchina mentre il livello basso dura 3 cicli macchina. Pertantoabbiamo ottenuto un segnale rettangolare avente un periodo pari a 4 cicli macchina ed un dutycicle14 del 25%. Possiamo renderlo un segnale quadro infarcendolo con l’istruzione NOP15 in cuiil micro non fa nulla, se non perdere tempo, in pratica una istruzione inutile, tanto inutile che iprogettisti hanno pensato di introdurla nel ridotto set di istruzioni del PIC.

Esercizio proposto 3.4.2. Modificare il programma precedente in modo tale che generi un segnalequadro di frequenza pari a 100 kHz, sapendo che viene utilizzato un quarzo da 4 MHz.

Esercizio proposto 3.4.3. Rispettare le consegne dell’esercizio precedente sapendo che il quarzoutilizzato e da 20 MHz.

Esercizio proposto 3.4.4. Provare entrambi gli esercizi precedenti con il simulatore e l’analiz-zatore logico integrati in MPLAB.

14Il duty cicle δ, o ciclo utile, di un segnale rettangolare e il rapporto tra la durata TH del livello alto e il suoperiodo T.

15Not OPerate.

(v. 0.20)

Page 77: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 67

Una volta effettuata la simulazione il programma puo essere provato nel sistema target, ovverola motherboard di cui si e accennato in precedenza. Si possono utilizzare fondamentalmente trestrumenti per caricare il programma:

• bootloader;

• programmatore;

• emulatore.

Nel primo caso si deve aver precedentemente caricato nella memoria flash del microcontrolloreun piccolo programma denominato bootloader. Questo programma, dopo che il sistema e statoresettato, e in grado di colloquiare, mediante una connessione seriale RS232, con un altro pro-gramma residente nel personal computer, denominato downloader. Al downloader bisogna passareil file con estensione .hex prodotto dall’assemblatore dopo la compilazione.

Con questo piccolo programma pilotiamo un diodo led con un segnale rettangolare a frequenzamolto elevata. Con la nostra vista non e possibile percepire il lampeggio dei led ma se applichiamole sonde di un oscilloscopio in corrispondenza dell’uscita RC3 e possibile visualizzare la formad’onda generata dal programma e poter effettuare delle misure di tempo su di essa.

Esercizio proposto 3.4.5. Calcolare il periodo ed il duty cicle del segnale rettangolare generatoin uscita da RC3 e confrontarlo con quanto visualizzato dall’oscilloscopio.

Esercizio proposto 3.4.6. Modificare il programma precedente in modo tale che si accendano espengano in modo alternato due led, uno pilotato da RC3 el’altro da RC4.

3.5 Il primo programma in C

Il PIC, oltre che in assembler, puo essere programmato anche in C. E’ necessario disporre alloradi un cross-compilatore per la propria piattaforma di sviluppo.

Uno dei cross-compilatori per PIC piu diffusi e quello prodotto dalla HiTech, disponibile anchein una versione Lite gratuita per uso didattico ed hobbistico.In questa sede si fara riferimento adesso qualora si rende necessario approfondire aspetti legati alla particolare implementazione delcompilatore. Questo compilatore, inoltre, si integra facilmente con l’ambiente di sviluppo MPLAB.

Vediamo subito la versione in C del nostro primo programma realizzato in assembler, visto neiprecedenti paragrafi.

#include <pic.h>

main()

{

TRISC = 0b11110111; // poni RC3 come uscita

PORTC = 0x08; // alza RC3

while(1) { //loop continuo

PORTC = PORTC & 0xF7; // abbassa RC3

PORTC = PORTC | 0x08; // alza RC3

}

}

(v. 0.20)

Page 78: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

68 3.5. IL PRIMO PROGRAMMA IN C

Analizziamo anche in questo caso il programma riga per riga, o quasi.

#include <pic.h>

La direttiva include inserisce le dichiarazioni presenti nell’header file pic.h. Esso si trovanella directory include, una delle directory generate dall’installazione del compilatore, e, in modoindiretto, definisce i vari registri del PIC tra cui anche TRISC e PORTC.

PORTC = PORTC & 0xF7; // abbassa RC3

In questa istruzione e presente l’operatore &. Esso effettua un AND bit a bit tra i bit di ugualepeso degli operandi PORTC e 0xF7. In questo modo si costringe a 0 il bit di peso 3, mentre glialtri restano invariati.

PORTC = PORTC | 0x08; // alza RC3

In questa istruzione e presente l’operatore —. Esso effettua un OR bit a bit tra i bit di ugualepeso degli operandi PORTC e 0x08. In questo modo si pone a 1 il bit di peso 3, mentre gli altrirestano invariati.

Dopo aver compilato il precedente programma mediante il compilatore C integrato con MPLABe interessante andare a vedere la traduzione in assembler effettuata dal compilatore stesso, ovveroil suo disassemblato. Esso e visibile segliendo l’opzione Disassemby listing dal menu View diMPLAB.

Analizzando il disassemblato si nota che l’istruzione

TRISC = 0b11110111; // poni RC3 come uscita

e stata tradotta in ben 4 istruzioni

MOVLW 0xf7

BSF 0x3, 0x5

BCF 0x3, 0x6

MOVWF 0x7

La prima istruzione carica il byte 0xF7 (0b11110111 in binario) nell’accumulatore, le dueistruzioni successive pongono i bit RP1:RP0 a 01 in modo da selezionare il banco 1 dove si trovail registro TRISC. L’ultima istruzione copia il contenuto dell’accumulatore nel registro TRISC,il cui indirizzo all’interno del banco 1 e proprio 0x7. Lo stesso effetto poteva essere ottenutocon l’istruzione TRIS 0x7 ma i progettisti del compilatore hanno sicuramente preferito seguire ilconsiglio dei progettisti della Microchip.

L’istruzione

PORTC = PORTC & 0xF7; // abbassa RC3

e stata tradotta prevedibilmente nella seguente istruzione bit oriented.

BCF 0x7, 0x3

mentre l’istruzione

PORTC = PORTC | 0x08; // alza RC3

e stata tradotta nella istruzione

BSF 0x7, 0x3

(v. 0.20)

Page 79: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 69

Infine il loop continuo implementato dell’istruzione while(1) e realizzato grazie all’istruzioneGOTO.

Dopo questa breve analisi sono evidenti due dei punti di forza del linguaggio C rispettoall’assembler: la leggibilita del codice unita alla possibilita di operare sui singoli bit.

Esercizio proposto 3.5.1. Modificare il programma in C in modo da ottenere un segnale quadrodi periodo pari a 10 cicli macchina.

Esercizio proposto 3.5.2. Modificare il programma precedente in modo tale che si accendano espengano in modo alternato due led, uno pilotato da RC3 e l’altro da RC4.

Esercizio proposto 3.5.3. Provare entrambi gli esercizi precedenti con il simulatore e l’analiz-zatore logico integrati in MPLAB.

3.6 Temporizzazioni e routine - Secondo programma in as-

sembler

Come abbiamo incominciato ad intravvedere nei precedenti esempi, una delle caratteristiche piuinteressanti della programmazione dei microcontrollori e la possibilita di definire con precisione itempi di esecuzione del codice. Con un quarzo da 20 MHz cinque istruzioni NOP generano unritardo di 1 microsecondo e nel caso del precedente programma nell’uscita RC3 e presente unsegnale rettangolare di periodo pari a 800 ns con un duty cicle del 25%.

Se si presenta la necessita di introdurre ritardi dell’ordine dei millisecondi o dei secondi eevidente che non si puo inserire una serie di istruzioni NOP ma occorre seguire un’altra strada.

Un esempio di soluzione consiste nell’introdurre un ciclo, che esegua con l’ausilio di pocheistruzioni una serie molto lunga di NOP.

counter EQU 0x20 ;primo registro libero nel 16F876

;istruzioni ...

MOVLW 0x64 ;

MOVWF counter ; carica 100 nella variabile delay

ciclo NOP

DECFSZ counter, 1

GOTO ciclo

;altre istruzioni ....

Il precedente ciclo di ritardo impiega 4 cicli macchina ogni volta che viene effettuato, ed essoviene effettuato il numero di volte impostato nella variabile counter.

Nelle precedenti righe di codice sono presenti due novita.La prima e rappresentata dalla definizione della variabile counter attraverso la direttiva EQU

che assegna alla locazione di memoria di indirizzo 0x20 il nome counter. L’indirizzo 0x20 non ecasuale; esso e il primo registro di uso generale disponibile.

La seconda novita e rappresentata dalla seguente istruzione16

16DECrement f, Skip if Zero

(v. 0.20)

Page 80: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

70 3.6. TEMPORIZZAZIONI E ROUTINE - SECONDO PROGRAMMA IN ASSEMBLER

DECFSZ delay, 1

Il contenuto del registro counter viene decrementato. Se il secondo parametro e 1, comein questo caso, il risultato e rimesso nel registro counter. Se il risultato del decremento e 0l’istruzione successiva viene saltata. Nel nostro caso l’istruzione successiva e il GOTO che mantieneil ciclo; saltare tale istruzione equivale a terminare il ciclo.

L’istruzione DECFSZ dura ciclo macchina quando il risultato del decremento non e 0, e quindinon viene effettuato lo skip17, mentre dura due cicli macchina quando il risultato e nullo e quindiviene effettuato il salto.

Il ciclo precedente dura in tutto 401 cicli macchina, ottenuti in base al seguente conteggio.

istruzione cicli macchina

-------------------------------------------

MOVLW 0x64 1

MOVWF counter 1

ciclo NOP 1*100

DECFSZ counter,1 1*99+2

GOTO ciclo 2*99

-------------------------------------------

totale 401

Esercizio proposto 3.6.1. Inserire in un programma il ritardo precedente e verificare con ilsimulatore di MPLAB il ritardo ottenuto.

Suggerimento.Evitare di mettere numeri molto grandi nella variabile delay ed utilizzare lo strumento dei

breakpoint.

Se si vogliono ottenere ritardi di ordine di grandezza piu elevati si puo innestare un ciclo diritardo dentro un altro ciclo in modo da moltiplicare la durata del ciclo piu interno per il numerodi volte che viene eseguito il ciclo piu esterno. Il seguente programma implementa un doppio ciclodi ritardo composto da un ciclo esterno associato all’etichetta ciclo1 e da un ciclo, interno alciclo precedente, associato all’etichetta ciclo2.

list p=16f876 ; direttiva che definisce il microprocessore

#include <p16f876.inc> ; direttiva di inclusione di un file di testo

counter1 EQU 0x20 ; variabile utilizzata dalla routine delay

counter2 EQU 0x21 ; variabile utilizzata dalla routine delay

ORG 0x000 ; direttiva che stabilisce l’indirizzo

CLRF PCLATH ; azzera i bit di pagina

GOTO init ; salta all’inizio del programma

ORG 0x010 ; salta interrupt vector location

init MOVLW 0xE7 ; fase di inizializzazione del micro

BSF STATUS, 5 ; imposta banco 1

BCF STATUS, 6

MOVWF 0x07 ; poni RC3 e RC4 come uscite

BCF STATUS, 5 ; reimposta banco 0

17Salto.

(v. 0.20)

Page 81: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 71

MOVLW 08h ;

MOVWF PORTC ; alza RC3 e abbassa RC4

loop BCF PORTC, 3 ; abbassa RC3

CALL delay ; chiama routine delay

BSF PORTC, 3 ; alza RC3

CALL delay ; chiama routine delay

GOTO loop

;*****************************************************************

delay MOVLW 0xC8 ; carica 200 nell’accumulatore W

MOVWF counter1 ; carica il contenuto di W in counter1

ciclo1 MOVLW 0xC8 ; carica 200 nell’accumulatore W

MOVWF counter2 ; carica il contenuto di W in counter2

ciclo2 DECFSZ counter2, 1

GOTO ciclo2

DECFSZ counter1, 1

GOTO ciclo1

RETURN

END ; direttiva che indica il termine del programma

Nel precedente programma e presente la definizione della routine delay. La sua definizioneinizia con l’etichetta delay, che denomina l’indirizzo di partenza della routine, e termina conl’istruzione RETURN.

La routine delay e utilizzata, o meglio e chiamata all’interno del ciclo principale loop mediantel’istruzione CALL. Questa istruzione funziona in modo simile all’istruzione GOTO. Anch’essa, infatti,permette di scrivere nel Program Counter un nuovo indirizzo, ma provoca prima della scritturaanche il salvataggio del contenuto precedente del program Counter in un quell’area di memoriadenominata stack. L’indirizzo memorizzato nello stack viene poi recuperato, una volta terminatal’esecuzione della routine, mediante l’esecuzione dell’istruzione RETURN.

Lo stack del PIC 16F876 e dotato di otto registri. Grazie a questo fatto e possibile effettuarefino ad otto chiamate di subroutine, annidate una dentro l’altra.

L’assenza della istruzione RETURN nella definizione di una subroutine non viene rilevata comeerrore dall’assemblatore. Questo errore e molto pericoloso perche a volte puo essere difficilementerilevabile.

Esercizio proposto 3.6.2. Determinare la durata della seguente routine di ritardo iptizzando diutilizzare un quarzo da 4 MHz.

delay MOVLW 0x10

MOVWF counter1 ; carica il contenuto di W in counter1

ciclo1 DECFSZ counter, 1

GOTO ciclo1

RETURN

Suggerimento. Ricordarsi che l’istruzione DECFSZ dura due cicli macchina, invece di 1, quandonon viene effettuato lo skip e che l’istruzione GOTO viene effettuata una volta di meno.

(v. 0.20)

Page 82: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

72 3.7. TEMPORIZZAZIONI E FUNZIONI - SECONDO PROGRAMMA IN C

Esercizio proposto 3.6.3. Provare il precedente programma con il simulatore di MPLAB cari-cando prima valori molto bassi in delay1 e delay2, e poi valori molto alti. Tarare i valori di delay1e di delay2 in modo da ottenere una durata per la routine delay dell’ordine di 10 ms con un quarzoda 20 MHz

Suggerimento.Utilizzare dei BreakPoints unitamente allo strumento StopWatch disponibile all’interno del

menu Debugger.

Esercizio proposto 3.6.4. Qual’e il massimo ritardo ottenibile con la routine delay limitandosia modificare i valori caricati in counter1 e counter2 ?

Esercizio proposto 3.6.5. Modificare la routine delay in modo da ottenere un ritardo di 100ms.

3.7 Temporizzazioni e funzioni - Secondo programma in C

Se sono stati svolti gli esercizi del paragrafo precedente si sara notato quanto sia laborioso ottenereun ritardo molto grande, dell’ordine dei decimi di secondo. Lo stesso compito puo essere risoltopiu agevolmente con il seguente esempio in C. In questo caso e stata definita una funzione delay()che fa uso di una variabile intera counter.

#include <pic.h>

void delay(void); // dichiarazione funzione delay

main()

{

TRISC = 0b11110111; // poni RC3 come uscita

PORTC = 0x08; // alza RC3

while(1) { //loop continuo

PORTC = PORTC & 0xF7; // abbassa RC3

delay(); // chiama funzione delay

PORTC = PORTC | 0x08; // alza RC3

delay(); // chiama funzione delay

}

}

void delay(void) // definizione funzione delay

{

unsigned int counter = 65000;

while(counter)

{

counter--;

}

}

(v. 0.20)

Page 83: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 73

Esercizio proposto 3.7.1. Modificare la routine delay in modo da ottenere un ritardo di 1 s.

3.8 Timer ed interruzioni

In realta il modo di produrre dei ritardi visto nel paragrafo precedente, ottenuto impegnando ilmicro nell’esecuzione di migliaia di operazioni fondamentalmente inutili, puo essere utilizzato soloquando non e richiesta l’esecuzione di altri compiti, situazione questa che accade molto raramente.

Un modo piu elegante ed allo stesso tempo piu efficiente per effettuare temporizzazioni con imicrocontrollori consiste nell’utilizzare uno dei timer appositamente presenti al loro interno.

Il PIC 16F876 mette a disposizione tre timer: timer0, timer1 e timer2. Il primo e un timer a8 bit, mentre gli altri due sono timer a 16 bit.

Nei prossimi esempi si fara uso in particolare del timer1, di cui ora daremo una descrizionesommaria.

Il Timer1 e una periferica che puo funzionare sia da timer che da contatore, basata su dueregistri ad 8 bit (TMR1H e TMR1L) che possono essere scritti e letti separatamente dal pro-gramma. Essi formano insieme il registro a 16 bit TMR1, il cui contenuto viene incrementatoautonomamente da una sorgente interna (funzionamento come timer) oppure da una sorgenteesterna (funzionamento come contatore).

Una volta raggiunto il valore 65535, pari a FFFFh, al prossimo incremento il registro TMR1 vieneazzerato automaticamente e il conteggio riprende da 0. Questo evento e denominato overflow18

ed esso scatena un interrupt segnalato dal bit TMR1IF (Timer 1 Interrupt Flag).Indichiamo con Tint il tempo che intercorre tra due eventi di overflow e quindi tra due chiamate

consecutive della routine di interrupt: Esso e pari a:

Tint = (65535− TMR1) · 4 · p · TOSC (3.1)

dove TMR1 e il valore che viene caricato nel registro del Timer1 dalla riutine di interrupt,TOSC e il periodo del clock interno, p e il fattore di riduzione impostato nel prescaler.

Esplicitando la relazione precedente rispetto a TMR1 si ottiene il valore da impostare nelregistro omonimo.

TMR1 = 65535−Tint

4 · p · TOSC

Il seguente esempio fa uso del timer 1 per introdurre un ritardo.

list p=16f876 ; list directive to define processor

#include <p16f876.inc> ; definizione variabili specifiche processore

; *** definizione variabili *******************************************

cont1 EQU 0x020 ; contatore

led EQU 0x021 ; stato del led

ORG 0x000 ; processor reset vector

GOTO init ; go to beginning of program

;--- routine di interrupt ----------------------------

18In generale, con overflow si denomina il superamento delle capacita di sistema automatico di calcolo

(v. 0.20)

Page 84: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

74 3.8. TIMER ED INTERRUZIONI

ORG 0x004 ;

DECF cont1,1 ; decrementa il contatore

MOVLW 0x0B ; carica 0x0BDB in TMR1

MOVWF TMR1H

MOVLW 0xDB

MOVWF TMR1L

BTFSC PORTC,4

GOTO intsp

BSF PORTC, 4 ; RC3 alto

GOTO endint

intsp BCF PORTC, 4 ; RC3 basso

endint BCF PIR1,TMR1IF

RETFIE

;--- inizializzazione sistema ------------------------

ORG 0x020 ;

init MOVLW 0x7 ; imposta PORTA I/O digitali

BSF STATUS, 0x5

BCF STATUS, 0x6

MOVWF ADCON0

BCF STATUS, 0x5

MOVLW 0x30 ; inizializza PORTA

TRIS PORTA

BCF PORTA, 1 ; buzzer off

MOVLW 0xF7 ; fase di inizializzazione del micro

TRIS PORTC ; poni RC3 come uscita

BCF led,0

BCF PORTC, 3 ; RC3 basso

MOVLW 0x30 ; presc.1/8,

MOVWF T1CON

BSF INTCON,7

BSF INTCON,6

BSF STATUS,5

BSF PIE1,0

BCF STATUS,5

MOVLW 0x0B ; carica 0x0BDB in TMR1

MOVWF TMR1H

MOVLW 0xDB

MOVWF TMR1L

BSF T1CON,0 ; abilita il Timer 1

;--- loop continuo -----------------------------------

loop MOVLW 0x0A ; carica 10 in cont1

MOVWF cont1

loop1 MOVLW 0x00 ; attendi che cont1 si azzeri

XORWF cont1,0

BTFSS 3,2

GOTO loop1

BTFSC led,0

GOTO spegni

BSF led,0

(v. 0.20)

Page 85: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 75

BSF PORTC, 3 ; RC3 alto

GOTO loop

spegni BCF led,0

BCF PORTC, 3 ; RC3 basso

GOTO loop

END ; directive ’end of program’

(v. 0.20)

Page 86: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

76 3.9. DOMANDE

3.9 Domande

1. Qual’e la principale differenza fra le architetture Harvard e Von Neumann.

2. Che tipo di architettura e implementata nel PIC16F876 ?

3. Quali tipi di memoria sono presenti all’interno del PIC 16F876 ?

4. Qual’e la dimensione del registro Program Counter nel PIC 16F876? Perche?

5. Con un quarzo da 16 Mhz in quanto tempo il PIC16F876 esegue le due seguenti istruzioni

MOVLW 16h

MOVWF 05h

(a) 1 ms

(b) 400 ns

(c) 0, 5µs

(d) 250 ns

6. Con quale di queste istruzioni si carica nel registro PORTB un dato ?

(a) BCF 05h, 2

(b) MOVWF 06h

(c) TRIS 06h

(d) NOP

7. Il PIC 16F876 di quanti ingressi analogici AD e dotato ?

(a) 4

(b) 5

(c) 6

(d) 7

8. L’espressione ORG 0x30 e:

(a) una direttiva

(b) una istruzione

(c) un’etichetta

(d) un indirizzo

9. Quale di questi tipi di memoria non e utilizzato all’interno dei microcontrollori ?

(a) Flash;

(b) Dinamic RAM;

(c) EEPROM;

(d) Static RAM.

10. Quali informazioni contiene il registro PC presente all’interno dei microcontrollori ?

(a) le informazioni relative allo stato del processore;

(b) la prossima istruzione da eseguire;

(c) il dato generato dalla istruzione in fase di esecuzione;

(d) l’indirizzo della prossima istruzione da eseguire.

(v. 0.20)

Page 87: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

CAPITOLO 3. I MICROCONTROLLORI PIC 77

3.10 Esercizi

1. Configurare tutte le linee del port B come ingressi e leggere il port B caricando nell’accu-mulatore il valore letto.

2. Configurare le cinque linee del port A come ingressi e le corrispondenti linee del port B comeuscite. Leggere il contenuto del port A e replicarlo nel port B.

3. Scrivere un programma che imposta come uscite le linee RB7-RB0 del port A ed inviare adesse prima il byte A5h e poi il byte 5Ah.

4. Scrivere un programma che generi, per un tempo indefinito, un’onda rettangolare con dutycicle pari al 50% e frequenza pari a 100 kHz. Si supponga di avere a disposizione un quarzoda 16 MHz.

5. Dato il seguente programma rispondere alle seguenti domande determinare:

(a) il numero di word occupate nella memoria di programma (giustificare la risposta);

(b) il codice oggetto prodotto dalle righe da 1 a 10;

(c) la durata della routine delay ipotizzando di utilizzare un quarzo da 4 MHz;

(d) la funzione svolta dal programma.

list p=16f877 ;1

#include <p16f877.inc> ;2

count1 EQU 0x20 ;3

count2 EQU 0x21 ;4

ORG 0x000 ;5

CLRF PCLATH ;6

GOTO init ;7

ORG 0x010 ;8

init BSF STATUS, 5 ;9

BCF STATUS, 6 ;10

MOVLW 0xff ;11

MOVWF PORTB ;12

CLRF PORTD ;13

BCF STATUS, 5 ;14

loop MOVFW PORTB ;15

MOVWF PORTD ;16

CALL delay ;17

GOTO loop ;18

delay MOVLW 0x19 ;19

MOVWF count1 ;20

cicle1 MOVLW 0x84 ;21

MOVWF count2 ;22

cicle2 DECFSZ count2, 1 ;23

GOTO cicle2 ;24

DECFSZ count1, 1 ;25

GOTO cicle1 ;26

RETURN ;27

END ;28

(v. 0.20)

Page 88: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

78 3.10. ESERCIZI

(v. 0.20)

Page 89: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Capitolo 4

ARGOMENTI AVANZATI

4.1 Multitasking

79

Page 90: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

80 4.1. MULTITASKING

(v. 0.20)

Page 91: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Appendice A

Set di istruzioni del PIC 16F87X

La famiglia mid-range di microcontrollori PIC utilizza un set di istruzioni lungo 14 bit [2]. Questoset prevede 36 istruzioni. Molte di queste istruzioni operano con l’accumulatore ed un file register.

Tabella A.1: Operazioni orientate al BIT con i file register

BCF Bit Clear fSintassi: BCF f,bOperandi: 0 ≤ f ≤ 127

0 ≤ b ≤ 7Operazione: 0 → (f < b >)Flag: NessunoDescrizione: Pone a 0 il bit b di f

BSF Bit Set fSintassi: BSF f,bOperandi: 0 ≤ f ≤ 127

0 ≤ b ≤ 7Operazione: 1 → (f < b >)Flag: NessunoDescrizione: Pone a 1 il bit b di f

81

Page 92: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

82

Tabella A.2: Operazioni orientate al BYTE con i file register

CLRF Clear fSintassi: CLRF fOperandi: 0 ≤ f ≤ 127Operazione: 00h → (f < b >)

1 → Z

Flag: ZDescrizione: Pone a 0 tutti i bit b di f

DECFSZ Decrement f, Skip if 0Sintassi: [etichetta] DECFSZf, d

Operandi: 0 ≤ f ≤ 127d ∈ [0, 1]

Operazione: (f) − 1 → (destination)Flag: NessunoDescrizione: Decrementa il registro f, se d=1 il risultato viene posto in f, se d=0

il risultato viene posto in W. Se a seguito del decremento il registro fdiventa zero viene saltata l’istruzione successiva e sostituita con unaistruzione NOP

MOVWF Carica W in FSintassi: [etichetta] MOV WFf

Operandi: 0 ≤ f ≤ 255Operazione: (W ) → (f)Flag: nessunoDescrizione: Copia il contenuto dell’accumulatore nel registro identificato da f

NOP No OperationSintassi: [etichetta] NOP

Operandi: nessunoOperazione: nessunaFlag: nessunoDescrizione: Non svolge alcuna operazione. E’ comunemente utilizzata per

introdurre un ritardo pari ad un ciclo macchina.

(v. 0.20)

Page 93: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

APPENDICE A. SET DI ISTRUZIONI DEL PIC 16F87X 83

Tabella A.3: Operazioni di controllo e con letterali

CALL Call SubroutineSintassi: [< etichetta >] CALLk

Operandi: 0 ≤ k ≤ 2047Operazione: k → PC < 0 : 10 >

PCLATH < 4 : 3 >→ PC < 12 : 11 >

Flag: nessunoDescrizione: Dapprima, l’indirizzo di ritorno (PC+1) e caricato (pushed) nello

stack. Poi, gli 11 bit indicati da k vengono caricati nel PC e i bit4 e 3 del registro PCLATH vengono caricati rispettivamente nei bit12 e 11 del PC.

CLRWDT Clear Watchdog TimerSintassi: [< etichetta >] CRWDT

Operandi: nessunoOperazione: 00h → WDT

0 → WDT prescaler

1 → TO

1 → PD

Flag: TO PD

Descrizione: Resetta il Watchdog Timer e il suo prescaler

GOTO Salto non condizionatoSintassi: [< etichetta >] GOTOk

Operandi: 0 ≤ k ≤ 2047Operazione: k → PC < 0 : 10 >

PCLATH < 4 : 3 >→ PC < 12 : 11 >

Flag: nessunoDescrizione: gli 11 bit indicati da k vengono caricati nel PC e i bit 4 e 3 del registro

PCLATH vengono caricati rispettivamente nei bit 12 e 11 del PC.

MOVLW Carica un valore nell’accumulatoreSintassi: [< etichetta >] MOV LWk

Operandi: 0 ≤ k ≤ 255Operazione: k → (W )Flag: nessunoDescrizione: Gli 8 bit indicati da k vengono caricati nell’accumulatore.

RETURN Return from SubroutineSintassi: [< etichetta >] RETURN

Operandi: nessunoOperazione: TOS → PC

PCLATH < 4 : 3 >→ PC < 12 : 11 >

Flag: nessunoDescrizione: L’indirizzo di ritorno dalla subroutine e prelevato (POPed) dalla ci-

ma dello stack1 e caricato nel PC. Questa istruzione dura due ciclimacchina.

(v. 0.20)

Page 94: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

84

(v. 0.20)

Page 95: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Appendice B

DIRETTIVE DEL PIC 16F87X

Le direttive sono istruzioni all’assemblatore presenti nel codice sorgente ma che non vengonotradotte in codice binario. Esse sono utilizzate per istruire l’assemblatore riguardo alla allocazionedel codice, al formato dell’output, ecc.

Le direttive sono suddivise in cinque categorie:

• Control

• Data

• Listing

• Macro

• ObjectFile

Ci soffermeremo solo sulle direttive piu comuni.

ORG Set Program OriginSintassi: [< etichetta >] org < espressione > +Descrizione: Imposta l’origine del programma all’indirizzo

definito con espressione

85

Page 96: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

86

(v. 0.20)

Page 97: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Bibliografia

[1] A.Kelley, I.Pohl, C didattica e programmazione, Pearson Education (2004)

[2] AAVV, PIC16F87X Data Sheet Microchip Technology Inc. (2001)

[3] A.De Santis, M.Cacciaglia, C.Saggese, Corso di Sistemi, Vol.2, Calderini Edagricole (2001)

[4] D.Martello, Introduzione al C, http://www.fisica.unile.it/ martello/corsi/Informatica/index.html (2003)

87

Page 98: PROGRAMMARE I MICROCONTROLLORI versione 0digidownload.libero.it/friuliweb/didattica/microcontrollori_0-20.pdf · Capitolo 1 I MICROCONTROLLORI Obiettivi didattici • Conoscere l’architettura

Indice analitico

codice- macchina, 10oggetto, 10sorgente, 10

codice macchina, 4compilatore

cross -, 11installazione cross -, 67

88