Area SX srl - Informatica e Microelettronica
0
Torna a: Home Page Soluzioni Microcontrollori Rabbit Introduzione al linguaggio C

Introduzione al linguaggio C

Data di pubblicazione: 17-10-2003 | Versione Italiana  | (No English Version)The English version of this article does not exists
Parole chiave: - How-To - Rabbit -


Modulo Rabbit RCM2200

I concetti di programmazione C introdotti in questo corso sono validi per tutte le versioni di Dynamic C ad eccezione di alcuni esempi, orientati alla gestione delle reti, per i quali non sono presenti le librerie nelle versioni di kit di sviluppo per Rabbit sprovvisti di connessione Ethernet.

Prerequisiti

In questa lezione, ed in quelle che verranno pubblicate sucessivamente, diamo per scontato che abbiate già installato l'ambiente di sviluppo Dynamic C sul vostro PC e che abbiate collegato correttamente un Rabbit Core + Scheda di sviluppo SX01 al programmatore seriale.

Chi non l'avesse fatto può accedere al seguente articolo:

  • Installazione SDK Rabbit RCM2200
    In questo articolo viene illustrata l'installazione e la prima prova di funzionamento del Kit di sviluppo per i moduli RCM2200 della Rabbit Semiconductor. L'articolo fà riferimento all'uso del Kit congiuntamente alla scheda per prototipi SX01

Scriviamo il nostro primo programma in C

Lanciamo il Dynamic C e creiamo un nuovo file sorgente in C selezionando la voce di menu:

  File -> New

Scriviamo quindi il seguente codice:

  main() {
    printf("Ciao mondo !");
  }

Lanciamo quindi in esecuzione il programma selezionando dal menu la voce:

  Run -> Run

Il programma verrà compilato ed il codice binario ottenuto sarà inviato direttamente al micro Rabbit presente sul core module tramite il programmatore connesso alla porta seriale del PC. Terminato il trasferimento del codice il Rabbit verrà resettato ed il codice eseguito direttamente sul micro.

Il risultato sarà il seguente:


Figura 1: La schermata standard output di un programma in esecuzione su Rabbit

Quella che abbiamo appena lanciato in esecuzione è probabilmente una delle forme più semplici di programma scritte in C, ma in essa ci sono già una serie di concetti importanti che vanno chiariti prima di proseguire.

La funzione main()

Qualsiasi parte di codice eseguibile scritta in C va inserita all'interno di una funzione.

