Next: Acquisizione e grafico dei
Up: Gestione di un oscilloscopio
Previous: EXIT
Dopo aver compilato e fatto partire l'emulatore, per verificare che
funzioni correttamente bisogna riuscire a comunicare attraverso l'interfaccia
seriale.
Qualunque ambiente di sviluppo di codice per acquisizione dati fornisce
delle interfacce di alto livello per la comunicazione con i protocolli
più comuni. Questo laboratorio non fa eccezione ed insieme ai file
distribuiti con l'emulatore c'è un file serial.c (ed il relativo
serial.h) che contiene le funzioni necessarie per dialogare
utilizzando la porta seriale: viene definita una struttura serialport
che contiene tutti i parametri necessari per accedere ad una porta
ed inizializzarla correttamente e poi vengono implementate delle funzioni
che operano su puntatori serialport* per aprire, chiudere,
leggere da e scrivere su porte seriali.
Tali funzioni sono:
- serialport* OpenSerial(const char* deviceName)
che inizializza una porta seriale. Come argomento vuole una stringa
con il nome del file (in Linux tutte le device sono dei file) corrispondente
alla porta seriale. ``/dev/ttyS0'' e ``/dev/ttyS1''
sono i nomi possibili. Il valore di ritorno è un puntatore ad una
struttura serialport con i dati della porta cosí aperta.
Se non si riesce ad aprire la porta, il puntatore restituito è nullo.
- void CloseSerial(serialport* port)
chiude correttamente la porta.
- int WriteSerial(serialport* port, const char*
buffer)
invia una stringa alla porta seriale. il valore di ritorno è la dimensione
della stringa scritta sulla porta seriale.
- int ReadSerial(serialport* port, char* buffer)
legge dalla porta seriale e mette il risultato nella stringa buffer.
Tale stringa deve essere già dimensionata nel programma che usa la
funzione e deve essere di dimensione MAXBUFFERSIZE. Il valore
di ritorno è la dimensione della stringa letta, o 0 se non viene letto
niente dalla porta seriale durante SERIAL_TIMEOUT secondi.
Entrambi i valori di MAXBUFFERSIZE e SERIAL_TIMEOUT
sono definiti in serial.h.
Per poter usare queste funzioni non è necessario vederne l'implementazione
in serial.c, ma dovrebbe essere sufficiente l'informazione
presente nell'header file.
Realizzare un programma che permetta di comunicare interattivamente
con l'emulatore, seguendo lo schema:
- Aprire la porta COM1 (/dev/ttyS0).
- Leggere una riga di comando da terminale.
- Inviare la stringa alla porta seriale.
- Provare a leggere indietro una risposta dalla porta seriale: se si
ottiene una risposta dallo strumento, stamparla su terminale, altrimenti
mandare un avviso che non si è osservato niente durante il perido
di attesa SERIAL_TIMEOUT.
- ripetere i passi da 2 a 4 fino a quando non viene digitato un Ctrl-d.
- Chiudere la porta seriale ed uscire dal programma.
Una complicazione rispetto agli altri esercizi che abbiamo fatto è
che non sappiamo a priori come è fatta la linea da leggere: potrebbere
essere un comando solo, comando più argomento, o addirittura più comandi
concatenati. Quindi, anziché usare uno scanf, conviene usare la funzione
delle standard libraries
int getline(char **line, int *n, FILE *input)
che appunto legge un'intera linea e la mette in una stringa allocata
dinamicamente con un malloc. All'uscita della chiamata, *line
è un puntatore all'inizio della zona di memoria allocata con malloc,
n contiene la dimensione di questa zona di memoria ed il
valore di ritorno è il numero di caratteri che effettivamente compongono
la stringa letta, o -1 in caso di errore. Bisogna poi anche ricordare
che lo standard input non è altro che un FILE* un po' speciale:
si chiama stdin ed è dichiarato in stdio.h.
Quello che segue è un programma di esempio che usa getline per leggere
una riga e ristamparla sullo schermo: dovrebbe essere sufficiente
adattarlo un po' per aggiungere la parte di comunicazione attraverso
le funzioni in serial.h:
-
- #include <stdlib.h>
#include <stdio.h>
int main() {
char *riga=0;
int dim=0;
int letti;
while ( (letti=getline(&riga,&dim,stdin))!=-1 )
printf("Letti %d caratteri:\n==%s==\n",letti,riga);
return 0;
}
Utilizzare il programma cosí costruito per verificare che si è in
grado di ricevere l'informazione dall'oscilloscopio e verificare il
formato con cui vengono restituiti i dati. Quando si devono leggere
i dati di una forma d'onda bisogna avere un attimo di pazienza: quanto
tempo ci vuole per leggere una stringa di 10000 caratteri a 9600 baud
(bit per secondo), che è la velocità di trasmissione dell'oscilloscopio?
Siccome la risposta del circuito ad una forzante è calcolata tramite
l'integrazione di un'equazione differenziale di una funzione d'onda,
se si chiede di integrare su un tempo troppo lungo, potrebbe essere
che il vostro programma vada in time out mentre l'emulatore sta facendo
i suoi calcoli. Siccome la velocità di calcolo dipende molto dalla
CPU e dalla configurazione del PC, provate a vedere qual è
la lunghezza di tempo massima per cui si riesce ad integrare (per
acquisire una funzione d'onda, l'emulatore deve integrare per almeno
10 volte il valore di s/div dato con HORIZONTAL:MAIN:SCALE,
quindi basterà variare questo parametro).
Next: Acquisizione e grafico dei
Up: Gestione di un oscilloscopio
Previous: EXIT
Attilio Andreazza
2003-05-07