Una funzione consiste in una collezione di istruzioni che il micro deve eseguire. Per poter iniziare ad eseguire qualcosa il C si aspetta di trovare un funzione di partenza di nome "main" (dall'inglese "principale").

Per raccogliere delle istruzioni all'interno di una funzione dobbiamo specificare il nome della funzione stessa seguito da una coppia di parentesi tonde:

  main()

Quindi una coppia di parentesi graffe in cui inserire tutte le istruzioni che compongono la funzione:

  main() {
  }

L'uso degli spazi a inizia riga (indentazione) semplifica la lettura di un programma in C, ma sono solo fortemente consigliati, non obbligatori.

Lo stesso codice è assolutamente valido se scritto nelle seguenti forme:

  main() {}

oppure

  main()
  {
  }

e cosi via. In pratica in C non ha molta importanza, il più delle volte, la presenza di spazi o carriage return tra le diverse istruzioni e direttive del linguaggio.

Una funzione può contenere a sua volta chiamate ad altre funzioni che a loro volta possono contenerne delle altre.

Nel nostro caso con:

  main() {
    printf("Ciao mondo !");
  }

Viene richiamata all'interno della funzione main(), la funzione print() il cui compito è quello di inviare stringhe di caratteri sulla stdio ovvero sulla consolle predefinita che corrisponde nel Dynamic C nella finestra stdio.c riportata in figura 1.

La funzione printf() accetta dei parametri che devono essere inseriti all'interno delle parentesi tonde. In questo caso si tratta della stringa "Ciao mondo !" da inviare sulla finestra standard stdio.

Le variabili

Proviamo ora a inserire delle variabili con cui fare due conti all'interno del nostro programma.

Premiamo il pulsante EDIT sotto la barra dei menu e modifichiamo il nostro programma così:

  main() {
    int i;

    i=100;
    printf("La variabile i vale %d",i);
  }

Lanciamo in esecuzione il programma. Quello che otterremo è riportato nella figura seguente:


Figura 2: Visualizzazione del valore della variabile i

In pratica quello che abbiamo fatto è stato inserire un definizione per una nuova variabile con la riga:

  int i;

Dove int indica il tipo di variabile. In questo caso un intero con segno a 16 bit in grado quindi di memorizzare valori numerici compresi nell'intervallo da -32768 a +32767.

L'intervallo minimo e massimo del valore numerico che è possibile inserire in una variabile di tipo int deriva appunto dalla sua dimensione di 16 bit. Con 16 bit è possibile rappresentare valori a zero a 2 elevato alla sedicesima ovvero 65535. Utilizando un bit di questi 16 per memorizzare il segno i numero minimi e massimi diventano quelli indicati.

Se avessimo specificato la variabile come unsigned int avremmo rinunciato al segno (da cui il prefisso unsigned) e quindi a tutti i valori negativi ma aumentato l'intervallo di valori positivi possibili da +32767 a +65535.

Esistono altri tipo di variabili in C che consentono di memorizzare valori diversi. Nella figura 4, estratta dal manuale ufficiale del Dynamic C, riportiamo le tipologie di variabili possibili.


Tavola 1: Tipi di dati gestiti dal Dynamic C

La riga:

  i=100;

Assegna il valore 100 alla variabile i.

La riga:

  printf("La variabile i vale %d",i);

Visualizza il valore sulla consolle stdio. La funzione printf() in questo caso accetta due parametri separati da una virgola. Il primo parametro è una stringa in cui possono essere inserire delle parti di frase statiche e dei formattatori.

Per distinguere un formattatore dal resto del testo viene utilizzato il carattere %. In questo caso %d significa: "Sostituisci %d con il valore decimale contenuto nella variabile i".

Il numero di variabili accettate dalla printf() oltre la stringa di formattazione dipende dal numero di formattatori presenti.

Volendo rappresentare lo stesso numero sia come valore decimale che esadecimale potremo scrivere:

  printf("La variabile i vale %d dec [%x hex]",i,i);

per ottenere in uscita:

  La variabile i vale 100 dec [64 hex]

Di seguito viene riportato l'elenco dei possibili formattatori riconosciuti dalla printf():

  %d intero decimale (si usa con le variabili di tipo int)
  %u intero decimale senza segno (si usa con le variabili di tipo unsigned int)
  %x intero esadecimale (si usa con le variabili int o unsigned int)
  %s stringa (Si usa con le stringhe)
  %f numeri con virgola (si usa con le variabili float)

Gli operatori condizionali

Il linguaggio C è un linguaggio di tipo procedurale, ovvero composto da una serie di istruzioni eseguite in sequenza dal microprocessore al fine di effettuare, appunto, una una procedura.

In molti casi, durante il regolare flusso del programma, è necessario poter scegliere tra diverse possibili opzioni all'interno della procedura o ripetere, per un determinato numero di volte, la stessa serie di istruzioni ciclicamente.

Per risolvere questo problema il programmatore ha a disposizione una serie di costrutti in grado di deviare il normale flusso sequenziale del microprocessore, vediamo quali sono.

L'ISTRUZIONE IF

L'istruzione if è la più classica delle istruzioni condizionali ed esiste praticamente per qualsiasi linguaggio di programmazione. Il suo formato più semplice è il seguente:

  if (espressione) {
    .. istruzioni da eseguire se l'espressione è vera
  }

In pratica se il risultato dell'espressione all'interno delle parentesi è vero viene eseguito il blocco di istruzioni tra parentesi graffe. In caso contrario se il risultato dell'espressione è falso il blocco tra le parentesi non viene eseguito.

La distinzione tra un valore vero e falso viene effettuata in C nella seguente maniera:

- E' vero un valore diverso da zero
- E' falso un valore pari a zero

Vediamo un esempio pratico:

  main() {
    int a;

    a=1;

    if (a) {
      printf("Vero\n");
    }

    if (!a) {
      printf("Falso\n");
    }
  }

Se eseguiamo il codice così come lo abbiamo scritto otterremo sulla consolle il messaggio "Vero" in quanto a vale 1 che viene considerato come un valore vero.

Se assegniamo alla variabile a uno dei seguenti valori -1, 10, -500, ecc. otterremo sempre il messaggio "Vero".

Assegnando invece ad a il valore 0 otterremo il messaggio "Falso". L'operatore ! (punto esclamativo) è infatti un operatore che nega il risultato dell'espressione alla sua destra per cui se a è falso !a è vero ed il codice tra la seconda coppia di parantesi graffe viene eseguito.

Un modo molto più elegante di scrivere lo stesso programma è il seguente:

  main() {
    int a;

    a=1;

    if (a) {
      printf("Vero\n");
    } else {
      printf("Falso\n");
    }
  }

Ovvero "se" a è vero, esegui il primo blocco di istruzioni, "altrimenti" esegui il secondo blocco.

Ovviamente l'espressione tra parentesi tonde può essere anche più complessa e prevedere un controllo per uno specifico valore di a. Ad esempio:

  main() {
    int a;

    a=54;

    if (a==54) {
      printf("Vero\n");
    } else {
      printf("Falso\n");
    }
  }

In questo caso abbiamo usato l'operatore == (doppio uguale) che genera appunto un valore vero o falso dopo aver comparato due valori.

Da notare come sia diverso l'uso dell'operatore di comparazione == da quello di assegnazione = (singolo uguale).

= assegna alla variabile sulla sinistra il valore sulla destra
== compara il valore di sinistra con quello di destra ma non effettua alcuna assegnazione

La comparazione può essere effettuata naturalmente anche tra due variabili. Ad esempio:

  main() {
    int a;
    int b;

    a=54;
    b=53;

    if (a==b) {
      printf("Vero\n");
    } else {
      printf("Falso\n");
    }
  }

Con questo esempio viene visualizzato il messaggio "Falso" in quanto a è diverso da b.

E' possibile effettuare più controlli in cascata per aumentare il numero di derivazioni del programma. Ad esempio:

  main() {
    int a;
    int b;

    a=54;
    b=54;

    if (a==b) {
      printf("A uguale a B\n");
    } else if (a>b) {
      printf("A maggiore di B\n");
    } else if (a‹b) {
      printf("A minore di B\n");
    }
  }

Esiste anche la possibilità di effettuare dei salti in punti diversi del programma tramite l'istruzione goto. Questo metodo è assolutamente sconsigliato in quanto potrebbe rendere un programma complesso assolutamente illeggibile, ma spesso può rappresentare una valida soluzione per accellerare i tempi di sviluppo di un programma. Vediamo come modificare l'esempio precedente usando l'istruzione goto:

  main() {
    int a;
    int b;

    a=54;
    b=54;

    if (a==b) goto Uguale;
    if (a>b)  goto Maggiore;
    if (a‹b)  goto Minore;

  Uguale:
    printf("A uguale a B\n");
    exit(0);

  Maggiore:
    printf("A maggiore di B\n");
    exit(1);

  Minore:
    printf("A minore di B\n");
    exit(2);
  }

In questo esempio ci sono una serie di novità da comprendere. Anzitutto il formato della funzione goto. La goto consente di far saltare il programma in un punto diverso del sorgente. Il punto in cui andare è identificato da una label (etichetta) costituita da un nome seguito da due punti (:). Nell'esempio le label sono Uguale:, Maggiore: e Minore: e vanno specificate (senza i due punti) di seguito all'istruzione goto.

In ognuna delle if utilizzate non è stata inserita la coppia di parentesi graffe. Questo perché l'istruzione da eseguire all'interno della if è una sola. Nel caso di debbano eseguire più istruzioni è obbligatorio inserire le parentesi graffe.

La funzione exit(0) consente di uscire immediatamente dal programma e ridare il controllo al Dynamic C. Il numero tra parentesi è un codice di errore che possiamo passare al Dynamic C per indicare una eventuale condizione d'errore.

Il valore verrà visualizzato con una message box come riportato in figura 3.


Figura 3: Codice d'errore in uscita

L'ISTRUZIONE SWITCH

L'istruzione switch consente sempre di selezionare porzioni di codice da eseguire in base al valore che assume una espressione in una forma leggermente diversa. Vediamo un esempio:

  main() {
    int a;

    a=54;

    switch(a) {

    case 0:
      printf("A uguale a zero\n");
      break;

    case 1:
      printf("A uguale a uno\n");
      break;

    case 2:
      printf("A uguale a due\n");
      break;

    default:
      printf("Altro valore\n");
      break;

    }
  }

La switch valuta il valore dell'espressione tra parantesi tonde (in questo caso il valore della variabile a) e lo confronta con diverse costanti numeriche tramite l'istruzione case. Quando trova una costante numerica uguale al risultato dell'espressione esegue il codice che segue la case. L'istruzione break serve ad uscire dalla switch ed evitare che venga eseguito il codice al di sotto delle case successive.

L'istruzione default è opzionale e il codice specificato dopo di essa viene eseguito solo se l'espressione non è uguale a nessuno dei valori specificati.

Segnala questo articolo: 



Parole chiave: - How-To - Rabbit -

Data di pubblicazione: 17-10-2003Hits: 35421
I marchi citati sono propriet� dei titolari dei relativi diritti. Le caratteristiche tecniche e i prezzi riportati sono indicativi e soggetti a variazioni senza preavviso. Le foto non hanno valore contrattuale. Nonostante accurate verifiche, il presente documento pu� contenere prezzi o specifiche errati. Area SX si scusa in anticipo e si impegna ad evitare tali imprecisioni.

 Area SX store
In questa sezione puoi ordinare direttamente i prodotti descritti in questo articolo
R101-0478;SX01
Tutti i prezzi indicati sono espressi in Euro con IVA e spese di trasporto escluse. I prezzi si riferiscono al singolo pezzo
DescrizioneCodicePrezzo

Rivenditori Social Contatti Condizioni
Area SX s.r.l
Via Stefano Longanesi 25
00146 Roma

Tel: +39.06.99.33.02.57
Fax: +39.06.62.20.27.85
P.IVA 06491151004
Condizioni di vendita
Procedura di rientro in garanzia
Condizioni per i rivenditori